From 8d02403622de6047550b7a872ed7f4c717ea4d8a Mon Sep 17 00:00:00 2001 From: euda Date: Sun, 10 May 2015 01:52:28 +0900 Subject: [PATCH] First commit: Nothing changed from original netatalk v.3.1.7, Completely same as originaly distributed --- AUTHORS | 106 + CONTRIBUTORS | 120 + COPYING | 340 + COPYRIGHT | 46 + Makefile.am | 25 + Makefile.in | 912 + NEWS | 1541 ++ VERSION | 1 + abigen.sh | 21 + aclocal.m4 | 2082 +++ bin/Makefile.am | 7 + bin/Makefile.in | 707 + bin/ad/Makefile.am | 24 + bin/ad/Makefile.in | 844 + bin/ad/ad.c | 90 + bin/ad/ad.h | 85 + bin/ad/ad_cp.c | 1020 ++ bin/ad/ad_find.c | 176 + bin/ad/ad_ls.c | 687 + bin/ad/ad_mv.c | 444 + bin/ad/ad_rm.c | 321 + bin/ad/ad_set.c | 330 + bin/ad/ad_util.c | 304 + bin/afppasswd/Makefile.am | 20 + bin/afppasswd/Makefile.in | 709 + bin/afppasswd/afppasswd.c | 354 + bin/cnid/Makefile.am | 7 + bin/cnid/Makefile.in | 590 + bin/cnid/cnid2_create.in | 361 + bin/megatron/Makefile.am | 4 + bin/megatron/Makefile.in | 519 + bin/misc/Makefile.am | 23 + bin/misc/Makefile.in | 779 + bin/misc/fce.c | 202 + bin/misc/logger_test.c | 112 + bin/misc/netacnv.c | 105 + bin/misc/uuidtest.c | 155 + compile | 347 + config.guess | 1537 ++ config.h.in | 761 + config.sub | 1789 ++ config/Makefile.am | 73 + config/Makefile.in | 822 + config/README | 1 + config/afp.conf.tmpl | 12 + config/dbus-session.conf.tmpl | 45 + config/extmap.conf | 308 + config/netatalk-dbus.conf | 17 + config/pam/Makefile.am | 19 + config/pam/Makefile.in | 587 + config/pam/netatalk.tmpl | 5 + configure | 22726 ++++++++++++++++++++++++ configure.ac | 327 + contrib/Makefile.am | 3 + contrib/Makefile.in | 706 + contrib/macusers/Makefile.am | 5 + contrib/macusers/Makefile.in | 590 + contrib/macusers/README.macusers | 4 + contrib/macusers/macusers.in | 134 + contrib/shell_utils/Makefile.am | 23 + contrib/shell_utils/Makefile.in | 609 + contrib/shell_utils/afpstats | 29 + contrib/shell_utils/apple_dump.in | 915 + contrib/shell_utils/asip-status.pl.in | 557 + contrib/shell_utils/fce_ev_script.sh | 62 + contrib/shell_utils/make-casetable.pl | 324 + contrib/shell_utils/make-precompose.h.pl | 260 + depcomp | 787 + distrib/Makefile.am | 3 + distrib/Makefile.in | 706 + distrib/config/Makefile.am | 3 + distrib/config/Makefile.in | 589 + distrib/config/netatalk-config.in | 233 + distrib/initscripts/Makefile.am | 235 + distrib/initscripts/Makefile.in | 797 + distrib/initscripts/netatalk.xml.tmpl | 51 + distrib/initscripts/rc.bsd.tmpl | 13 + distrib/initscripts/rc.debian.tmpl | 67 + distrib/initscripts/rc.gentoo.tmpl | 14 + distrib/initscripts/rc.netbsd.tmpl | 19 + distrib/initscripts/rc.redhat.tmpl | 95 + distrib/initscripts/rc.solaris.tmpl | 60 + distrib/initscripts/rc.suse.tmpl | 60 + distrib/initscripts/service.systemd.tmpl | 19 + distrib/m4/Makefile.am | 6 + distrib/m4/Makefile.in | 574 + distrib/m4/netatalk.m4 | 158 + doc/Makefile.am | 9 + doc/Makefile.in | 717 + doc/html.xsl.in | 13 + doc/man.xsl.in | 26 + doc/manpages/Makefile.am | 1 + doc/manpages/Makefile.in | 704 + doc/manpages/man1/Makefile.am | 40 + doc/manpages/man1/Makefile.in | 551 + doc/manpages/man1/ad.1.xml | 402 + doc/manpages/man1/afpldaptest.1.xml | 97 + doc/manpages/man1/afppasswd.1.xml | 151 + doc/manpages/man1/afpstats.1.xml | 50 + doc/manpages/man1/apple_dump.1.xml | 182 + doc/manpages/man1/asip-status.pl.1.xml | 162 + doc/manpages/man1/dbd.1.xml | 132 + doc/manpages/man1/macusers.1.xml | 75 + doc/manpages/man1/megatron.1.xml | 143 + doc/manpages/man1/netatalk-config.1.xml | 163 + doc/manpages/man1/uniconv.1.xml | 227 + doc/manpages/man5/Makefile.am | 26 + doc/manpages/man5/Makefile.in | 537 + doc/manpages/man5/afp.conf.5.xml | 2297 +++ doc/manpages/man5/afp_signature.conf.5.xml | 87 + doc/manpages/man5/afp_voluuid.conf.5.xml | 88 + doc/manpages/man5/extmap.conf.5.xml | 79 + doc/manpages/man8/Makefile.am | 26 + doc/manpages/man8/Makefile.in | 537 + doc/manpages/man8/afpd.8.xml | 259 + doc/manpages/man8/cnid_dbd.8.xml | 270 + doc/manpages/man8/cnid_metad.8.xml | 129 + doc/manpages/man8/netatalk.8.xml | 96 + doc/manual/Makefile.am | 63 + doc/manual/Makefile.in | 576 + doc/manual/configuration.xml | 1931 ++ doc/manual/install.xml | 362 + doc/manual/intro.xml | 15 + doc/manual/manual.xml.in | 116 + doc/manual/netatalk.html | 14 + doc/manual/upgrade.xml | 1540 ++ etc/Makefile.am | 3 + etc/Makefile.in | 706 + etc/afpd/Makefile.am | 101 + etc/afpd/Makefile.in | 1345 ++ etc/afpd/acl_mappings.h | 105 + etc/afpd/acls.c | 1795 ++ etc/afpd/acls.h | 120 + etc/afpd/afp_config.c | 236 + etc/afpd/afp_config.h | 11 + etc/afpd/afp_dsi.c | 713 + etc/afpd/afp_options.c | 253 + etc/afpd/afp_util.c | 160 + etc/afpd/afprun.c | 320 + etc/afpd/afpstats-service.xml | 8 + etc/afpd/afpstats.c | 122 + etc/afpd/afpstats.h | 23 + etc/afpd/afpstats_obj.c | 110 + etc/afpd/afpstats_obj.h | 19 + etc/afpd/afpstats_service_glue.h | 121 + etc/afpd/afs.c | 319 + etc/afpd/appl.c | 503 + etc/afpd/auth.c | 1087 ++ etc/afpd/auth.h | 52 + etc/afpd/catsearch.c | 1094 ++ etc/afpd/desktop.c | 1056 ++ etc/afpd/desktop.h | 62 + etc/afpd/dircache.c | 697 + etc/afpd/dircache.h | 40 + etc/afpd/directory.c | 2637 +++ etc/afpd/directory.h | 149 + etc/afpd/enumerate.c | 511 + etc/afpd/extattrs.c | 522 + etc/afpd/extattrs.h | 24 + etc/afpd/fce_api.c | 632 + etc/afpd/fce_api_internal.h | 51 + etc/afpd/fce_util.c | 195 + etc/afpd/file.c | 2322 +++ etc/afpd/file.h | 136 + etc/afpd/filedir.c | 861 + etc/afpd/filedir.h | 27 + etc/afpd/fork.c | 1347 ++ etc/afpd/fork.h | 99 + etc/afpd/hash.c | 1095 ++ etc/afpd/hash.h | 73 + etc/afpd/icon.h | 46 + etc/afpd/main.c | 479 + etc/afpd/mangle.c | 287 + etc/afpd/mangle.h | 30 + etc/afpd/messages.c | 191 + etc/afpd/misc.h | 25 + etc/afpd/nfsquota.c | 174 + etc/afpd/ofork.c | 539 + etc/afpd/quota.c | 814 + etc/afpd/spotlight.c | 1454 ++ etc/afpd/spotlight_marshalling.c | 811 + etc/afpd/status.c | 656 + etc/afpd/status.h | 44 + etc/afpd/switch.c | 225 + etc/afpd/switch.h | 39 + etc/afpd/uam.c | 534 + etc/afpd/uam_auth.h | 67 + etc/afpd/uid.c | 12 + etc/afpd/uid.h | 8 + etc/afpd/unix.c | 288 + etc/afpd/unix.h | 227 + etc/afpd/volume.c | 1072 ++ etc/afpd/volume.h | 33 + etc/cnid_dbd/Makefile.am | 33 + etc/cnid_dbd/Makefile.in | 814 + etc/cnid_dbd/cmd_dbd.c | 309 + etc/cnid_dbd/cmd_dbd.h | 29 + etc/cnid_dbd/cmd_dbd_scanvol.c | 867 + etc/cnid_dbd/cnid_metad.c | 650 + etc/cnid_dbd/comm.c | 284 + etc/cnid_dbd/comm.h | 21 + etc/cnid_dbd/db_param.c | 198 + etc/cnid_dbd/db_param.h | 39 + etc/cnid_dbd/dbd.h | 28 + etc/cnid_dbd/dbd_add.c | 196 + etc/cnid_dbd/dbd_dbcheck.c | 54 + etc/cnid_dbd/dbd_delete.c | 91 + etc/cnid_dbd/dbd_get.c | 66 + etc/cnid_dbd/dbd_getstamp.c | 55 + etc/cnid_dbd/dbd_lookup.c | 316 + etc/cnid_dbd/dbd_rebuild_add.c | 83 + etc/cnid_dbd/dbd_resolve.c | 61 + etc/cnid_dbd/dbd_search.c | 51 + etc/cnid_dbd/dbd_update.c | 67 + etc/cnid_dbd/dbif.c | 1327 ++ etc/cnid_dbd/dbif.h | 114 + etc/cnid_dbd/main.c | 598 + etc/cnid_dbd/pack.c | 129 + etc/cnid_dbd/pack.h | 18 + etc/cnid_dbd/usockfd.c | 175 + etc/cnid_dbd/usockfd.h | 41 + etc/netatalk/Makefile.am | 34 + etc/netatalk/Makefile.in | 787 + etc/netatalk/afp_avahi.c | 335 + etc/netatalk/afp_avahi.h | 39 + etc/netatalk/afp_mdns.c | 349 + etc/netatalk/afp_mdns.h | 22 + etc/netatalk/afp_zeroconf.c | 48 + etc/netatalk/afp_zeroconf.h | 35 + etc/netatalk/netatalk.c | 475 + etc/spotlight/Makefile.am | 35 + etc/spotlight/Makefile.in | 830 + etc/spotlight/sparql_map.c | 136 + etc/spotlight/sparql_map.h | 53 + etc/spotlight/sparql_parser.c | 2060 +++ etc/spotlight/sparql_parser.h | 130 + etc/spotlight/sparql_parser.y | 370 + etc/spotlight/spotlight_rawquery_lexer.c | 1867 ++ etc/spotlight/spotlight_rawquery_lexer.l | 45 + etc/uams/Makefile.am | 144 + etc/uams/Makefile.in | 957 + etc/uams/uams_dhx2_pam.c | 968 + etc/uams/uams_dhx2_passwd.c | 634 + etc/uams/uams_dhx_pam.c | 760 + etc/uams/uams_dhx_passwd.c | 401 + etc/uams/uams_gss.c | 638 + etc/uams/uams_guest.c | 147 + etc/uams/uams_pam.c | 485 + etc/uams/uams_passwd.c | 384 + etc/uams/uams_pgp.c | 197 + etc/uams/uams_randnum.c | 570 + include/Makefile.am | 3 + include/Makefile.in | 706 + include/atalk/Makefile.am | 59 + include/atalk/Makefile.in | 692 + include/atalk/acl.h | 68 + include/atalk/adouble.h | 465 + include/atalk/afp.h | 215 + include/atalk/afp_dtrace.d | 10 + include/atalk/bstradd.h | 47 + include/atalk/bstrlib.h | 300 + include/atalk/byteorder.h | 217 + include/atalk/cnid.h | 122 + include/atalk/cnid_bdb_private.h | 71 + include/atalk/cnid_mysql_private.h | 20 + include/atalk/cnid_private.h | 74 + include/atalk/compat.h | 51 + include/atalk/dalloc.h | 39 + include/atalk/dictionary.h | 68 + include/atalk/directory.h | 103 + include/atalk/dsi.h | 210 + include/atalk/ea.h | 211 + include/atalk/errchk.h | 170 + include/atalk/fce_api.h | 134 + include/atalk/ftw.h | 109 + include/atalk/globals.h | 195 + include/atalk/hash.h | 179 + include/atalk/iniparser.h | 50 + include/atalk/ldapconfig.h | 57 + include/atalk/list.h | 165 + include/atalk/logger.h | 199 + include/atalk/netatalk_conf.h | 39 + include/atalk/paths.h | 17 + include/atalk/queue.h | 41 + include/atalk/server_child.h | 57 + include/atalk/server_ipc.h | 17 + include/atalk/spotlight.h | 128 + include/atalk/standards.h | 34 + include/atalk/talloc.h | 1711 ++ include/atalk/tdb.h | 181 + include/atalk/uam.h | 101 + include/atalk/unicode.h | 152 + include/atalk/unix.h | 55 + include/atalk/util.h | 227 + include/atalk/uuid.h | 41 + include/atalk/vfs.h | 127 + include/atalk/volume.h | 208 + install-sh | 527 + libatalk/Makefile.am | 126 + libatalk/Makefile.in | 952 + libatalk/acl/Makefile.am | 17 + libatalk/acl/Makefile.in | 719 + libatalk/acl/aclldap.h | 27 + libatalk/acl/cache.c | 362 + libatalk/acl/cache.h | 39 + libatalk/acl/ldap.c | 450 + libatalk/acl/ldap_config.c | 104 + libatalk/acl/unix.c | 515 + libatalk/acl/uuid.c | 304 + libatalk/adouble/Makefile.am | 19 + libatalk/adouble/Makefile.in | 690 + libatalk/adouble/ad_attr.c | 176 + libatalk/adouble/ad_conv.c | 293 + libatalk/adouble/ad_date.c | 44 + libatalk/adouble/ad_flush.c | 489 + libatalk/adouble/ad_lock.c | 660 + libatalk/adouble/ad_lock.h | 29 + libatalk/adouble/ad_mmap.c | 108 + libatalk/adouble/ad_open.c | 2086 +++ libatalk/adouble/ad_read.c | 100 + libatalk/adouble/ad_recvfile.c | 261 + libatalk/adouble/ad_sendfile.c | 106 + libatalk/adouble/ad_size.c | 33 + libatalk/adouble/ad_write.c | 284 + libatalk/bstring/Makefile.am | 6 + libatalk/bstring/Makefile.in | 662 + libatalk/bstring/bstradd.c | 206 + libatalk/bstring/bstrlib.c | 2956 +++ libatalk/cnid/Makefile.am | 29 + libatalk/cnid/Makefile.in | 802 + libatalk/cnid/README | 50 + libatalk/cnid/cdb/Makefile.am | 21 + libatalk/cnid/cdb/Makefile.in | 761 + libatalk/cnid/cdb/README | 35 + libatalk/cnid/cdb/cnid_cdb.h | 51 + libatalk/cnid/cdb/cnid_cdb_add.c | 292 + libatalk/cnid/cdb/cnid_cdb_close.c | 36 + libatalk/cnid/cdb/cnid_cdb_delete.c | 46 + libatalk/cnid/cdb/cnid_cdb_get.c | 50 + libatalk/cnid/cdb/cnid_cdb_lookup.c | 136 + libatalk/cnid/cdb/cnid_cdb_meta.c | 8 + libatalk/cnid/cdb/cnid_cdb_meta.h | 50 + libatalk/cnid/cdb/cnid_cdb_nextid.c | 28 + libatalk/cnid/cdb/cnid_cdb_open.c | 381 + libatalk/cnid/cdb/cnid_cdb_private.h | 125 + libatalk/cnid/cdb/cnid_cdb_rebuild_add.c | 140 + libatalk/cnid/cdb/cnid_cdb_resolve.c | 49 + libatalk/cnid/cdb/cnid_cdb_update.c | 104 + libatalk/cnid/cnid.c | 355 + libatalk/cnid/cnid_init.c | 96 + libatalk/cnid/dbd/Makefile.am | 6 + libatalk/cnid/dbd/Makefile.in | 661 + libatalk/cnid/dbd/cnid_dbd.c | 1043 ++ libatalk/cnid/dbd/cnid_dbd.h | 39 + libatalk/cnid/last/Makefile.am | 10 + libatalk/cnid/last/Makefile.in | 665 + libatalk/cnid/last/README | 4 + libatalk/cnid/last/cnid_last.c | 173 + libatalk/cnid/last/cnid_last.h | 31 + libatalk/cnid/mysql/Makefile.am | 6 + libatalk/cnid/mysql/Makefile.in | 674 + libatalk/cnid/mysql/cnid_mysql.c | 954 + libatalk/cnid/tdb/Makefile.am | 20 + libatalk/cnid/tdb/Makefile.in | 748 + libatalk/cnid/tdb/README | 35 + libatalk/cnid/tdb/cnid_tdb.h | 75 + libatalk/cnid/tdb/cnid_tdb_add.c | 210 + libatalk/cnid/tdb/cnid_tdb_close.c | 22 + libatalk/cnid/tdb/cnid_tdb_delete.c | 50 + libatalk/cnid/tdb/cnid_tdb_get.c | 40 + libatalk/cnid/tdb/cnid_tdb_lookup.c | 152 + libatalk/cnid/tdb/cnid_tdb_nextid.c | 17 + libatalk/cnid/tdb/cnid_tdb_open.c | 153 + libatalk/cnid/tdb/cnid_tdb_resolve.c | 37 + libatalk/cnid/tdb/cnid_tdb_update.c | 108 + libatalk/compat/Makefile.am | 11 + libatalk/compat/Makefile.in | 674 + libatalk/compat/getusershell.c | 136 + libatalk/compat/misc.c | 77 + libatalk/compat/mktemp.c | 119 + libatalk/compat/pselect.c | 81 + libatalk/compat/rquota_xdr.c | 122 + libatalk/compat/strlcpy.c | 74 + libatalk/dsi/Makefile.am | 9 + libatalk/dsi/Makefile.in | 676 + libatalk/dsi/README | 45 + libatalk/dsi/dsi_attn.c | 58 + libatalk/dsi/dsi_close.c | 30 + libatalk/dsi/dsi_cmdreply.c | 36 + libatalk/dsi/dsi_getsess.c | 125 + libatalk/dsi/dsi_getstat.c | 28 + libatalk/dsi/dsi_init.c | 33 + libatalk/dsi/dsi_opensess.c | 67 + libatalk/dsi/dsi_read.c | 64 + libatalk/dsi/dsi_stream.c | 640 + libatalk/dsi/dsi_tcp.c | 476 + libatalk/dsi/dsi_tickle.c | 38 + libatalk/dsi/dsi_write.c | 79 + libatalk/dummy.c | 0 libatalk/iniparser/Makefile.am | 7 + libatalk/iniparser/Makefile.in | 665 + libatalk/iniparser/dictionary.c | 377 + libatalk/iniparser/iniparser.c | 652 + libatalk/libatalk-3.0.1.abi | 549 + libatalk/libatalk-3.0.2.abi | 565 + libatalk/libatalk-3.0.3.abi | 566 + libatalk/libatalk-3.0.4.abi | 566 + libatalk/libatalk-3.0.5.abi | 568 + libatalk/libatalk-3.0.6.abi | 570 + libatalk/libatalk-3.0.abi | 548 + libatalk/libatalk-3.0beta1.abi | 550 + libatalk/libatalk-3.0beta2.abi | 548 + libatalk/libatalk-3.1.0.abi | 651 + libatalk/libatalk-3.1.1.abi | 639 + libatalk/libatalk-3.1.2.abi | 639 + libatalk/libatalk-3.1.3.abi | 634 + libatalk/libatalk-3.1.4.abi | 635 + libatalk/libatalk-3.1.5.abi | 635 + libatalk/libatalk-3.1.6.abi | 635 + libatalk/talloc/Makefile.am | 4 + libatalk/talloc/Makefile.in | 662 + libatalk/talloc/dalloc.c | 280 + libatalk/talloc/talloc.c | 2379 +++ libatalk/tdb/Makefile.am | 16 + libatalk/tdb/Makefile.in | 687 + libatalk/tdb/check.c | 423 + libatalk/tdb/dump.c | 137 + libatalk/tdb/error.c | 57 + libatalk/tdb/freelist.c | 386 + libatalk/tdb/freelistcheck.c | 109 + libatalk/tdb/io.c | 472 + libatalk/tdb/lock.c | 592 + libatalk/tdb/open.c | 552 + libatalk/tdb/tdb.c | 1140 ++ libatalk/tdb/tdb_private.h | 279 + libatalk/tdb/transaction.c | 1236 ++ libatalk/tdb/traverse.c | 366 + libatalk/unicode/Makefile.am | 22 + libatalk/unicode/Makefile.in | 806 + libatalk/unicode/charcnv.c | 1046 ++ libatalk/unicode/charsets/Makefile.am | 34 + libatalk/unicode/charsets/Makefile.in | 705 + libatalk/unicode/charsets/generic_cjk.c | 215 + libatalk/unicode/charsets/generic_cjk.h | 42 + libatalk/unicode/charsets/generic_mb.c | 113 + libatalk/unicode/charsets/generic_mb.h | 2 + libatalk/unicode/charsets/mac_centraleurope.c | 67 + libatalk/unicode/charsets/mac_centraleurope.h | 139 + libatalk/unicode/charsets/mac_chinese_simp.c | 117 + libatalk/unicode/charsets/mac_chinese_simp.h | 146 + libatalk/unicode/charsets/mac_chinese_trad.c | 122 + libatalk/unicode/charsets/mac_chinese_trad.h | 124 + libatalk/unicode/charsets/mac_cyrillic.c | 67 + libatalk/unicode/charsets/mac_cyrillic.h | 142 + libatalk/unicode/charsets/mac_greek.c | 112 + libatalk/unicode/charsets/mac_greek.h | 91 + libatalk/unicode/charsets/mac_hebrew.c | 222 + libatalk/unicode/charsets/mac_hebrew.h | 111 + libatalk/unicode/charsets/mac_japanese.c | 130 + libatalk/unicode/charsets/mac_japanese.h | 252 + libatalk/unicode/charsets/mac_korean.c | 126 + libatalk/unicode/charsets/mac_korean.h | 771 + libatalk/unicode/charsets/mac_roman.c | 118 + libatalk/unicode/charsets/mac_roman.h | 117 + libatalk/unicode/charsets/mac_turkish.c | 65 + libatalk/unicode/charsets/mac_turkish.h | 167 + libatalk/unicode/iconv.c | 437 + libatalk/unicode/precompose.h | 2156 +++ libatalk/unicode/utf16_case.c | 122 + libatalk/unicode/utf16_casetable.h | 5974 +++++++ libatalk/unicode/utf8.c | 281 + libatalk/unicode/util_unistr.c | 837 + libatalk/util/Makefile.am | 34 + libatalk/util/Makefile.in | 823 + libatalk/util/bprint.c | 52 + libatalk/util/cnid.c | 201 + libatalk/util/fault.c | 164 + libatalk/util/ftw.c | 828 + libatalk/util/getiface.c | 148 + libatalk/util/gettok.c | 162 + libatalk/util/locking.c | 95 + libatalk/util/logger.c | 518 + libatalk/util/module.c | 71 + libatalk/util/netatalk_conf.c | 2170 +++ libatalk/util/queue.c | 116 + libatalk/util/server_child.c | 351 + libatalk/util/server_ipc.c | 311 + libatalk/util/server_lock.c | 147 + libatalk/util/socket.c | 737 + libatalk/util/strdicasecmp.c | 554 + libatalk/util/unix.c | 556 + libatalk/vfs/Makefile.am | 9 + libatalk/vfs/Makefile.in | 672 + libatalk/vfs/acl.c | 137 + libatalk/vfs/ea_ad.c | 1771 ++ libatalk/vfs/ea_sys.c | 567 + libatalk/vfs/extattr.c | 1039 ++ libatalk/vfs/unix.c | 368 + libatalk/vfs/vfs.c | 885 + libevent/ChangeLog | 1245 ++ libevent/Doxyfile | 257 + libevent/LICENSE | 74 + libevent/Makefile.am | 249 + libevent/Makefile.in | 1344 ++ libevent/Makefile.nmake | 47 + libevent/README | 188 + libevent/WIN32-Code/event2/event-config.h | 363 + libevent/WIN32-Code/tree.h | 1354 ++ libevent/aclocal.m4 | 1051 ++ libevent/arc4random.c | 539 + libevent/autogen.sh | 15 + libevent/buffer.c | 3062 ++++ libevent/buffer_iocp.c | 325 + libevent/bufferevent-internal.h | 410 + libevent/bufferevent.c | 875 + libevent/bufferevent_async.c | 690 + libevent/bufferevent_filter.c | 511 + libevent/bufferevent_openssl.c | 1418 ++ libevent/bufferevent_pair.c | 333 + libevent/bufferevent_ratelim.c | 1011 ++ libevent/bufferevent_sock.c | 693 + libevent/changelist-internal.h | 101 + libevent/compat/sys/queue.h | 488 + libevent/config.h.in | 436 + libevent/configure | 17492 ++++++++++++++++++ libevent/configure.in | 796 + libevent/defer-internal.h | 100 + libevent/devpoll.c | 306 + libevent/epoll.c | 473 + libevent/epoll_sub.c | 52 + libevent/evbuffer-internal.h | 281 + libevent/evdns.c | 4620 +++++ libevent/evdns.h | 45 + libevent/event-internal.h | 363 + libevent/event.c | 2897 +++ libevent/event.h | 85 + libevent/event_iocp.c | 290 + libevent/event_rpcgen.py | 1717 ++ libevent/event_tagging.c | 590 + libevent/evhttp.h | 45 + libevent/evmap-internal.h | 92 + libevent/evmap.c | 799 + libevent/evport.c | 473 + libevent/evrpc-internal.h | 204 + libevent/evrpc.c | 1174 ++ libevent/evrpc.h | 45 + libevent/evsignal-internal.h | 64 + libevent/evthread-internal.h | 382 + libevent/evthread.c | 445 + libevent/evthread_pthread.c | 189 + libevent/evthread_win32.c | 339 + libevent/evutil.c | 2177 +++ libevent/evutil.h | 39 + libevent/evutil_rand.c | 147 + libevent/ht-internal.h | 484 + libevent/http-internal.h | 195 + libevent/http.c | 4515 +++++ libevent/include/Makefile.am | 47 + libevent/include/Makefile.in | 610 + libevent/include/event2/buffer.h | 838 + libevent/include/event2/buffer_compat.h | 110 + libevent/include/event2/bufferevent.h | 821 + libevent/include/event2/bufferevent_compat.h | 100 + libevent/include/event2/bufferevent_ssl.h | 107 + libevent/include/event2/bufferevent_struct.h | 116 + libevent/include/event2/dns.h | 643 + libevent/include/event2/dns_compat.h | 336 + libevent/include/event2/dns_struct.h | 80 + libevent/include/event2/event.h | 1197 ++ libevent/include/event2/event_compat.h | 220 + libevent/include/event2/event_struct.h | 141 + libevent/include/event2/http.h | 863 + libevent/include/event2/http_compat.h | 90 + libevent/include/event2/http_struct.h | 130 + libevent/include/event2/keyvalq_struct.h | 80 + libevent/include/event2/listener.h | 143 + libevent/include/event2/rpc.h | 596 + libevent/include/event2/rpc_compat.h | 61 + libevent/include/event2/rpc_struct.h | 100 + libevent/include/event2/tag.h | 124 + libevent/include/event2/tag_compat.h | 49 + libevent/include/event2/thread.h | 236 + libevent/include/event2/util.h | 691 + libevent/iocp-internal.h | 201 + libevent/ipv6-internal.h | 81 + libevent/kqueue.c | 475 + libevent/libevent.pc.in | 16 + libevent/libevent_openssl.pc.in | 16 + libevent/libevent_pthreads.pc.in | 16 + libevent/listener.c | 875 + libevent/log-internal.h | 59 + libevent/log.c | 224 + libevent/m4/acx_pthread.m4 | 279 + libevent/m4/libtool.m4 | 7982 +++++++++ libevent/m4/ltoptions.m4 | 384 + libevent/m4/ltsugar.m4 | 123 + libevent/m4/ltversion.m4 | 23 + libevent/m4/lt~obsolete.m4 | 98 + libevent/minheap-internal.h | 160 + libevent/mm-internal.h | 61 + libevent/poll.c | 333 + libevent/ratelim-internal.h | 105 + libevent/sample/Makefile.am | 29 + libevent/sample/Makefile.in | 605 + libevent/sample/dns-example.c | 239 + libevent/sample/event-test.c | 143 + libevent/sample/hello-world.c | 141 + libevent/sample/http-server.c | 405 + libevent/sample/le-proxy.c | 278 + libevent/sample/signal-test.c | 77 + libevent/sample/time-test.c | 108 + libevent/select.c | 333 + libevent/signal.c | 444 + libevent/strlcpy-internal.h | 21 + libevent/strlcpy.c | 74 + libevent/test/Makefile.am | 98 + libevent/test/Makefile.in | 1012 ++ libevent/test/Makefile.nmake | 61 + libevent/test/bench.c | 196 + libevent/test/bench_cascade.c | 174 + libevent/test/bench_http.c | 191 + libevent/test/bench_httpclient.c | 222 + libevent/test/regress.c | 2406 +++ libevent/test/regress.gen.c | 1225 ++ libevent/test/regress.gen.h | 207 + libevent/test/regress.h | 125 + libevent/test/regress.rpc | 25 + libevent/test/regress_buffer.c | 1666 ++ libevent/test/regress_bufferevent.c | 835 + libevent/test/regress_dns.c | 1853 ++ libevent/test/regress_et.c | 205 + libevent/test/regress_http.c | 3614 ++++ libevent/test/regress_iocp.c | 352 + libevent/test/regress_listener.c | 214 + libevent/test/regress_main.c | 395 + libevent/test/regress_minheap.c | 98 + libevent/test/regress_rpc.c | 893 + libevent/test/regress_ssl.c | 449 + libevent/test/regress_testutils.c | 215 + libevent/test/regress_testutils.h | 66 + libevent/test/regress_thread.c | 511 + libevent/test/regress_util.c | 1094 ++ libevent/test/regress_zlib.c | 344 + libevent/test/rpcgen_wrapper.sh | 41 + libevent/test/test-changelist.c | 220 + libevent/test/test-eof.c | 124 + libevent/test/test-init.c | 66 + libevent/test/test-ratelim.c | 478 + libevent/test/test-time.c | 114 + libevent/test/test-weof.c | 118 + libevent/test/test.sh | 163 + libevent/test/tinytest.c | 388 + libevent/test/tinytest.h | 87 + libevent/test/tinytest_local.h | 12 + libevent/test/tinytest_macros.h | 184 + libevent/util-internal.h | 319 + libevent/whatsnew-2.0.txt | 609 + libevent/win32select.c | 376 + ltmain.sh | 9655 ++++++++++ macros/Makefile.am | 20 + macros/Makefile.in | 535 + macros/afs-check.m4 | 30 + macros/ax_pthread.m4 | 309 + macros/cnid-backend.m4 | 186 + macros/config-checks.m4 | 32 + macros/db3-check.m4 | 227 + macros/grep-check.m4 | 9 + macros/gssapi-check.m4 | 101 + macros/iconv.m4 | 120 + macros/largefile-check.m4 | 78 + macros/libgcrypt.m4 | 123 + macros/libtool.m4 | 7982 +++++++++ macros/ltoptions.m4 | 384 + macros/ltsugar.m4 | 123 + macros/ltversion.m4 | 23 + macros/lt~obsolete.m4 | 98 + macros/netatalk.m4 | 1212 ++ macros/pam-check.m4 | 160 + macros/perl-check.m4 | 9 + macros/ps-check.m4 | 9 + macros/quota-check.m4 | 26 + macros/ssl-check.m4 | 83 + macros/summary.m4 | 163 + macros/tcp-wrappers.m4 | 51 + macros/util.m4 | 24 + macros/zeroconf.m4 | 87 + man/Makefile.am | 3 + man/Makefile.in | 706 + man/man1/Makefile.am | 15 + man/man1/Makefile.in | 650 + man/man1/ad.1.in | 250 + man/man1/afpldaptest.1.in | 67 + man/man1/afppasswd.1.in | 122 + man/man1/afpstats.1.in | 50 + man/man1/apple_dump.1.in | 114 + man/man1/asip-status.pl.1.in | 135 + man/man1/dbd.1.in | 86 + man/man1/macusers.1.in | 54 + man/man1/netatalk-config.1.in | 110 + man/man1/uniconv.1.in | 203 + man/man5/Makefile.am | 9 + man/man5/Makefile.in | 628 + man/man5/afp.conf.5.in | 1520 ++ man/man5/afp_signature.conf.5.in | 86 + man/man5/afp_voluuid.conf.5.in | 87 + man/man5/extmap.conf.5.in | 77 + man/man8/Makefile.am | 9 + man/man8/Makefile.in | 625 + man/man8/afpd.8.in | 171 + man/man8/cnid_dbd.8.in | 249 + man/man8/cnid_metad.8.in | 90 + man/man8/netatalk.8.in | 67 + missing | 330 + test/Makefile.am | 1 + test/Makefile.in | 704 + test/afpd/Makefile.am | 79 + test/afpd/Makefile.in | 1386 ++ test/afpd/afpfunc_helpers.c | 241 + test/afpd/afpfunc_helpers.h | 56 + test/afpd/subtests.c | 70 + test/afpd/subtests.h | 44 + test/afpd/test.c | 116 + test/afpd/test.h | 76 + test/afpd/test.sh | 21 + ylwrap | 240 + 725 files changed, 336331 insertions(+) create mode 100644 AUTHORS create mode 100644 CONTRIBUTORS create mode 100644 COPYING create mode 100644 COPYRIGHT create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 VERSION create mode 100755 abigen.sh create mode 100644 aclocal.m4 create mode 100644 bin/Makefile.am create mode 100644 bin/Makefile.in create mode 100644 bin/ad/Makefile.am create mode 100644 bin/ad/Makefile.in create mode 100644 bin/ad/ad.c create mode 100644 bin/ad/ad.h create mode 100644 bin/ad/ad_cp.c create mode 100644 bin/ad/ad_find.c create mode 100644 bin/ad/ad_ls.c create mode 100644 bin/ad/ad_mv.c create mode 100644 bin/ad/ad_rm.c create mode 100644 bin/ad/ad_set.c create mode 100644 bin/ad/ad_util.c create mode 100644 bin/afppasswd/Makefile.am create mode 100644 bin/afppasswd/Makefile.in create mode 100644 bin/afppasswd/afppasswd.c create mode 100644 bin/cnid/Makefile.am create mode 100644 bin/cnid/Makefile.in create mode 100755 bin/cnid/cnid2_create.in create mode 100644 bin/megatron/Makefile.am create mode 100644 bin/megatron/Makefile.in create mode 100644 bin/misc/Makefile.am create mode 100644 bin/misc/Makefile.in create mode 100644 bin/misc/fce.c create mode 100644 bin/misc/logger_test.c create mode 100644 bin/misc/netacnv.c create mode 100644 bin/misc/uuidtest.c create mode 100755 compile create mode 100755 config.guess create mode 100644 config.h.in create mode 100755 config.sub create mode 100644 config/Makefile.am create mode 100644 config/Makefile.in create mode 100644 config/README create mode 100644 config/afp.conf.tmpl create mode 100644 config/dbus-session.conf.tmpl create mode 100644 config/extmap.conf create mode 100644 config/netatalk-dbus.conf create mode 100644 config/pam/Makefile.am create mode 100644 config/pam/Makefile.in create mode 100644 config/pam/netatalk.tmpl create mode 100755 configure create mode 100644 configure.ac create mode 100644 contrib/Makefile.am create mode 100644 contrib/Makefile.in create mode 100644 contrib/macusers/Makefile.am create mode 100644 contrib/macusers/Makefile.in create mode 100644 contrib/macusers/README.macusers create mode 100644 contrib/macusers/macusers.in create mode 100644 contrib/shell_utils/Makefile.am create mode 100644 contrib/shell_utils/Makefile.in create mode 100755 contrib/shell_utils/afpstats create mode 100755 contrib/shell_utils/apple_dump.in create mode 100755 contrib/shell_utils/asip-status.pl.in create mode 100644 contrib/shell_utils/fce_ev_script.sh create mode 100755 contrib/shell_utils/make-casetable.pl create mode 100755 contrib/shell_utils/make-precompose.h.pl create mode 100755 depcomp create mode 100644 distrib/Makefile.am create mode 100644 distrib/Makefile.in create mode 100644 distrib/config/Makefile.am create mode 100644 distrib/config/Makefile.in create mode 100644 distrib/config/netatalk-config.in create mode 100644 distrib/initscripts/Makefile.am create mode 100644 distrib/initscripts/Makefile.in create mode 100644 distrib/initscripts/netatalk.xml.tmpl create mode 100644 distrib/initscripts/rc.bsd.tmpl create mode 100644 distrib/initscripts/rc.debian.tmpl create mode 100644 distrib/initscripts/rc.gentoo.tmpl create mode 100644 distrib/initscripts/rc.netbsd.tmpl create mode 100644 distrib/initscripts/rc.redhat.tmpl create mode 100644 distrib/initscripts/rc.solaris.tmpl create mode 100644 distrib/initscripts/rc.suse.tmpl create mode 100644 distrib/initscripts/service.systemd.tmpl create mode 100644 distrib/m4/Makefile.am create mode 100644 distrib/m4/Makefile.in create mode 100644 distrib/m4/netatalk.m4 create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/html.xsl.in create mode 100644 doc/man.xsl.in create mode 100644 doc/manpages/Makefile.am create mode 100644 doc/manpages/Makefile.in create mode 100644 doc/manpages/man1/Makefile.am create mode 100644 doc/manpages/man1/Makefile.in create mode 100644 doc/manpages/man1/ad.1.xml create mode 100644 doc/manpages/man1/afpldaptest.1.xml create mode 100644 doc/manpages/man1/afppasswd.1.xml create mode 100644 doc/manpages/man1/afpstats.1.xml create mode 100644 doc/manpages/man1/apple_dump.1.xml create mode 100644 doc/manpages/man1/asip-status.pl.1.xml create mode 100644 doc/manpages/man1/dbd.1.xml create mode 100644 doc/manpages/man1/macusers.1.xml create mode 100644 doc/manpages/man1/megatron.1.xml create mode 100644 doc/manpages/man1/netatalk-config.1.xml create mode 100644 doc/manpages/man1/uniconv.1.xml create mode 100644 doc/manpages/man5/Makefile.am create mode 100644 doc/manpages/man5/Makefile.in create mode 100644 doc/manpages/man5/afp.conf.5.xml create mode 100644 doc/manpages/man5/afp_signature.conf.5.xml create mode 100644 doc/manpages/man5/afp_voluuid.conf.5.xml create mode 100644 doc/manpages/man5/extmap.conf.5.xml create mode 100644 doc/manpages/man8/Makefile.am create mode 100644 doc/manpages/man8/Makefile.in create mode 100644 doc/manpages/man8/afpd.8.xml create mode 100644 doc/manpages/man8/cnid_dbd.8.xml create mode 100644 doc/manpages/man8/cnid_metad.8.xml create mode 100644 doc/manpages/man8/netatalk.8.xml create mode 100644 doc/manual/Makefile.am create mode 100644 doc/manual/Makefile.in create mode 100644 doc/manual/configuration.xml create mode 100644 doc/manual/install.xml create mode 100644 doc/manual/intro.xml create mode 100644 doc/manual/manual.xml.in create mode 100644 doc/manual/netatalk.html create mode 100644 doc/manual/upgrade.xml create mode 100644 etc/Makefile.am create mode 100644 etc/Makefile.in create mode 100644 etc/afpd/Makefile.am create mode 100644 etc/afpd/Makefile.in create mode 100644 etc/afpd/acl_mappings.h create mode 100644 etc/afpd/acls.c create mode 100644 etc/afpd/acls.h create mode 100644 etc/afpd/afp_config.c create mode 100644 etc/afpd/afp_config.h create mode 100644 etc/afpd/afp_dsi.c create mode 100644 etc/afpd/afp_options.c create mode 100644 etc/afpd/afp_util.c create mode 100644 etc/afpd/afprun.c create mode 100644 etc/afpd/afpstats-service.xml create mode 100644 etc/afpd/afpstats.c create mode 100644 etc/afpd/afpstats.h create mode 100644 etc/afpd/afpstats_obj.c create mode 100644 etc/afpd/afpstats_obj.h create mode 100644 etc/afpd/afpstats_service_glue.h create mode 100644 etc/afpd/afs.c create mode 100644 etc/afpd/appl.c create mode 100644 etc/afpd/auth.c create mode 100644 etc/afpd/auth.h create mode 100644 etc/afpd/catsearch.c create mode 100644 etc/afpd/desktop.c create mode 100644 etc/afpd/desktop.h create mode 100644 etc/afpd/dircache.c create mode 100644 etc/afpd/dircache.h create mode 100644 etc/afpd/directory.c create mode 100644 etc/afpd/directory.h create mode 100644 etc/afpd/enumerate.c create mode 100644 etc/afpd/extattrs.c create mode 100644 etc/afpd/extattrs.h create mode 100644 etc/afpd/fce_api.c create mode 100644 etc/afpd/fce_api_internal.h create mode 100644 etc/afpd/fce_util.c create mode 100644 etc/afpd/file.c create mode 100644 etc/afpd/file.h create mode 100644 etc/afpd/filedir.c create mode 100644 etc/afpd/filedir.h create mode 100644 etc/afpd/fork.c create mode 100644 etc/afpd/fork.h create mode 100644 etc/afpd/hash.c create mode 100644 etc/afpd/hash.h create mode 100644 etc/afpd/icon.h create mode 100644 etc/afpd/main.c create mode 100644 etc/afpd/mangle.c create mode 100644 etc/afpd/mangle.h create mode 100644 etc/afpd/messages.c create mode 100644 etc/afpd/misc.h create mode 100644 etc/afpd/nfsquota.c create mode 100644 etc/afpd/ofork.c create mode 100644 etc/afpd/quota.c create mode 100644 etc/afpd/spotlight.c create mode 100644 etc/afpd/spotlight_marshalling.c create mode 100644 etc/afpd/status.c create mode 100644 etc/afpd/status.h create mode 100644 etc/afpd/switch.c create mode 100644 etc/afpd/switch.h create mode 100644 etc/afpd/uam.c create mode 100644 etc/afpd/uam_auth.h create mode 100644 etc/afpd/uid.c create mode 100644 etc/afpd/uid.h create mode 100644 etc/afpd/unix.c create mode 100644 etc/afpd/unix.h create mode 100644 etc/afpd/volume.c create mode 100644 etc/afpd/volume.h create mode 100644 etc/cnid_dbd/Makefile.am create mode 100644 etc/cnid_dbd/Makefile.in create mode 100644 etc/cnid_dbd/cmd_dbd.c create mode 100644 etc/cnid_dbd/cmd_dbd.h create mode 100644 etc/cnid_dbd/cmd_dbd_scanvol.c create mode 100644 etc/cnid_dbd/cnid_metad.c create mode 100644 etc/cnid_dbd/comm.c create mode 100644 etc/cnid_dbd/comm.h create mode 100644 etc/cnid_dbd/db_param.c create mode 100644 etc/cnid_dbd/db_param.h create mode 100644 etc/cnid_dbd/dbd.h create mode 100644 etc/cnid_dbd/dbd_add.c create mode 100644 etc/cnid_dbd/dbd_dbcheck.c create mode 100644 etc/cnid_dbd/dbd_delete.c create mode 100644 etc/cnid_dbd/dbd_get.c create mode 100644 etc/cnid_dbd/dbd_getstamp.c create mode 100644 etc/cnid_dbd/dbd_lookup.c create mode 100644 etc/cnid_dbd/dbd_rebuild_add.c create mode 100644 etc/cnid_dbd/dbd_resolve.c create mode 100644 etc/cnid_dbd/dbd_search.c create mode 100644 etc/cnid_dbd/dbd_update.c create mode 100644 etc/cnid_dbd/dbif.c create mode 100644 etc/cnid_dbd/dbif.h create mode 100644 etc/cnid_dbd/main.c create mode 100644 etc/cnid_dbd/pack.c create mode 100644 etc/cnid_dbd/pack.h create mode 100644 etc/cnid_dbd/usockfd.c create mode 100644 etc/cnid_dbd/usockfd.h create mode 100644 etc/netatalk/Makefile.am create mode 100644 etc/netatalk/Makefile.in create mode 100644 etc/netatalk/afp_avahi.c create mode 100644 etc/netatalk/afp_avahi.h create mode 100644 etc/netatalk/afp_mdns.c create mode 100644 etc/netatalk/afp_mdns.h create mode 100644 etc/netatalk/afp_zeroconf.c create mode 100644 etc/netatalk/afp_zeroconf.h create mode 100644 etc/netatalk/netatalk.c create mode 100644 etc/spotlight/Makefile.am create mode 100644 etc/spotlight/Makefile.in create mode 100644 etc/spotlight/sparql_map.c create mode 100644 etc/spotlight/sparql_map.h create mode 100644 etc/spotlight/sparql_parser.c create mode 100644 etc/spotlight/sparql_parser.h create mode 100644 etc/spotlight/sparql_parser.y create mode 100644 etc/spotlight/spotlight_rawquery_lexer.c create mode 100644 etc/spotlight/spotlight_rawquery_lexer.l create mode 100644 etc/uams/Makefile.am create mode 100644 etc/uams/Makefile.in create mode 100644 etc/uams/uams_dhx2_pam.c create mode 100644 etc/uams/uams_dhx2_passwd.c create mode 100644 etc/uams/uams_dhx_pam.c create mode 100644 etc/uams/uams_dhx_passwd.c create mode 100644 etc/uams/uams_gss.c create mode 100644 etc/uams/uams_guest.c create mode 100644 etc/uams/uams_pam.c create mode 100644 etc/uams/uams_passwd.c create mode 100644 etc/uams/uams_pgp.c create mode 100644 etc/uams/uams_randnum.c create mode 100644 include/Makefile.am create mode 100644 include/Makefile.in create mode 100644 include/atalk/Makefile.am create mode 100644 include/atalk/Makefile.in create mode 100644 include/atalk/acl.h create mode 100644 include/atalk/adouble.h create mode 100644 include/atalk/afp.h create mode 100644 include/atalk/afp_dtrace.d create mode 100644 include/atalk/bstradd.h create mode 100644 include/atalk/bstrlib.h create mode 100644 include/atalk/byteorder.h create mode 100644 include/atalk/cnid.h create mode 100644 include/atalk/cnid_bdb_private.h create mode 100644 include/atalk/cnid_mysql_private.h create mode 100644 include/atalk/cnid_private.h create mode 100644 include/atalk/compat.h create mode 100644 include/atalk/dalloc.h create mode 100644 include/atalk/dictionary.h create mode 100644 include/atalk/directory.h create mode 100644 include/atalk/dsi.h create mode 100644 include/atalk/ea.h create mode 100644 include/atalk/errchk.h create mode 100755 include/atalk/fce_api.h create mode 100644 include/atalk/ftw.h create mode 100644 include/atalk/globals.h create mode 100644 include/atalk/hash.h create mode 100644 include/atalk/iniparser.h create mode 100644 include/atalk/ldapconfig.h create mode 100644 include/atalk/list.h create mode 100644 include/atalk/logger.h create mode 100644 include/atalk/netatalk_conf.h create mode 100644 include/atalk/paths.h create mode 100644 include/atalk/queue.h create mode 100644 include/atalk/server_child.h create mode 100644 include/atalk/server_ipc.h create mode 100644 include/atalk/spotlight.h create mode 100644 include/atalk/standards.h create mode 100644 include/atalk/talloc.h create mode 100644 include/atalk/tdb.h create mode 100644 include/atalk/uam.h create mode 100644 include/atalk/unicode.h create mode 100644 include/atalk/unix.h create mode 100644 include/atalk/util.h create mode 100644 include/atalk/uuid.h create mode 100644 include/atalk/vfs.h create mode 100644 include/atalk/volume.h create mode 100755 install-sh create mode 100644 libatalk/Makefile.am create mode 100644 libatalk/Makefile.in create mode 100644 libatalk/acl/Makefile.am create mode 100644 libatalk/acl/Makefile.in create mode 100644 libatalk/acl/aclldap.h create mode 100644 libatalk/acl/cache.c create mode 100644 libatalk/acl/cache.h create mode 100644 libatalk/acl/ldap.c create mode 100644 libatalk/acl/ldap_config.c create mode 100644 libatalk/acl/unix.c create mode 100644 libatalk/acl/uuid.c create mode 100644 libatalk/adouble/Makefile.am create mode 100644 libatalk/adouble/Makefile.in create mode 100644 libatalk/adouble/ad_attr.c create mode 100644 libatalk/adouble/ad_conv.c create mode 100644 libatalk/adouble/ad_date.c create mode 100644 libatalk/adouble/ad_flush.c create mode 100644 libatalk/adouble/ad_lock.c create mode 100644 libatalk/adouble/ad_lock.h create mode 100644 libatalk/adouble/ad_mmap.c create mode 100644 libatalk/adouble/ad_open.c create mode 100644 libatalk/adouble/ad_read.c create mode 100644 libatalk/adouble/ad_recvfile.c create mode 100644 libatalk/adouble/ad_sendfile.c create mode 100644 libatalk/adouble/ad_size.c create mode 100644 libatalk/adouble/ad_write.c create mode 100644 libatalk/bstring/Makefile.am create mode 100644 libatalk/bstring/Makefile.in create mode 100644 libatalk/bstring/bstradd.c create mode 100644 libatalk/bstring/bstrlib.c create mode 100644 libatalk/cnid/Makefile.am create mode 100644 libatalk/cnid/Makefile.in create mode 100644 libatalk/cnid/README create mode 100644 libatalk/cnid/cdb/Makefile.am create mode 100644 libatalk/cnid/cdb/Makefile.in create mode 100644 libatalk/cnid/cdb/README create mode 100644 libatalk/cnid/cdb/cnid_cdb.h create mode 100644 libatalk/cnid/cdb/cnid_cdb_add.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_close.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_delete.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_get.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_lookup.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_meta.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_meta.h create mode 100644 libatalk/cnid/cdb/cnid_cdb_nextid.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_open.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_private.h create mode 100644 libatalk/cnid/cdb/cnid_cdb_rebuild_add.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_resolve.c create mode 100644 libatalk/cnid/cdb/cnid_cdb_update.c create mode 100644 libatalk/cnid/cnid.c create mode 100644 libatalk/cnid/cnid_init.c create mode 100644 libatalk/cnid/dbd/Makefile.am create mode 100644 libatalk/cnid/dbd/Makefile.in create mode 100644 libatalk/cnid/dbd/cnid_dbd.c create mode 100644 libatalk/cnid/dbd/cnid_dbd.h create mode 100644 libatalk/cnid/last/Makefile.am create mode 100644 libatalk/cnid/last/Makefile.in create mode 100644 libatalk/cnid/last/README create mode 100644 libatalk/cnid/last/cnid_last.c create mode 100644 libatalk/cnid/last/cnid_last.h create mode 100644 libatalk/cnid/mysql/Makefile.am create mode 100644 libatalk/cnid/mysql/Makefile.in create mode 100644 libatalk/cnid/mysql/cnid_mysql.c create mode 100644 libatalk/cnid/tdb/Makefile.am create mode 100644 libatalk/cnid/tdb/Makefile.in create mode 100644 libatalk/cnid/tdb/README create mode 100644 libatalk/cnid/tdb/cnid_tdb.h create mode 100644 libatalk/cnid/tdb/cnid_tdb_add.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_close.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_delete.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_get.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_lookup.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_nextid.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_open.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_resolve.c create mode 100644 libatalk/cnid/tdb/cnid_tdb_update.c create mode 100644 libatalk/compat/Makefile.am create mode 100644 libatalk/compat/Makefile.in create mode 100644 libatalk/compat/getusershell.c create mode 100644 libatalk/compat/misc.c create mode 100644 libatalk/compat/mktemp.c create mode 100644 libatalk/compat/pselect.c create mode 100644 libatalk/compat/rquota_xdr.c create mode 100644 libatalk/compat/strlcpy.c create mode 100644 libatalk/dsi/Makefile.am create mode 100644 libatalk/dsi/Makefile.in create mode 100644 libatalk/dsi/README create mode 100644 libatalk/dsi/dsi_attn.c create mode 100644 libatalk/dsi/dsi_close.c create mode 100644 libatalk/dsi/dsi_cmdreply.c create mode 100644 libatalk/dsi/dsi_getsess.c create mode 100644 libatalk/dsi/dsi_getstat.c create mode 100644 libatalk/dsi/dsi_init.c create mode 100644 libatalk/dsi/dsi_opensess.c create mode 100644 libatalk/dsi/dsi_read.c create mode 100644 libatalk/dsi/dsi_stream.c create mode 100644 libatalk/dsi/dsi_tcp.c create mode 100644 libatalk/dsi/dsi_tickle.c create mode 100644 libatalk/dsi/dsi_write.c create mode 100644 libatalk/dummy.c create mode 100644 libatalk/iniparser/Makefile.am create mode 100644 libatalk/iniparser/Makefile.in create mode 100644 libatalk/iniparser/dictionary.c create mode 100644 libatalk/iniparser/iniparser.c create mode 100644 libatalk/libatalk-3.0.1.abi create mode 100644 libatalk/libatalk-3.0.2.abi create mode 100644 libatalk/libatalk-3.0.3.abi create mode 100644 libatalk/libatalk-3.0.4.abi create mode 100644 libatalk/libatalk-3.0.5.abi create mode 100644 libatalk/libatalk-3.0.6.abi create mode 100644 libatalk/libatalk-3.0.abi create mode 100644 libatalk/libatalk-3.0beta1.abi create mode 100644 libatalk/libatalk-3.0beta2.abi create mode 100644 libatalk/libatalk-3.1.0.abi create mode 100644 libatalk/libatalk-3.1.1.abi create mode 100644 libatalk/libatalk-3.1.2.abi create mode 100644 libatalk/libatalk-3.1.3.abi create mode 100644 libatalk/libatalk-3.1.4.abi create mode 100644 libatalk/libatalk-3.1.5.abi create mode 100644 libatalk/libatalk-3.1.6.abi create mode 100644 libatalk/talloc/Makefile.am create mode 100644 libatalk/talloc/Makefile.in create mode 100644 libatalk/talloc/dalloc.c create mode 100644 libatalk/talloc/talloc.c create mode 100644 libatalk/tdb/Makefile.am create mode 100644 libatalk/tdb/Makefile.in create mode 100644 libatalk/tdb/check.c create mode 100644 libatalk/tdb/dump.c create mode 100644 libatalk/tdb/error.c create mode 100644 libatalk/tdb/freelist.c create mode 100644 libatalk/tdb/freelistcheck.c create mode 100644 libatalk/tdb/io.c create mode 100644 libatalk/tdb/lock.c create mode 100644 libatalk/tdb/open.c create mode 100644 libatalk/tdb/tdb.c create mode 100644 libatalk/tdb/tdb_private.h create mode 100644 libatalk/tdb/transaction.c create mode 100644 libatalk/tdb/traverse.c create mode 100644 libatalk/unicode/Makefile.am create mode 100644 libatalk/unicode/Makefile.in create mode 100644 libatalk/unicode/charcnv.c create mode 100644 libatalk/unicode/charsets/Makefile.am create mode 100644 libatalk/unicode/charsets/Makefile.in create mode 100644 libatalk/unicode/charsets/generic_cjk.c create mode 100644 libatalk/unicode/charsets/generic_cjk.h create mode 100644 libatalk/unicode/charsets/generic_mb.c create mode 100644 libatalk/unicode/charsets/generic_mb.h create mode 100644 libatalk/unicode/charsets/mac_centraleurope.c create mode 100644 libatalk/unicode/charsets/mac_centraleurope.h create mode 100644 libatalk/unicode/charsets/mac_chinese_simp.c create mode 100644 libatalk/unicode/charsets/mac_chinese_simp.h create mode 100644 libatalk/unicode/charsets/mac_chinese_trad.c create mode 100644 libatalk/unicode/charsets/mac_chinese_trad.h create mode 100644 libatalk/unicode/charsets/mac_cyrillic.c create mode 100644 libatalk/unicode/charsets/mac_cyrillic.h create mode 100644 libatalk/unicode/charsets/mac_greek.c create mode 100644 libatalk/unicode/charsets/mac_greek.h create mode 100644 libatalk/unicode/charsets/mac_hebrew.c create mode 100644 libatalk/unicode/charsets/mac_hebrew.h create mode 100644 libatalk/unicode/charsets/mac_japanese.c create mode 100644 libatalk/unicode/charsets/mac_japanese.h create mode 100644 libatalk/unicode/charsets/mac_korean.c create mode 100644 libatalk/unicode/charsets/mac_korean.h create mode 100644 libatalk/unicode/charsets/mac_roman.c create mode 100644 libatalk/unicode/charsets/mac_roman.h create mode 100644 libatalk/unicode/charsets/mac_turkish.c create mode 100644 libatalk/unicode/charsets/mac_turkish.h create mode 100644 libatalk/unicode/iconv.c create mode 100644 libatalk/unicode/precompose.h create mode 100644 libatalk/unicode/utf16_case.c create mode 100644 libatalk/unicode/utf16_casetable.h create mode 100644 libatalk/unicode/utf8.c create mode 100644 libatalk/unicode/util_unistr.c create mode 100644 libatalk/util/Makefile.am create mode 100644 libatalk/util/Makefile.in create mode 100644 libatalk/util/bprint.c create mode 100644 libatalk/util/cnid.c create mode 100644 libatalk/util/fault.c create mode 100644 libatalk/util/ftw.c create mode 100644 libatalk/util/getiface.c create mode 100644 libatalk/util/gettok.c create mode 100644 libatalk/util/locking.c create mode 100644 libatalk/util/logger.c create mode 100644 libatalk/util/module.c create mode 100644 libatalk/util/netatalk_conf.c create mode 100644 libatalk/util/queue.c create mode 100644 libatalk/util/server_child.c create mode 100644 libatalk/util/server_ipc.c create mode 100644 libatalk/util/server_lock.c create mode 100644 libatalk/util/socket.c create mode 100644 libatalk/util/strdicasecmp.c create mode 100644 libatalk/util/unix.c create mode 100644 libatalk/vfs/Makefile.am create mode 100644 libatalk/vfs/Makefile.in create mode 100644 libatalk/vfs/acl.c create mode 100644 libatalk/vfs/ea_ad.c create mode 100644 libatalk/vfs/ea_sys.c create mode 100644 libatalk/vfs/extattr.c create mode 100644 libatalk/vfs/unix.c create mode 100644 libatalk/vfs/vfs.c create mode 100644 libevent/ChangeLog create mode 100644 libevent/Doxyfile create mode 100644 libevent/LICENSE create mode 100644 libevent/Makefile.am create mode 100644 libevent/Makefile.in create mode 100644 libevent/Makefile.nmake create mode 100644 libevent/README create mode 100644 libevent/WIN32-Code/event2/event-config.h create mode 100644 libevent/WIN32-Code/tree.h create mode 100644 libevent/aclocal.m4 create mode 100644 libevent/arc4random.c create mode 100755 libevent/autogen.sh create mode 100644 libevent/buffer.c create mode 100644 libevent/buffer_iocp.c create mode 100644 libevent/bufferevent-internal.h create mode 100644 libevent/bufferevent.c create mode 100644 libevent/bufferevent_async.c create mode 100644 libevent/bufferevent_filter.c create mode 100644 libevent/bufferevent_openssl.c create mode 100644 libevent/bufferevent_pair.c create mode 100644 libevent/bufferevent_ratelim.c create mode 100644 libevent/bufferevent_sock.c create mode 100644 libevent/changelist-internal.h create mode 100644 libevent/compat/sys/queue.h create mode 100644 libevent/config.h.in create mode 100755 libevent/configure create mode 100644 libevent/configure.in create mode 100644 libevent/defer-internal.h create mode 100644 libevent/devpoll.c create mode 100644 libevent/epoll.c create mode 100644 libevent/epoll_sub.c create mode 100644 libevent/evbuffer-internal.h create mode 100644 libevent/evdns.c create mode 100644 libevent/evdns.h create mode 100644 libevent/event-internal.h create mode 100644 libevent/event.c create mode 100644 libevent/event.h create mode 100644 libevent/event_iocp.c create mode 100755 libevent/event_rpcgen.py create mode 100644 libevent/event_tagging.c create mode 100644 libevent/evhttp.h create mode 100644 libevent/evmap-internal.h create mode 100644 libevent/evmap.c create mode 100644 libevent/evport.c create mode 100644 libevent/evrpc-internal.h create mode 100644 libevent/evrpc.c create mode 100644 libevent/evrpc.h create mode 100644 libevent/evsignal-internal.h create mode 100644 libevent/evthread-internal.h create mode 100644 libevent/evthread.c create mode 100644 libevent/evthread_pthread.c create mode 100644 libevent/evthread_win32.c create mode 100644 libevent/evutil.c create mode 100644 libevent/evutil.h create mode 100644 libevent/evutil_rand.c create mode 100644 libevent/ht-internal.h create mode 100644 libevent/http-internal.h create mode 100644 libevent/http.c create mode 100644 libevent/include/Makefile.am create mode 100644 libevent/include/Makefile.in create mode 100644 libevent/include/event2/buffer.h create mode 100644 libevent/include/event2/buffer_compat.h create mode 100644 libevent/include/event2/bufferevent.h create mode 100644 libevent/include/event2/bufferevent_compat.h create mode 100644 libevent/include/event2/bufferevent_ssl.h create mode 100644 libevent/include/event2/bufferevent_struct.h create mode 100644 libevent/include/event2/dns.h create mode 100644 libevent/include/event2/dns_compat.h create mode 100644 libevent/include/event2/dns_struct.h create mode 100644 libevent/include/event2/event.h create mode 100644 libevent/include/event2/event_compat.h create mode 100644 libevent/include/event2/event_struct.h create mode 100644 libevent/include/event2/http.h create mode 100644 libevent/include/event2/http_compat.h create mode 100644 libevent/include/event2/http_struct.h create mode 100644 libevent/include/event2/keyvalq_struct.h create mode 100644 libevent/include/event2/listener.h create mode 100644 libevent/include/event2/rpc.h create mode 100644 libevent/include/event2/rpc_compat.h create mode 100644 libevent/include/event2/rpc_struct.h create mode 100644 libevent/include/event2/tag.h create mode 100644 libevent/include/event2/tag_compat.h create mode 100644 libevent/include/event2/thread.h create mode 100644 libevent/include/event2/util.h create mode 100644 libevent/iocp-internal.h create mode 100644 libevent/ipv6-internal.h create mode 100644 libevent/kqueue.c create mode 100644 libevent/libevent.pc.in create mode 100644 libevent/libevent_openssl.pc.in create mode 100644 libevent/libevent_pthreads.pc.in create mode 100644 libevent/listener.c create mode 100644 libevent/log-internal.h create mode 100644 libevent/log.c create mode 100644 libevent/m4/acx_pthread.m4 create mode 100644 libevent/m4/libtool.m4 create mode 100644 libevent/m4/ltoptions.m4 create mode 100644 libevent/m4/ltsugar.m4 create mode 100644 libevent/m4/ltversion.m4 create mode 100644 libevent/m4/lt~obsolete.m4 create mode 100644 libevent/minheap-internal.h create mode 100644 libevent/mm-internal.h create mode 100644 libevent/poll.c create mode 100644 libevent/ratelim-internal.h create mode 100644 libevent/sample/Makefile.am create mode 100644 libevent/sample/Makefile.in create mode 100644 libevent/sample/dns-example.c create mode 100644 libevent/sample/event-test.c create mode 100644 libevent/sample/hello-world.c create mode 100644 libevent/sample/http-server.c create mode 100644 libevent/sample/le-proxy.c create mode 100644 libevent/sample/signal-test.c create mode 100644 libevent/sample/time-test.c create mode 100644 libevent/select.c create mode 100644 libevent/signal.c create mode 100644 libevent/strlcpy-internal.h create mode 100644 libevent/strlcpy.c create mode 100644 libevent/test/Makefile.am create mode 100644 libevent/test/Makefile.in create mode 100644 libevent/test/Makefile.nmake create mode 100644 libevent/test/bench.c create mode 100644 libevent/test/bench_cascade.c create mode 100644 libevent/test/bench_http.c create mode 100644 libevent/test/bench_httpclient.c create mode 100644 libevent/test/regress.c create mode 100644 libevent/test/regress.gen.c create mode 100644 libevent/test/regress.gen.h create mode 100644 libevent/test/regress.h create mode 100644 libevent/test/regress.rpc create mode 100644 libevent/test/regress_buffer.c create mode 100644 libevent/test/regress_bufferevent.c create mode 100644 libevent/test/regress_dns.c create mode 100644 libevent/test/regress_et.c create mode 100644 libevent/test/regress_http.c create mode 100644 libevent/test/regress_iocp.c create mode 100644 libevent/test/regress_listener.c create mode 100644 libevent/test/regress_main.c create mode 100644 libevent/test/regress_minheap.c create mode 100644 libevent/test/regress_rpc.c create mode 100644 libevent/test/regress_ssl.c create mode 100644 libevent/test/regress_testutils.c create mode 100644 libevent/test/regress_testutils.h create mode 100644 libevent/test/regress_thread.c create mode 100644 libevent/test/regress_util.c create mode 100644 libevent/test/regress_zlib.c create mode 100755 libevent/test/rpcgen_wrapper.sh create mode 100644 libevent/test/test-changelist.c create mode 100644 libevent/test/test-eof.c create mode 100644 libevent/test/test-init.c create mode 100644 libevent/test/test-ratelim.c create mode 100644 libevent/test/test-time.c create mode 100644 libevent/test/test-weof.c create mode 100755 libevent/test/test.sh create mode 100644 libevent/test/tinytest.c create mode 100644 libevent/test/tinytest.h create mode 100644 libevent/test/tinytest_local.h create mode 100644 libevent/test/tinytest_macros.h create mode 100644 libevent/util-internal.h create mode 100644 libevent/whatsnew-2.0.txt create mode 100644 libevent/win32select.c create mode 100644 ltmain.sh create mode 100644 macros/Makefile.am create mode 100644 macros/Makefile.in create mode 100644 macros/afs-check.m4 create mode 100644 macros/ax_pthread.m4 create mode 100644 macros/cnid-backend.m4 create mode 100644 macros/config-checks.m4 create mode 100644 macros/db3-check.m4 create mode 100644 macros/grep-check.m4 create mode 100644 macros/gssapi-check.m4 create mode 100644 macros/iconv.m4 create mode 100644 macros/largefile-check.m4 create mode 100644 macros/libgcrypt.m4 create mode 100644 macros/libtool.m4 create mode 100644 macros/ltoptions.m4 create mode 100644 macros/ltsugar.m4 create mode 100644 macros/ltversion.m4 create mode 100644 macros/lt~obsolete.m4 create mode 100644 macros/netatalk.m4 create mode 100644 macros/pam-check.m4 create mode 100644 macros/perl-check.m4 create mode 100644 macros/ps-check.m4 create mode 100644 macros/quota-check.m4 create mode 100644 macros/ssl-check.m4 create mode 100644 macros/summary.m4 create mode 100644 macros/tcp-wrappers.m4 create mode 100644 macros/util.m4 create mode 100644 macros/zeroconf.m4 create mode 100644 man/Makefile.am create mode 100644 man/Makefile.in create mode 100644 man/man1/Makefile.am create mode 100644 man/man1/Makefile.in create mode 100644 man/man1/ad.1.in create mode 100644 man/man1/afpldaptest.1.in create mode 100644 man/man1/afppasswd.1.in create mode 100644 man/man1/afpstats.1.in create mode 100644 man/man1/apple_dump.1.in create mode 100644 man/man1/asip-status.pl.1.in create mode 100644 man/man1/dbd.1.in create mode 100644 man/man1/macusers.1.in create mode 100644 man/man1/netatalk-config.1.in create mode 100644 man/man1/uniconv.1.in create mode 100644 man/man5/Makefile.am create mode 100644 man/man5/Makefile.in create mode 100644 man/man5/afp.conf.5.in create mode 100644 man/man5/afp_signature.conf.5.in create mode 100644 man/man5/afp_voluuid.conf.5.in create mode 100644 man/man5/extmap.conf.5.in create mode 100644 man/man8/Makefile.am create mode 100644 man/man8/Makefile.in create mode 100644 man/man8/afpd.8.in create mode 100644 man/man8/cnid_dbd.8.in create mode 100644 man/man8/cnid_metad.8.in create mode 100644 man/man8/netatalk.8.in create mode 100755 missing create mode 100644 test/Makefile.am create mode 100644 test/Makefile.in create mode 100644 test/afpd/Makefile.am create mode 100644 test/afpd/Makefile.in create mode 100644 test/afpd/afpfunc_helpers.c create mode 100644 test/afpd/afpfunc_helpers.h create mode 100644 test/afpd/subtests.c create mode 100644 test/afpd/subtests.h create mode 100644 test/afpd/test.c create mode 100644 test/afpd/test.h create mode 100755 test/afpd/test.sh create mode 100755 ylwrap diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..4af9ae2 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,106 @@ +Lots of thanks to the following people who've made Netatalk what it is +with their contributions. Cheers. + +Original Authors, pre-Sourceforge. + +Thanks a bunch folks, where ever you are. + + Wesley Craig + Adrian Sun + Steve Hirsch: ProDOS II support/initial Randnum support + Robert Marinchick: initial rquota patch + Frank Morton: megatron information patch + Tim Carlson: Solaris testing + iNOUE Koichi: RPM for RedHat systems + Stefan Bethke: FreeBSD + Leland Wallace + +Recent Contributors since Sourceforge + +Sourceforge Administration: + Jeffrey Buchbinder + Matthew Keller + +Developers: Version 1.4.99 - 1.5 + Alain Richard + David R Bosso + Joe Clarke + Jonathan Newman + Lance Levsen + Matthew Keller + Andrew Morgan + Daniel E. Lautenschleger + Jeffrey Buchbinder + Sam Noble + Simon Bazley + Sebastian Rittau + Steve Freitas + Uwe Hees + Benjamin Heitmann + Bob Rogers + Burkhard Schmidt + Glenn Trewitt + Olaf Hering + Robert Cohen + Robert Stickel + Sumit + +Webmin Module: + Matthew Keller + +Package Maintainers: + Sebastian Rittau (RPM, Debian) + Joe Clarke (FreeBSD) + +Sourceforge Website Maintainers: + Andrew Morgan + +Documentation: Version 1.4.99 - 1.5 + Steve Freitas + Karen A Swanberg + Lance Levsen + Andrew Morgan + Jeffrey Buchbinder + Gjermund G Thorsen + Paul Krohn + Ryan McBeth + Simon Bazley + Rob Lineweaver + Alistair Riddell + Edmund Lam + +Bug Reports: Version 1.4.99 - 1.5 + Ryan Dooley + Don Jessup + Kevin M. Myer + Lawrence Farr" + Ralph Hackl + Adrian Moir + Akop Pogosian + Alistair Riddell + Axel Rose + Benjamin Lee + Brice D Ruth + Carsten Rogas + Daniel Resare + Derrik Pates + Edmund Lam + Gjermund Gusland Thorsen <90167484@mobilpost.com> + Ian Wehrman + Magnus Stenman + Mark Guertin + Matthew Geier + Miro Jurisic + Roland Schulz + Simon Roberts + Steven Karel + Thomas Schierle + + Roger + + +And thanks to everyone on the netatalk-devel and netatalk-docs +lists. If you feel you should be listed here and aren't, please let me +know, Lance Levsen, l.levsen@printwest.com + +Cheers. \ No newline at end of file diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..c826fe2 --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,120 @@ +Lots of thanks to the following people who've made Netatalk what it is +with their contributions. Cheers. + +Original Authors, pre-Sourceforge. + +Thanks a bunch folks, wherever you are. + + Wesley Craig + Adrian Sun + Steve Hirsch : ProDOS II support/initial Randnum + support + Robert Marinchick: initial rquota patch + Frank Morton: megatron information patch + Tim Carlson: Solaris testing + iNOUE Koichi: RPM for RedHat systems + Stefan Bethke: FreeBSD + Leland Wallace + Gerry Tomlinson : + original afile/achfile/acleandir implementation + +Recent Contributors since Sourceforge + +Sourceforge Administration: + Jeffrey Buchbinder + Matthew Keller + +Developers: Version 1.4.99 - 2.0 + Alain Richard + David R Bosso + Joe Clarke + Jonathan Newman + Lance Levsen + Matthew Keller + Andrew Morgan + Daniel E. Lautenschleger + Jeffrey Buchbinder + Sam Noble + Simon Bazley + Sebastian Rittau + Steve Freitas + Uwe Hees + Benjamin Heitmann + Bob Rogers + Burkhard Schmidt + Glenn Trewitt + Olaf Hering + Robert Cohen + Robert Stickel + Sumit Bose + Brandon Warren + Dan Wilga + Rafal Lewczuk + Didier Gautheron + Joerg Lenneis + Bjoern Fernhomberg + +Webmin Module: + Matthew Keller + +Package Maintainers and Contributors: + Sebastian Rittau (Debian GNU/Linux) + Jonas Smedegaard (Debian GNU systems) + Joe Clarke (FreeBSD) + David Rankin (NetBSD) + +Sourceforge Website Maintainers: + Andrew Morgan + +Documentation: Version 1.4.99 - 2.0 + Steve Freitas + Karen A Swanberg + Lance Levsen + Andrew Morgan + Jeffrey Buchbinder + Gjermund G Thorsen + Paul Krohn + Ryan McBeth + Simon Bazley + Rob Lineweaver + Alistair Riddell + Edmund Lam + Sebastian Rittau + Chris Blake + Thomas Kaiser + +Bug Reports: Version 1.4.99 - 2.0 + Ryan Dooley + Don Jessup + Kevin M. Myer + Lawrence Farr" + Ralph Hackl + Adrian Moir + Akop Pogosian + Alistair Riddell + Axel Rose + Benjamin Lee + Brice D Ruth + Carsten Rogas + Daniel Resare + Derrik Pates + Edmund Lam + Gjermund Gusland Thorsen <90167484@mobilpost.com> + Ian Wehrman + Magnus Stenman + Mark Guertin + Matthew Geier + Miro Jurisic + Roland Schulz + Simon Roberts + Steven Karel + Thomas Schierle + + Roger + + +And thanks to everyone on the netatalk-devel and netatalk-docs +lists. If you feel you should be listed here and aren't, please let +us know. + +Cheers! diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..7400d7d --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,46 @@ +Copyright (c) 1990,1996 Regents of The University of Michigan. +All Rights Reserved. + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appears in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation, and that the name of The University + of Michigan not be used in advertising or publicity pertaining to + distribution of the software without specific, written prior + permission. This software is supplied as is without expressed or + implied warranties of any kind. + +This product includes software developed by the University of +California, Berkeley and its contributors. + +Solaris code is encumbered by the following: + Copyright (C) 1996 by Sun Microsystems Computer Co. + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation. This software is + provided "as is" without express or implied warranty. + +Modifications for Appleshare IP and other files copyrighted by Adrian +Sun are under the following copyright: + + Copyright (c) 1997,1998,1999,2000 Adrian Sun (asun@cobalt.com) + All Rights Reserved. + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appears in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. This software is supplied as is + without expressed or implied warranties of any kind. + +Research Systems Unix Group +The University of Michigan +c/o Wesley Craig +535 W. William Street +Ann Arbor, Michigan ++1-313-764-2278 +netatalk@umich.edu diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..ec7f14d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,25 @@ +# Makefile.am for top level of netatalk package + +if USE_BUILTIN_LIBEVENT +SUBDIRS = libevent include libatalk bin config etc contrib distrib doc man macros test +else +SUBDIRS = include libatalk bin config etc contrib distrib doc man macros test +endif + +EXTRA_DIST = CONTRIBUTORS COPYRIGHT COPYING NEWS VERSION abigen.sh + +ACLOCAL_AMFLAGS = -I macros +AUTOMAKE_OPTIONS = foreign + +if RUN_LDCONFIG +install-exec-hook: + @printf "Running ldconfig to ensure libraries installed in system library directories are added to the dynamic linker cache ... " + @-@NETA_LDCONFIG@ + @printf "done\n" +endif + +if DEVELOPER +abi-clean: + @echo "Removing ABI file libatalk/libatalk-$(NETATALK_VERSION).abi" + @rm -f libatalk/libatalk-$(NETATALK_VERSION).abi +endif diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..d8570dd --- /dev/null +++ b/Makefile.in @@ -0,0 +1,912 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for top level of netatalk package +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = . +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure AUTHORS COPYING NEWS compile \ + config.guess config.sub depcomp install-sh ltmain.sh missing \ + ylwrap +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + cscope distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = include libatalk bin config etc contrib distrib doc man \ + macros test libevent +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_BUILTIN_LIBEVENT_FALSE@SUBDIRS = include libatalk bin config etc contrib distrib doc man macros test +@USE_BUILTIN_LIBEVENT_TRUE@SUBDIRS = libevent include libatalk bin config etc contrib distrib doc man macros test +EXTRA_DIST = CONTRIBUTORS COPYRIGHT COPYING NEWS VERSION abigen.sh +ACLOCAL_AMFLAGS = -I macros +AUTOMAKE_OPTIONS = foreign +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) + +clean-cscope: + -rm -f cscope.files + +cscope.files: clean-cscope cscopelist-recursive cscopelist + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@RUN_LDCONFIG_FALSE@install-exec-hook: +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + cscopelist-recursive ctags-recursive install-am \ + install-exec-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-cscope \ + clean-generic clean-libtool cscope cscopelist \ + cscopelist-recursive ctags ctags-recursive dist dist-all \ + dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \ + dist-zip distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-hook \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am + + +@RUN_LDCONFIG_TRUE@install-exec-hook: +@RUN_LDCONFIG_TRUE@ @printf "Running ldconfig to ensure libraries installed in system library directories are added to the dynamic linker cache ... " +@RUN_LDCONFIG_TRUE@ @-@NETA_LDCONFIG@ +@RUN_LDCONFIG_TRUE@ @printf "done\n" + +@DEVELOPER_TRUE@abi-clean: +@DEVELOPER_TRUE@ @echo "Removing ABI file libatalk/libatalk-$(NETATALK_VERSION).abi" +@DEVELOPER_TRUE@ @rm -f libatalk/libatalk-$(NETATALK_VERSION).abi + +# 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/NEWS b/NEWS new file mode 100644 index 0000000..30fe9bd --- /dev/null +++ b/NEWS @@ -0,0 +1,1541 @@ +Changes in 3.1.7 +================ +* UPD: Spotlight: enhance behaviour for long running queries, client + will now show "progress wheel" while waiting for first results. +* FIX: netatalk: fix a crash on Solaris when registering with mDNS +* FIX: netatalk: SIGHUP would kill the process instead of being resent + to the other Netatalk processes, bug #579 +* FIX: afpd: Solaris locking problem, bug #559 +* FIX: Handling of malformed UTF8 strings, bug #524 +* FIX: afpd: umask handling, bug #576 +* FIX: Spotlight: Limiting searches to subfolders, bug #581 +* FIX: afpd: reloading logging config may result in privilege + escalation in afpd processes +* FIX: afpd: ACL related error messages, now logged with loglevel + debug instead of error +* FIX: cnid_metad: fix tsockfd_create() return value on error +* FIX: CNID/MySQL: volume table name generation, bug #566. + +Changes in 3.1.6 +================ +* FIX: Spotlight: fix for long running queries +* UPD: afpd: distribute SIGHUP from parent afpd to children and force + reload shares +* FIX: netatalk: refresh Zeroconf registration when receiving SIGHUP +* NEW: configure option "--with-init-style=debian-systemd" for Debian 8 jessie + and later. + "--with-init-style=debian" is renamed "--with-init-style=debian-sysv". + +Changes in 3.1.5 +================ +* FIX: Spotlight: several important fixes + +Changes in 3.1.4 +================ +* FIX: afpd: Hangs in Netatalk which causes it to stop responding to + connections, bug #572. +* NEW: afpd: new option "force xattr with sticky bit = yes|no" + (default: no), FR #94 +* UPD: afpd: FCE version 2 with new event types and new config options + "fce ignore names" and "fce notify script" +* UPD: afpd: check for modified included config file, FR #95. +* UPD: libatalk: logger: remove flood protection and allocate messages +* UPD: Spotlight: use async Tracker SPARQL API +* NEW: afpd: new option "case sensitive = yes|no" (default: yes) + In spite of being case sensitive as a matter of fact, netatalk + 3.1.3 and earlier did not notify kCaseSensitive flag to the client. + Now, it is notified correctly by default, FR #62. + +Changes in 3.1.3 +================ +* UPD: Spotlight: more SPARQL query optimisations +* UPD: Spotlight: new options "sparql results limit", "spotlight + attributes" and "spotlight expr" +* FIX: afpd: Unarchiving certain ZIP archives fails, bug #569 +* UPD: Update Unicode support to version 7.0.0 +* FIX: Memory overflow caused by 'basedir regex', bug #567 +* NEW: afpd: delete empty resource forks, from FR #92 +* FIX: afpd: fix a crash when accessing ._ AppleDouble files created + by OS X via SMB, bug #564 +* FIX: afpd and dbd: Converting from AppleDouble v2 to ea may corrupt + the resource fork. In some circumstances an offset calculation + is wrong resulting in corrupt resource forks after the + conversion. Bug #568. +* FIX: ad: fix for bug #563 broke ad file utilities, bug #570. +* NEW: afpd: new advanced option controlling permissions and ACLs, + from FR #93 + +Changes in 3.1.2 +================ +* FIX: Option "vol dbpath" was broken in 3.1.1 +* FIX: Spotlight: file modification date, bug #545 +* FIX: Improve reliability of afpd child handler +* FIX: debian initscript: add 0 and 6 to Default-Stop. debian-bug#745520 +* FIX: put the Solaris share reservation after our locking stuff, bug #560. +* UPD: Improve Linux quota behaviour +* FIX: xattrs on *BSD, bug #562 +* NEW: afpd: support for using $u username variable in AFP volume + definitions. FR#90. +* FIX: getvolbypath returns incorrect volume, bug #563 +* FIX: fd leak when using appledouble = v2, bug #554 +* UPD: New options that control whether dbus and Tracker are started: + 'start dbus' and 'start tracker', both default to yes, FR#91 +* UPD: Spotlight: SPARQL query optimisations + +Changes in 3.1.1 +================ +* FIX: Add asprint() compatibility function for systems lacking it +* FIX: Fix ressource fork name conversion. Bug #534. +* FIX: Fix a bug where only the first configured UAM was loaded. + Bug #537. +* UPD: Add support for AFP 3.4. From FR #85. +* FIX: Registering with mDNS crashed. Bug #540 +* FIX: Saving from applications like Photoshop may fail, because + removing the ressource fork AppleDouble file failed. Bug #542. +* FIX: dbd: remove orphaned ._ AppleDouble files. Bug #549. +* NEW: afpd: Automatic conversion of ._ AppleDouble files + created by OS X. Bug #550. +* FIX: afpd: Fix a crash in of_closefork(). Bug #551. +* FIX: dbd: Don't print message "Ignoring ._file" for every ._ file. + Bug #552. +* FIX: afpd: Don't flood log with failed sys_set_ea() messages. + +Changes in 3.1.0 +================ +* NEW: AFP Spotlight support with Gnome Tracker +* NEW: New option "spotlight" (G/V) +* NEW: Configure option --with-tracker-pkgconfig-version +* NEW: Configure option --with-tracker-prefix +* NEW: If Spotlight is enabled, launch our own dbus instance +* NEW: New option "dbus daemon" (G) +* UPD: Add configure option --with-afpstats for overriding the + result of autodetecting dbus-glib presence +* NEW: Add recvfile support with splice() on Linux. New global options + "recvfile" (default: no) and "splice size" (default 64k). +* NEW: CNID backend "mysql" for use with a MySQL server + +Changes in 3.0.7 +================ +* FIX: Build fixes for the Kerberos UAM +* UPD: Use dedicated exit code for AFP connections that were dropped + by the client right after the TCP handshake +* FIX: Workaround for a problem which cannot be advertized by Avahi. Bug #541. +* FIX: Registering with mDNS crashed. Bug #540 +* FIX: Saving from applications like Photoshop may fail, because + removing the ressource fork AppleDouble file failed. Bug #542. +* FIX: macusers showed root user. Bug #495. +* UPD: Add file pathname to logmessage parse_entries: bogus eid. FR#87. + +Changes in 3.0.6 +================ +* FIX: charset conversion failed when copying from Mac OS 9. Bug #523. +* UPD: Don't force S_ISGID for directories on FreeBSD. Bug #525. +* NEW: Add support for ZFS ACLs on FreeBSD with libsunacl. From FR#83. +* FIX: Active Directory LDAP queries for ACL support with new options + "ldap user filter" and "ldap group filter". Bug #526. +* NEW: Option "vol dbnest", when set to true, the CNID database for + a volume is stored in the volume root of a share in a directory + .AppleDB like in Netatalk 2. Defaults to false. From FR#84. +* FIX: Small fix in the DSI tickle handling. Bug #528. +* UPD: Enhance handling of connection attempts when hitting the + connection limit. Bug #529. +* FIX: Saving from Word to a folder that is a symlink to a folder on + another filesystem results in a crash of the afpd process and + the save to fail. This happens only if the option + "follow symlinks" is enabled. Bug #532. +* FIX: Disable Kerberos UAM if AFP service principal name can't be + evaluated. Fixes bug #531. +* FIX: Fix handling of large number of volumes. Bug #527. +* NEW: Configure option --with-tbd which can be used to disable the + use of the bundled tdb and use a system installed version. + +Changes in 3.0.5 +================ +* FIX: Fix a crash when using pam_winbind. Fixes bug #516. +* NEW: New global/volume option "ignored attributes" +* FIX: "afp listen" option failed to take IPv6 addresses. Bug #515. +* FIX: Fix a possible crash in set_groups. Bug #518. +* NEW: Send optional AFP messages for vetoed files, new option + "veto message" can be used to enable sending messages. + Then whenever a client tries to access any file or directory + with a vetoed name, it will be sent an AFP message indicating + the name and the directory. From FR #81. +* NEW: New boolean volume option "delete veto files". If this option is + set to yes, then Netatalk will attempt to recursively delete any + vetoed files and directories. FR #82. +* UPD: systemd unit dir is /usr/lib/systemd/system . +* FIX: Saving files from application like MS Word may result in the file + loosing metadata like the Finder label. Bug #521. + +Changes in 3.0.4 +================ +* FIX: Opening files without metadata EA may result in an invalid + metadata EA. Check for malformed metadata EAs and delete them. + Fixes bug #510. +* FIX: Fix an issue with filenames containing non-ASCII characters that + lead to a failure setting the size of a files ressource fork. + This affected application like Adobe Photoshop where saving + files may fail. Fixes bug #511. +* UPD: Enhance ACL mapping, change global ACL option 'map acls' to take + the following options: "none", "rights" (default), "mode". + none = no mapping, this resembles the previous false/no setting + rights = map ACLs to Finder UARights, this resembles the previous + true/yes setting. This is the default. + mode = map ACLs to Finder UARights and UNIX mode + From FR #73. +* FIX: Fix a possible crash in cname() where cname_mtouname calls + dirlookup() where the curdir is freed because the dircache + detected a dev/inode cache difference and evicted the object + from the cache. Fixes bug #498. +* FIX: Add missing include, fixes bug #512. +* FIX: Change default FinderInfo for directories to be all 0, fixes + bug 514. +* NEW: New option "afp interfaces" which allows specifying where + Netatalk listens for AFP connections by interface names. + From FR #79. + +Changes in 3.0.3 +================ +* UPD: afpd: Increase default DSI server quantum to 1 MB +* UPD: bundled libevent2 is now static +* NEW: --with-lockfile=PATH configure option for specifying an + alternative path for the netatalk lockfile. +* UPD: systemd service file use PIDFile and ExecReload. + From FR #70. +* UPD: RedHat sysvinit: rm graceful, reimplement reload, add condrestart +* FIX: Couldn't create folders on FreeBSD 9.1 ZFS fileystems. + Fixed bug #491. +* FIX: Fix an issue with user homes when user home directory has not the + same name as the username. + Fixes bug #497. +* UPD: Fix PAM config install, new default installation dir is + $sysconfdir/pam.d/. Add configure option --with-pam-confdir + to specify alternative path. +* NEW: AFP stats about active session via dbus IPC. Client side python + program `afpstats`. Requires dbus, dbus-glib any python-dbus. + configure option --dbus-sysconf-dir for specifying dbus + system security configuration files. + New option 'afpstats' (default: no) which determines whether + to enable the feature or not. +* NEW: configure option --with-init-dir +* NEW: dtrace probes, cf include/atalk/afp_dtrace.d for available + probes. +* UPD: Reload groups when reloading volumes. FR #71. +* FIX: Attempt to read read-only ._ rfork results in disconnect. + Fixes bug #502. +* FIX: File's ressource fork can't be read if metadata EA is missing. + Fixes bug #501. +* FIX: Conversion from adouble v2 to ea for directories. + Fixes bug #500. +* FIX: Error messages when mounting read-only filesystems. + Fixes bug #504. +* FIX: Permissions of ._ AppleDouble ressource fork after conversion + from v2 to ea. + Fixes bug #505. +* UPD: Use FreeBSD sendfile() capability to send protocol header. + From FR #75. +* UPD: Increase IO size when sendfile() is not used. + From FR #76. +* FIX: Can't set Finder label on symlinked folder with "follow symlinks = yes". + Fixes bug #508. +* FIX: Setting POSIX ACLs on Linux + Fixes bug #506. +* FIX: "ad ls" segfault if requested object is not in an AFP volume. + Fixes bug #496. + +Changes in 3.0.2 +================ +* NEW: afpd: Put file extension type/creator mapping back in which had + been removed in 3.0. +* NEW: afpd: new option 'ad domain'. From FR #66. +* FIX: volumes and home share with symlinks in the path +* FIX: Copying packages to a Netatalk share could fail, bug #469 +* FIX: Reloading volumes from config file was broken. Fixes bug #474. +* FIX: Fix _device-info service type registered with dns-sd API +* FIX: Fix pathname bug for FCE modified event. +* FIX: Remove length limitation of options like "valid users". + Fixes bug #473. +* FIX: Dont copy our metadata EA in copyfile(). Fixes bug #452. +* FIX: Fix an error where catalog search gave incomplete results. + Fixes bug #479. +* REM: Remove TimeMachine volume used size FCE event. +* UPD: Add quoting support to '[in]valid users' option. Fixes bug #472. +* FIX: Install working PAM config on Solaris 11. Fixes bug #481. +* FIX: Fix a race condition between dbd and the cnid_dbd daemon + which could result in users being disconnected from volumes + when dbd was scanning their volumes. Fixes bug #477. +* FIX: Netatalk didn't start when the last line of the config file + afp.conf wasn't terminated by a newline. Fixes bug #476. +* NEW: Add a new volumes option 'follow symlinks'. The default setting is + false, symlinks are not followed on the server. This is the same + behaviour as OS X's AFP server. + Setting the option to true causes afpd to follow symlinks on the + server. symlinks may point outside of the AFP volume, currently + afpd doesn't do any checks for "wide symlinks". +* FIX: Automatic AppleDouble conversion to EAs failing for directories. + Fixes bug #486. +* FIX: dbd failed to convert appledouble files of symlinks. + Fixes bug #490. + +Changes in 3.0.1 +================ +* NEW: afpd: Optional "ldap uuid encoding = string | ms-guid" parameter to + afp.conf, allowing for usage of the binary objectGUID fields from + Active Directory. +* FIX: afpd: Fix a Solaris 10 SPARC sendfilev bug +* FIX: afpd: Fix a crash on FreeBSD +* FIX: afpd: Fixes open file handle refcounting bug which was reported as + being unable to play movies off a Netatalk AFP share. + Bug ID 3559783. +* FIX: afpd: Fix a possible data corruption when reading from and writing + to the server simultaniously under load +* FIX: Fix possible alignment violations due to bad casts +* FIX: dbd: Fix logging +* FIX: apple_dump: Extended Attributes AppleDouble support for *BSD +* FIX: handling of '/' and ':' in volume name +* UPD: Install relevant includes necessary for building programs with + installed headers and shared lib libatalk +* UPD: libevent configure args to pick up installed version. Removed + configure arg --disable-libevent, added configure args + --with-libevent-header|lib. +* UPD: gentoo initscript: merge from portage netatalk.init,v 1.1 +* REM: Remove --with-smbsharemodes configure option, it was an + empty stub not yet implemented + +Changes in 3.0 +============== + +* UPD: afpd: force read only mode if cnid scheme is last +* REM: afpd: removed global option "icon" +* FIX: CNID path for user homes + +Changes in 3.0 beta2 +==================== + +* UPD: Solaris and friends: Replace initscript with SMF manifest +* FIX: Solaris and friends: resource fork handling + +Changes in 3.0 beta1 +==================== + +* UPD: afpd: Performance tuning of read/write AFP operations. New option + "afp read locks" (default: no) which disables that the server + applies UNIX byte range locks to regions of files in AFP read and + write calls. +* UPD: apple_dump: Extended Attributes AppleDouble support. + (*BSD is not supported yet) + +Changes in 3.0 alpha3 +===================== + +* NEW: afpd: Per volume "login message", NetAFP bug ID #18 +* NEW: afpd: Cross-platform locking (share modes) on Solaris and derivates + with Solaris CIFS/SMB server. Uses new Solaris fcntl F_SHARE share + reservation locking primitives. Enabled by default, set global + "solaris share reservations" option to false to disable it. +* NEW: ad: ad set subcommand for changing Mac metadata on the server +* UPD: unix charset is UTF8 by default. + vol charset is same value as unix charset by default. +* UPD: .AppleDesktop/ are stored in $localstatedir/netatalk/CNID + (default: /var/netatalk/CNID), databases found in AFP volumes are + automatically moved +* FIX: afpd: Server info packet was malformed resulting in broken + server names being displayed on clients +* FIX: afpd: Byte order detection. Fixes an error where Netatalk on + OpenIndiana returned wrong volume size information. + +Changes in 3.0 alpha2 +===================== + +* UPD: afpd: Store '.' as is and '/' as ':' on the server, don't + CAP hexencode as "2e" and "2f" respectively +* UPD: afdp: Automatic name conversion, renaming files and directories + containing CAP sequences to their not enscaped forms +* UPD: afpd: Correct handling of user homes and users without homes +* UPD: afpd: Perform complete automatic adouble:v2 to adouble:ea conversion + as root. Previously only unlinking the adouble:v2 file was done as root +* UPD: dbd: -C option removes CAP encoding +* UPD: Add graceful option to RedHat init script +* UPD: Add --disable-bundled-libevent configure options When set to yes, + we rely on a properly installed version on libevent CPPFLAGS and LDFLAGS + should be set properly to pick that up +* UPD: Run ldconfig on Linux at the end of make install +* FIX: afpd: ad cp on appledouble = ea volumes +* FIX: dbd: ignore ._ appledouble files +* REM: Volumes options "use dots" and "hex encoding" + +Changes in 3.0 alpha1 +===================== + +* NEW: Central configuration file afp.conf which replaces all previous files +* NEW: netatalk: service controller starting and restarting afpd and cnid_metad + as necessary +* NEW: afpd: Extended Attributes AppleDouble backend (default) +* UPD: CNID databases are stored in $localstatedir/netatalk/CNID + (default: /var/netatalk/CNID), databases found in AFP volumes are + automatically moved +* UPD: Start scripts and service manifests have been changed to only start + the new netatalk service controller process +* UPD: afpd: UNIX privileges and use dots enabled by default +* UPD: afpd: Support for arbitrary AFP volumes using variable expansion has been + removed +* UPD: afpd: afp_voluuid.conf and afp_signature.conf location has been + changed to $localstatedir/netatalk/ (default: /var/netatalk/) +* UPD: afpd: default server messages dir changed to $localstatedir/netatalk/msg/ +* UPD: dbd: new option -C for conversion from AppleDouble v2 to ea +* REM: AppleTalk support has been removed +* REM: afpd: SLP and AFP proxy support have been removed +* REM: afpd: legacy file extension to type/creator mapping has been removed +* REM: afpd: AppleDouble backends v1, osx and sfm have been removed + +Changes in 2.2.4 +================ + +* FIX: Missing UAM links +* FIX: Lockup in AFP logout on Fedora 17 +* FIX: Reset signal handlers and alarm timer after successfull PAM + authentication. Fixes a problem with AFP disconnects caused + by pam_smbpass.so messing with our handlers and timer. +* FIX: afpd: Fix a possible problem with sendfile on Solaris derived + platforms + +Changes in 2.2.3 +================ + +* NEW: afpd: support for mdnsresponder +* NEW: afpd: new LDAP config option ldap_uuid_string +* UPD: based on Unicode 6.1.0 +* UPD: experimental systemd service files: always run both afpd and cnid_metad +* UPD: afpd: Ensure our umask is not altered by eg pam_umask +* UPD: afpd: Use GSS_C_NO_NAME as server principal when Kerberos options -fqdn + and -krb5service are not set, from Jamie Gilbertson +* UPD: afpd: Changed behaviour for TimeMachine volumes in case there's a problem + talking to the CNID daemons. Previously the volume was flagged read-only + and an AFP message was sent to the client. As this might result in + TimeMachine assuming the backup sparse bundle is damaged, we now just + switch the CNID database to an in-memory tdb without the additional stuff. +* FIX: afpd: sendfile() on FreeBSD was broken, courtesy of Denis Ahrens +* FIX: afpd: Dont use searchdb when doing partial name search +* FIX: afpd: Fix a possible bug handling disconnected sessions, + NetAFP Bug ID #16 +* FIX: afpd: Close IPC fds in afpd session child inherited from the afpd + master process +* FIX: dbd: Don't remove BerkeleyDB if it's still in use by eg cnid_dbd, fixes + bug introduced in 2.2.2 +* FIX: debian initscript: start avahi-daemon (if available) before atalkd +* FIX: Zeroconf could not advertise non-ASCII time machine volume name + +Changes in 2.2.2 +================ + +* NEW: afpd: New option "adminauthuser". Specifying eg "-adminauthuser root" + whenever a normal user login fails, afpd tries to authenticate as + the specified adminauthuser. If this succeeds, a normal session is + created for the original connecting user. Said differently: if you + know the password of adminauthuser, you can authenticate as any other + user. +* NEW: configure option "--enable-suse-systemd" for openSUSE12.1 and later. + "--enable-redhat-systemd" and "--enable-suse-systemd" are same as + "--enable-systemd". + "--enable-suse" is renamed "--enable-suse-sysv". +* NEW: experimental systemd service files in distrib/systemd/ +* UPD: afpd: Enhanced POSIX ACL mapping semantics, from Laura Mueller +* UPD: afpd: Reset options every time a :DEFAULT: line is found in a + AppleVolumes file +* UPD: afpd: Convert passwords from legacy encoding (wire format) to host + encoding, NetAFP Bug ID #14 +* UPD: afpd: Don't set ATTRBIT_SHARED flag for directories +* UPD: afpd: Use sendfile() on Solaris and FreeBSD for sending data +* UPD: afpd: Faster volume used size calculation for "volsizelimit" option, + cf man AppleVolume.default for details +* FIX: afpd: ACL access checking +* FIX: afpd: Fix an error when duplicating files that lacked an AppleDouble + file which lead to a possible Finder crash +* FIX: afpd: Read-only filesystems lead to afpd processes running as root +* FIX: afpd: Fix for filesystem without NFSv4 ACL support on Solaris +* FIX: afpd: Fix catsearch bug, NetAFP Bug ID #12 +* FIX: afpd: Fix dircache bug, NetAFP Bug ID #13 +* FIX: dbd: Better checking for duplicated or bogus CNIDs from AppleDouble + files +* FIX: dbd: Remove BerkeleyDB database environment after running `dbd`. This + is crucial for the automatic BerkeleyDB database upgrade feature which + is built into cnid_dbd and dbd. +* FIX: Fix compilation error when AppleTalk support is disabled +* FIX: Portability fixes +* FIX: search of surrogate pair + +Changes in 2.2.1 +================ + +* NEW: afpd: disable continous service feature by default, new option + -keepsessions to enable it +* NEW: configure option "--enable-redhat-systemd" for Fedora15 and later. + "--enable-redhat" is renamed "--enable-redhat-sysv". +* UPD: afpd: Enhance ACL support detection for volumes: enable them per volume + if + 1) ACL support compiled in, 2) the volume supports ACLs, 3) the new + volume option "noacls" is not set for the volume. + The previous behaviour was to enable ACL support for a volume if + 1) it was compiled in and 2) the volume supported ACLs. There was no way + to disable ACLs for a volume. +* UPD: afpd: add a configurable hold time option to FCE file modification event + generation, default is 60 s, new option "fceholdfmod" to change it +* UPD: afpd: add support for new NetBSD quota subsystem, Bug ID 3249879 +* FIX: afpd: increase BerkeleyDB locks and lockobjs +* FIX: afpd: create special folder as root +* FIX: afpd: fix compilation error if --enable-ddp is used +* FIX: afpd: More robust IPC reconnect error handling +* FIX: afpd: ACL access checking +* FIX: afpd: fix a possible race condition between SIGCHLD handler and + new connection attempts +* FIX: afpd: fix undefined behaviour when more then ~510 connetions where + established +* FIX: afpd: fix a crash when searching for a UUID that is not a special + local UUID and LDAP support is not compiled in +* FIX: afpd: .volinfo file not created on first volume access if user in rolist +* FIX: afpd: possible crash at startup when registering with Avahi + when Avahi is not running +* FIX: afpd: return correct user/group type when mapping UUIDs to names +* FIX: afpd: for directories add DARWIN_ACE_DELETE ACE + if DARWIN_ACE_ADD_SUBDIRECTORY is set +* FIX: afpd: afpd crashed when it failed to register with Avahi because eg + user service registration is disabled in the Avahi config +* FIX: dbd: function checking and removing malformed ad:ea header files failed + to chdir back to the original working directory +* FIX: cnid_dbd: increase BerkeleyDB locks and lockobjs +* FIX: cnid_dbd: implement -d option, deletes CNID db +* FIX: dbd: better detection of local (or SMB/NFS) modifications on AFP volumes +* FIX: suse: initscript return better status +* FIX: Sourcecode distribution: add missing headers +* FIX: Solaris 10: missing dirfd replacement function +* FIX: case-conversion of surrogate pair +* FIX: Compilation error on GNU/kFreeBSD, fixes Bug ID 3392794 and + Debian #630349 +* FIX: Fix Debian Bug#637025 +* FIX: Multiple *BSD compilation compatibility fixes, Bug ID 3380785 +* FIX: precompose_w() failed if tail character is decomposed surrogate pair + +Changes in 2.2.0 +============== + +* NEW: afpd: new volume option "nonetids" +* NEW: afpd: ACL access check caching +* NEW: afpd: FCE event notifications +* NEW: afpd: new option "-mimicmodel" for specifying Bonjour model registration +* UPD: Support for Berkeley DB 5.1 +* UPD: case-conversion is based on Unicode 6.0.0 +* UPD: cnid_metad: allow up to 4096 volumes +* UPD: afpd: only forward SIGTERM and SIGUSR1 from parent to childs +* UPD: afpd: use internal function instead of popening du -sh in order to + calculate the used size of a volume for option "volsizelimit" +* UPD: afpd: Add negative UUID caching, enhance local UUID handling +* FIX: afpd: configuration reload with SIGHUP +* FIX: afpd: crashes in the dircache +* FIX: afpd: Correct afp logout vs dsi eof behaviour +* FIX: afpd: new catsearch was broken +* FIX: afpd: only use volume UUIDs in master afpd +* FIX: dbd: Multiple fixes, reliable locking +* FIX: ad file suite: fix an error that resulted in CNID database + inconsistencies + +Changes in 2.2beta4 +=================== + +* NEW: afpd: new afpd.conf options "tcprcvbuf" and "tcpsndbuf" to customize + the corresponding TCP socket options. +* NEW: afpd: new afpd.conf option "nozeroconf" which disabled automatic + Zeroconf service registration. +* FIX: afpd: generate mersenne primes for DHX2 UAM once at startup, + not for every login +* FIX: afpd: DSI streaming deadlock +* FIX: afpd: extended sleep +* FIX: afpd: directory cache +* FIX: Support for platforms that do not have the *at functions +* UPD: afpd: put POSIX write lock on volume files while reading them + +Changes in 2.2beta3 +=================== + +* FIX: afpd: fix option volsizelimit to return a usefull value for the + volume free space using `du -sh` with popen +* FIX: afpd: fix idle connection disconnects +* FIX: afpd: don't disconnect sessions for clients if boottimes don't match +* FIX: afpd: better handling of very long filenames that contain many + multibyte UTF-8 glyphs + +Changes in 2.2beta2 +==================== + +* NEW: afpd: AFP 3.3 +* UPD: afpd: AFP 3.x can't be disabled + +Changes in 2.2beta1 +==================== + +* FIX: composition of Surrogate Pair +* UPD: gentoo,suse,cobalt,tru64: inistscript name is "netatalk", not "atalk" +* UPD: gentoo: rc-update install don't hook in the Makefile + +Changes in 2.2alpha5 +==================== + +* UPD: afpd: new option "searchdb" which enables fast catalog searches + using the CNID db. +* UPD: Case-insensitive fast search with the CNID db +* UPD: cnid_dbd: afpd now passes the volume path, not the db path when + connecting for a volume. cnid_dbd will read the + ".AppleDesktop/.volinfo" file of the volume in order to figure + out the CNID db path and the volume charset encoding. + +Changes in 2.2alpha4 +==================== + +* NEW: Enhanced CNID "dbd" database for fast name search support. + Important: this makes cnidscheme "cdb" incompatible with "dbd". +* NEW: afpd: support for fast catalog searches +* NEW: ad utility: ad find +* UPD: afpd: CNID database versioning check for "cdb" scheme +* UPD: cnid_dbd: CNID database versioning and upgrading. Additional + CNID database index for fast name searches. + +Changes in 2.2alpha3 +==================== + +* FIX: afpd: various fixes +* FIX: Any daemon did not run if atalkd doesn't exist (redhat/debian) + +Changes in 2.2alpha2 +==================== + +* FIX: afpd: fix compilation error when ACL support is not available +* FIX: Ensure Appletalk manpages and config files are distributed + +Changes in 2.2alpha1 +==================== + +* NEW: ad utility: ad cp +* NEW: ad utility: ad rm +* NEW: ad utility: ad mv +* NEW: afpd: dynamic directoy and CNID cache (new config option -dircachesize) +* NEW: afpd: POSIX 1e ACL support +* NEW: afpd: automagic Zeroconf registration with avahi, registering both + the service _afpovertcp._tcp and TimeMachine volumes with _adisk._tcp. +* UPD: afpd: ACLs usable (though not visible on the client side) without common + directory service, by mapping ACLs to UARight +* UPD: afpd: performance improvements for ACL access calculations +* UPD: AppleTalk is disabled by default at configuration time. If needed + use configure switch --enable-ddp. +* FIX: afpd: Solaris 10 compatibilty fix: don't use SO_SNDTIMEO/SO_RCVTIMEO, + use non-blocking IO and select instead. +* FIX: cnid_dbd: Solaris 10 compatibilty fix: don't use SO_SNDTIMEO/SO_RCVTIMEO, + use non-blocking IO and select instead. +* REM: afile/achfile/apple_cp/apple_mv/apple_rm: use ad + +Changes in 2.1.6 +================ + +* FIX: afpd: Fix for LDAP user cache corruption +* FIX: afpd: Fix for not shown ACLs for when filesyem uid or gid + couldn't be resolved because (eg deleted users/groups) +* FIX: gentoo: cannot set $CNID_CONFIG +* FIX: ubuntu: servername was empty +* FIX: Solaris: configure script failed to enable DDP module +* FIX: AppleDouble buffer overrun by extremely long filename +* UPD: afpd: return version info with machine type in DSIGetStatus +* UPD: dbd: use on-disk temporary rebuild db instead of in-memory db +* UPD: suse: initscript update + +Changes in 2.1.5 +================ + +* UPD: afpd: support newlines in -loginmesg with \n escaping syntax +* UPD: afpd: support for changed chmod semantics on ZFS with ACLs + in onnv145+ +* FIX: afpd: fix leaking ressource when moving objects on the server +* FIX: afpd: backport Solaris 10 compatibilty fix from 2.2: don't use + SO_SNDTIMEO/SO_RCVTIMEO, use non-blocking IO and select instead. +* FIX: afpd: misaligned memory access on Sparc in ad_setattr, fixes + bug 3110004. +* FIX: cnid_dbd: backport Solaris 10 compatibilty fix from 2.2: don't + use SO_SNDTIMEO/SO_RCVTIMEO, use non-blocking IO and select instead. + +Changes in 2.1.4 +================ + +* FIX: afpd: Downstream fix for FreeBSD PR 148022 +* FIX: afpd: Fixes for bugs 3074077 and 3074078 +* FIX: afpd: Better handling of symlinks in combination with ACLs and EAs. + Fixes bug 3074076. +* FIX: dbd: Adding a file with the CNID from it's adouble file did + not work in case that CNID was already occupied in the database +* FIX: macusers: add support for Solaris +* NEW: cnid_metad: use a PID lockfile +* NEW: afpd: prevent log flooding +* UPD: dbd: ignore ".zfs" snapshot directories +* UPD: dbd: support interrupting -re mode + +Changes in 2.1.3 +================ + +* FIX: afpd: fix a serious error in networking IO code +* FIX: afpd: Solaris 10 compatibilty fix: don't use SO_SNDTIMEO, use + non-blocking IO and select instead for writing/sending data. +* UPD: Support for BerkeleyDB 5.0. + +Changes in 2.1.2 +================ + +* FIX: afpd: fix for possible crash in case more then one server is + configured in afpd.conf. +* FIX: afpd: ExtendedAttributes in FreeBSD +* FIX: afpd: sharing home folders corrupted the per volume umask. +* UPD: afpd: umask for home folders is no longer taken from startup umask. +* UPD: afpd: dont and permissions with parent folder when creating new + directories on "upriv" volumes. +* UPD: afpd: use 'afpserver@fqdn' instead of 'afpserver/fqdn@realm'. + Prevents a crash in older GNU GSSAPI libs on eg. CentOS 5.x. + +Changes in 2.1.1 +================ + +* UPD: fallback to a temporary in memory tdb CNID database if the volume + database can't be opened now works with the default backend "dbd" too. +* FIX: afpd: afp_ldap.conf was missing from tarball. This only effected + [Open]Solaris. +* FIX: afpd: Check if options->server is set in set_signature, preventing + SIGSEGV. +* FIX: afpd: server signature wasn't initialized in some cases +* FIX: DESTDIR support: DESTDIR was expanded twice +* FIX: Fix for compilation error if header files of an older Netatalk + version are installed. + +Changes in 2.1-release +====================== + +* NEW: afpd: new volume option "volsizelimit" for limitting reported volume + size. Useful for limitting TM backup size. +* UPD: dbd: -c option for rebuilding volumes which prevents the creation + of .AppleDouble stuff, only removes orphaned files. + +Changes in 2.1-beta2 +==================== + +* NEW: afpd: static generated AFP signature stored in afp_signature.conf, + cf man 5 afp_signature.conf +* NEW: afpd: clustering support: new per volume option "cnidserver". +* UPD: afpd: set volume defaults options "upriv" and "usedots" in the + volume config file AppleVolumes.default. This will only affect + new installations, but not upgrades. +* FIX: afpd: prevent security attack guessing valid server accounts. afpd + now returns error -5023 for unknown users, as does AppleFileServer. + +Changes in 2.1-beta1 +==================== + +* NEW: afpd: AFP 3.2 support +* NEW: afpd: Extended Attributes support using native attributes or + using files inside .AppleDouble directories. +* NEW: afpd: ACL support with ZFS +* NEW: cnid_metad: options -l and -f to configure logging +* NEW: IPv6 support +* NEW: AppleDouble compatible UNIX files utility suite `ad ...`. + With 2.1 only `ad ls`. +* NEW: CNID database maintanance utility dbd +* NEW: support BerkeleyDB upgrade. Starting with the next release + after 2.1 in case of BerkeleyDB library updates, Netatalk + will be able to upgrade the CNID databases. +* NEW: afpd: store and read CNIDs to/from AppleDouble files by default. + This is used as a cache and as a backup in case the database + is deleted or corrupted. It can be disabled with a new volume + option "nocnidcache". +* NEW: afpd: sending SIGINT to a child afpd process enables debug logging + to /tmp/afpd.PID.XXXXXX. +* NEW: configure args to download and install a "private" Webmin instance + including only basic Webmin modules plus our netatalk.wbm. +* NEW: fallback to a temporary in memory tdb CNID database if the volume + database can't be opened. +* NEW: support for Unicode characters in the range above U+010000 using + internal surrogate pairs +* NEW: apple_dump: utility to dump AppleSingle and AppleDouble files +* NEW: afpldaptest: utility to check afp_ldap.conf. +* UPD: atalkd and papd are now disabled by default. AppleTalk is legacy. +* UPD: slp advertisement is now disabled by default. server option -slp + SRVLOC is legacy. +* UPD: cdb/dbd CNID backend requires BerkeleyDB >= 4.6 +* UPD: afpd: default CNID backend is "dbd" +* UPD: afpd: try to install PAM config that pulls in system|common auth +* UPD: afpd: symlink handling: never followed server side, client resolves + them, so it's safe to use them now. +* UPD: afpd: Comment out all extension->type/creator mappings in + AppleVolumes.system. They're unmaintained, possibly wrong and + do not fit for OS X. +* FIX: rewritten logger +* FIX: afpd: UNIX permissions handling +* FIX: cnid_dbd: always use BerkeleyDB transactions +* FIX: initscripts installation now correctly uses autoconf paths, + ie they're installed to --sysconfdir. +* FIX: UTF-8 volume name length +* FIX: atalkd: workaround for broken Linux 2.6 AT kernel module: + Linux 2.6 sends broadcast queries to the first available socket + which is in our case the last configured one. atalkd now tries to + find the right one. + Note: now a misconfigured or plugged router can broadcast a wrong route ! +* REM: afpd: removed CNID backends "db3", "hash" and "mtab" +* REM: cnid_maint: use dbd +* REM: cleanappledouble.pl: use dbd +* REM: nu: use `macusers` instead + +Changes in 2.0.5 +================ + +* NEW: afpd: Time Machine support with new volume option "tm". +* FIX: papd: Remove variable expansion for BSD printers. Fixes CVE-2008-5718. +* FIX: afpd: .AppleDxxx folders were user accessible if option 'usedots' + was set +* FIX: afpd: vetoed files/dirs where still accessible +* FIX: afpd: cnid_resolve: don't return '..' as a valid name. +* FIX: uniconv: -d option wasn't working + +Changes in 2.0.4 +================ + +* REM: remove timeout +* NEW: afpd: DHX2 uams using GNU libgcrypt. +* NEW: afpd: volume options 'illegalseq', 'perm' and 'invisibledots' + 'ilegalseq' encode illegal sequence in filename asis, ex "\217-", which is not + a valid SHIFT-JIS char, is encoded as U\217 -. + 'perm' value OR with the client requested permissions. (help with OSX 10.5 + strange permissions). + Make dot files visible by default with 'usedots', use 'invisibledots' + for keeping the old behavior, ie for OS9 (OSX hide dot files on its + own). +* NEW: afpd: volume options allow_hosts/denied hosts +* NEW: afpd: volume options dperm/fperm default directory and file + permissions or with server requests. +* NEW: afpd: afpd.conf, allow line continuation with \ +* NEW: afpd: AppleVolumes.default allow line continuation with \ +* NEW: afpd: Mac greek encoding. +* NEW: afpd: CJK encoding. +* UPD: afpd: Default UAMs: DHX + DHX2 +* FIX: afpd: return the right error in createfile and copyfile if the disk + is full. +* FIX: afpd: resolveid return the same error code than OSX if it's a directory +* FIX: afpd: server name check, test for the whole loopback subnet + not only 127.0.0.1. +* UPD: afpd: limit comments size to 128 bytes, (workaround for Adobe CS2 bug). +* UPD: afpd: no more daemon icon. +* UPD: usedots, return an invalide name only for .Applexxx files used by netatalk not + all files starting with .apple. +* UPD: cnid: increase the number of cnid_dbd slots to 512. +* FIX: cnid: dbd detach the daemon from the control terminal. +* UPD: cnid: never ending Berkeley API changes... +* UPD: cnid: dbd add a timeout when reading data from afpd client. +* UPD: cnid: Don't wait five second after the first error when speaking to the dbd + backend. +* FIX: papd: vars use % not $ +* FIX: papd: quote chars in popen variables expansion. security fix. +* FIX: papd: papd -d didn't write to stderr. +* FIX: papd: ps comments don't always use () +* FIX: many compilation errors (solaris, AFS, Tru64, xfs quota...). + +Changes in 2.0.3 +================ + +* NEW: afpd: add a cachecnid option that controls if afpd should + use the IDs stored in the AD2 files as cache. Defaults + to off. +* UPD: afpd: deal with more than 32 groups. +* FIX: afpd: several catsearch fixes, based on patch from + TSUBAKIMOTO Hiroya. +* FIX: afpd: fix a race when a client very quickly reconnects and + tries to kill its old session. +* FIX: afpd: OSX style symlink caused problems with Panther clients. +* FIX: afpd: old files with default type didn't show the right icon + in finder, from Shlomi Yaakobovich, slightly modified. +* FIX: cnid_check: disable cnid_check if CNID db was configured with + transactions and really bail out after the first error. +* FIX: admin-group configure option was broken. +* FIX: several problems with IDs cached in AD2 files. +* FIX: Ignore BIDI in UTF8 hints from OSX. +* FIX: Lots of gcc warning fixes. +* FIX: small configure script changes. + + +Changes in 2.0.2 +================ + +* NEW: cnid: Add an indexes check and rebuild, optional for dbd + (parameter check default no), standalone program cnid_index for + cdb. +* UPD: Enhanced afpd's -v command line switch and added -V for more + verbose information +* UPD: uams_gss: build the principal used by uams_gss.so from afpd's + configuration, don't use GSS_C_NT_HOSTBASED_SERVICE +* UPD: cnid_dbd: add process id in syslog and small clean up +* REM: remove netatalkshorternamelinks.pl cf. SF bug [ 1061396 ] + netatalkshorternamelinks.pl broken +* FIX: afpd: check for DenyRead on FPCopyFile +* FIX: afpd: add missing flush for AD2 Metadata on FPCopyFile, SF bug + [ 1055691 ] Word 98 OS 9 Saving an existing file +* FIX: afpd: Deal with AFP3 connection and type 2 (non-UTF8) names. + reported by Gair Heaton, HI RESOLUTION SYSTEMS +* FIX: afpd: Broken 'crlf' option +* FIX: afpd: fix SF bug [ 1079622 ] afpd/dhx memory bug, + by Ralf Schuchardt +* FIX: afpd: Return an error if we cannot get the db stamp in + afp_openvol. +* FIX: afpd: Fix slp registration with Solaris9 slpd, from + hat at fa2.so-net.ne.jp + + +Changes in 2.0.1 +================ + +* NEW: --enable-debian configure option. Will install /etc/init.d/atalk + to get not in conflict with standard debian /etc/init.d/netatalk. + Reads netatalk.conf from $ETCDIR and not from /etc/default/ +* UPD: Disable logger code by default. Log to syslog instead +* UPD: changed netatalk.conf default settings to prevent problems with + AppleTalk zone names containing spaces +* FIX: insecure tempfile handling bug in etc2ps.sh, + found by Trustix, CAN-2004-0974. +* REM: remove add_netatalk_printer and netatalk.template from stable + branch until fixed. (possible symlink vulnerabilities) +* FIX: afpd: set hasBeenInited in default finder info. This bug caused + endless finder refreshes with OS9 finder if the noadouble option + was used. From TSUBAKIMOTO Hiroya. +* FIX: afpd: fix a bug in default CREATOR/TYPE handling. Due to this bug + the type/creator mappings in AppleVolumes.system were ignored, + causing problems i.e. with OS9 clients. +* FIX: AppleVolumes.system: By default don't define a CREATOR/TYPE for a + file of unknown type. +* FIX: fix two Tru64 UNIX compilation errors, + from Burkhard Schmidt bs AT cpfs.mpg.de +* FIX: afpd: FPMapId wasn't using UTF8 for groups if requested by client. + +Changes in 2.0.0 +================ + +* UPD: afpd: add an error message if -ipaddr parameter cannot be parsed +* UPD: updated documentation +* FIX: afpd: fix a file descriptor and memory leak with OSX ._ resource fork +* FIX: afpd: Prevent overwriting a file by renaming a file in the same + directory to the same name. Won't work with OSX, the dest file gets + deleted by OSX first. +* FIX: sometimes '0' was used instead of 0 for creator/type +* FIX: removed setpgrp check from configure, we don't use it anymore and + it doesn't work with cross compile. +* FIX: fix for Solaris "make maintainer-clean", from Alexander Barton +* FIX: fix username matching bug in afppasswd. from kanai at nadmin dot org +* FIX: reworked username check a little. Depending on the UAM, the wrong + username _could_ have been selected. + +Changes in 2.0-rc2 +================== + +* UPD: use 0 0 for default creator/type rather than UNIX TEXT, from + Shlomi Yaakobovich. +* UPD: updated documentation +* UPD: change machine type from Macintosh to Netatalk in status reply +* FIX: afpd: CopyFile only create a resource fork for destination if source + has one. +* FIX: afpd: mangling: for utf8 --> max filename length is 255 bytes, else 31. +* FIX: cnid_dbd: fix a signed/unsigned, 16/32 bits mismatch. from Burkhard + Schmidt, bs at cpfs.mpg.de. +* FIX: afpd: After ad_setid don't flush resource fork if it has not been + modified. +* FIX: NEWS: Fixed ancient NEWS entries. Removed umlauts +* FIX: fix macname cache, SF bug 1021642 +* FIX: revert Makefile change from 2.0-rc1. We have to include BDB_CFLAGS + after CFLAGS + +Changes in 2.0-rc1 +================== + +* NEW: new manual page for asip-status.pl +* UPD: updated documentation +* UPD: uams: link uam_dhx_passwd.so to lcrypt before lcrypto. might help with + MD5 passwords +* UPD: Improved BerkeleyDB detection +* UPD: sys/solaris/Makefile.in: enable 'make check', from Alexander Barton +* UPD: tcp wrappers detection should work on OpenBSD as well now +* UPD: macbin: increase the maximum size of macbinary forks, as suggested by + Sourceforge bug ID 829221 +* UPD: ASP: rework getstatus. use several ASP packets if the client allows + it, otherwise just send as much as we can +* FIX: FreeBSD 5 build, from Alex Barton (alex at barton.de) +* FIX: OSX 10.3 build +* FIX: papd: workaround a problem with PJL before Postscript +* FIX: afpd: make sure we only disconnect on old session if the users match +* FIX: apfd: Quark6 mangled long filenames should work better now +* FIX: enhance ADv1 to ADv2 conversion. Fixed a SIGSEGV reported by Mark Baker +* FIX: better detection of invalid resource forks +* FIX: fix some linking problems on OpenBSD +* FIX: afpd: catsearch.c, filedir.c: fix bogus casts, from Olaf Hering + (olh at suse.de) +* FIX: afpd: don't try to create special folders and .volinfo on read-only + volumes +* FIX: iconv/unicode enhancements. fixed a sigsegv on conversion error +* FIX: configure.in: fix a typo, reported by Joerg Rossdeutscher +* FIX: uniconv: enhanced uniconv behaviour +* FIX: fixed some Solaris compilation problems +* FIX: papd/Makefile.am: add a missing $DESTDIR, from Vlad Agranovsky +* FIX: afpd: quota.c: remove a c99 declaration, from Yann Rouillard +* FIX: configure.in: Solaris/gcc 3.0 fix, from Yann Rouillard +* FIX: afpd: fix a SIGSEGV when sharing home dirs without any options in + AppleVolumes. +* FIX: numerous small bugfixes + +Changes in 2.0-beta2 +==================== + +* NEW: atalkd, papd and npb tools now support nbpnames with extended + characters +* NEW: integrated CUPS support for papd +* NEW: optionally advertise SSH tunneling capabilties +* NEW: automatic logfile removal for cnid_metad +* NEW: asip-status.pl has been added to netatalk +* UPD: updated documentation +* UPD: we now require Berkeley DB >= 4.1 +* UPD: 64bit Linux fixes from Stew Benedict, Mandrakesoft +* UPD: remove --enable-sendfile +* UPD: more verbose error messages +* FIX: better handling for resource forks without read access +* FIX: Tru64 build, by Burkhard Schmidt +* FIX: MIT Kerberos detection +* FIX: varios *BSD compile problems +* FIX: compile problem with libiconv, reported by Joe Marcus Clarke +* FIX: adv1tov2: make it work with the new structure +* FIX: afpd: filenames longer than 127 bytes were not enumerated correctly, + reported by Thies C. Arntzen +* FIX: afpd: return IP before FQDN in status reply. +* FIX: afpd: Mac chooser could crash on a codepage conversion error +* FIX: afpd: KerberosV auth with Panther clients, make long AD tickets work, + reported by Andrew Smith +* FIX: atalkd: could send invalid NBPLKUP replies, e.g with more than 15 + printers. Reported by Almacha +* FIX: papd: fix papd.conf parsing problems with consecutive ':' and missing + newline. Reported by Craig White. +* FIX: megatron: make megatron work with UTF-8 volumes +* FIX: timeout: running timeout with commands which accept arguments, + from Yuval Yeret. +* FIX: uniconv: fix a SEGFAULT, reported by Matthew Geier +* FIX: pam detection: PAM_C/LDFLAGS were always empty, from Alexander Barton +* FIX: numerous small bugfixes. + +Changes in 2.0-beta1 +==================== + +* NEW: OSX style adouble scheme +* NEW: japanese SHIFT_JIS codepage (iconv supplied) +* NEW: Solaris kernel module build integrated with configure +* NEW: Gentoo start scripts +* NEW: cnid_dbd doesn't use transactions by default +* FIX: afpd: the volume casefold option was broken +* FIX: afpd: update AD2 headers and keep owner on file exchange +* FIX: Solaris 9 and FreeBSD 4.9/5.2 compilation +* FIX: free space reported with groups quotas on Linux +* FIX: OS9/OS X didn't update free space +* FIX: finder crash if folder opened got deleted by another process +* FIX: randnum UAM wasn't AFP3 ready +* FIX: numerous small bugfixes. + +Changes in 2.0-alpha2 +===================== + +* NEW: uniconv tool for converting volume encoding. +* NEW: afpd: Make sure getstatus doesn't return loopback address as server IP. +* NEW: afpd: Specify USEDOTS with MSWINDOWS implicitely. +* NEW: afpd: SRVLOC register with IP address instead of hostname by default, + if -fqdn is specified register with FQDN. Added extended character + support for SLP, non ASCII characters are escaped Added ZONE to registration. +* NEW: atalkd: Make atalkd set interfaces to ALLMULTI on linux by default. +* NEW: cnid_metad: Use DB_PRIVATE attribute for dbd backend without transaction. +* FIX: afpd: Partial workaround for an OSX client deadlock. +* FIX: afpd: Reenumerate folder if db is out of sync in resolveID. +* FIX: afpd: Don't modify modification date in copyfile. +* FIX: afpd: Variable $v substitution: always use name defined in config files. +* FIX: libatalk: Speed optimisation for byte locking was broken on resource fork. +* FIX: Solaris 9 compilation. +* FIX: Tru64 compilation fixes. +* FIX: AFS compilation fixes. +* FIX: strncpy bugfix. +* FIX: configure, man pages update and small bugfixes. + +Changes in 2.0-alpha1 +===================== + +* NEW: afpd: We now support AFP 3.x, which features long filenames and + large file support +* NEW: CNID handling completely reworked. We now use per Volume configurable + CNID backends. +* NEW: Two new daemons, cnid_metad and cnid_dbd to implement the dbd CNID backend. + Using Berkeley DB transactions with the CNID database should be safe now. +* NEW: The on disk format of the CNID database has changed. We now support 8 byte + device and inode numbers and an additinal type field that should make + detection of file/directory changes outside of afpd more robust. + Changed from HASH to BTREE access which speeds things up in certain cases + and reduces database file size. +* NEW: Long file name mangling is now implemented using the CNID ID, so no database is + required to map names to mangled names. This is the same method Mac OS X uses. +* NEW: New format (version 2) for Metadata in AppleDouble files. We record device and + inode of the underlying file as well as the CNID. This can be used for recovery + and speeds up access to the CNID. +* NEW: The old NLS codepage system has been removed. It was replaced by an iconv + based conversion system, which provides much more flexibility. +* NEW: You can safely use extended characters in volume names and for SIGUSR2 messaging. +* NEW: The default volume encoding is UTF-8. +* NEW: All documentation is now generated using DocBook. New or completely reworked + sections about installing, setting up and upgrading Netatalk replace various + README files in the doc directory. +* FIX: Protect afpd better against unexpected signals during updates of the CNID + database with the cdb backend. This makes database corruption less likely. +* FIX: All manpages have been reviewed and should now be up to date. +* FIX: Tons of bug fixes since 1.6.4. Please consults the CVS change log for details. + +Changes in 1.6.4 +================ + +* NEW: afpd: Using the mswindows option now implicitly specifies usedots. + [Sam Noble] +* UPD: afpd.8: Updated the option documentation. + [Thomas Kaiser, Sebastian Rittau] +* FIX: configure: Removed broken --with-flock-locks option. [Bjoern Fernhomberg] +* FIX: libatalk: Do not log network probe (OSX 10.3). [Didier Gautheron] +* FIX: libatalk: Deadlock in signal handlers. [Didier] +* FIX: libatalk: Compilation with Linux kernel 2.6 fixed. [Sebastian, Bjoern] +* FIX: afpd: Solaris compile issues. [Bjoern] +* FIX: afpd: If connection broke in dsi_tickle the child did never die. [Bjoern] +* FIX: afpd: Catsearch, fixes a possible segmentation fault. [Bjoern] +* FIX: afpd: Compilation issues. [Olaf Hering, Sebastian] +* FIX: cnid: Fix compile problems on Tru64. [Burkhard Schmidt] +* FIX: megatron: Fixed an uninitialized variable. [Olaf] +* FIX: installation: Don't overwrite PAM file if --enable-overwrite configure + option is not set. [Sam, Ryan Cleary] +* FIX: installation: Fixed BSD installation. [Toru TAKAMIZU] +* FIX: docs: Removed ssl-dir/ssl-dirs confusion from doc/INSTALL. [Bjoern] + +Changes in 1.6.3 +================ + +* UPD: afpd: Infrastructural support for an upcoming Kerberos 5 UAM. + [Sam Noble] +* UPD: uams_dhx_passwd: Better random seed in Tru64. [Burkhard Schmidt] +* FIX: afpd: Bug in AFP connection negotiation stage. [Sam] +* FIX: afpd: Catsearch, when Mac and unix name differ, search on attributes. +* FIX: afpd: Files could be opened for writing on read-only filesystems. +* FIX: afpd: Debugging using SIGUSR1 was broken. [Stefan Muenkner] +* FIX: afpd: Segfault after login. [Robby Griffin, Sean Bolton] +* FIX: psf: Correct path to etc2ps.sh. +* FIX: shell_utils: Don't distribute generated files. +* FIX: aecho: -A option didn't work. [Chris Shiels] +* FIX: configure: Berkeley DB path detection could be wrong. [Stefan] +* FIX: Automake build fixes. + +Changes in 1.6.2 +================ + +* FIX: atalkd: Fixes for reading long configuration file lines. [Dan Wilga] +* FIX: afpd: CNID id allocation in a multiuser environment. +* FIX: papd: Fix PSSP support when PAM is enabled. +* FIX: macusers: Can now cope with IP addresses as well as host names. +* FIX: etc2ps.sh: Install correctly. + +Changes in 1.6.1 +================ + +* UPD: Improve --enable-fhs. [Olaf Hering] +* UPD: Add BDB 4.1.x support. +* UPD: Add more documentation on CNID, as well as list which versions + of Berkeley DB are supported. +* FIX: Codepage file maccode.koi8-r is now correctly cleaned. +* FIX: Fix init script location on SuSE. [Olaf] +* FIX: Build fixes. [Olaf, Steven N. Hirsch] +* FIX: Various bugs when a user doesn't have access permission to a folder. + (Fixes an OSX kernel panic.) +* FIX: CNID, folders' DID handling with concurrent access or symlinks. + (Fixes an endless loop in afpd.) + +Changes in 1.6.0 +================ + +* FIX: pap looks at the STDOUT file descriptor to see if it's connected to + a tty, instead of STDIN. + +Changes in 1.6pre2 +================== + +* UPD: Removed --with-catsearch option from configure and enable FPCatSearch + by default. +* UPD: The dbpath argument does now support variable substitution. +* FIX: Build fix for non-GNU-C compilers in libatalk/util/logger.c. +* FIX: Two directories with the same name but different case confused the + Mac Finder. +* FIX: The ROOT_PARENT directory could get invalidated. + +Changes in 1.6pre1 +==================== + +* NEW: Long file name mangling support. +* NEW: Improved log file support. +* NEW: Server-side find capability ("FPCatSearch") +* NEW: Concurrent datastore (CDB) is now the default CNID datastore. This + should be heavily tested in a multiuser environment. +* NEW: Variable substitution support has been added for the dbpath AppleVolume + option. +* UPD: CNID DID handling is now enabled by default. +* FIX: Various bug and build fixes as well as code cleanups. + +Changes in 1.5.5 +================ + +* NEW: Allow afpd debugging to be enabled by sending the afpd process + a SIGUSR1. +* NEW: Allow SLP to be disabled per afpd process by adding a new -noslp flag + to afpd.conf. +* FIX: Use server name (if not NULL) for the SLP URL. +* FIX: papd: buffer overflow during config file read (Olaf Hering) + +Changes in 1.5.4 +================ + +* FIX: File open read only and then read write (aka pb with Illustrator). +* FIX: Problems with unexpected EOF when reading files on a ddp connection + Photoshop, old finder. +* FIX: --with-nls-dir option does now work + +Changes in 1.5.3 +================ + +* UPD: Extend the --disable-shell-check functionality to ignore users + with _no_ shell. Also, send a log message if a user is refused login + based on the fact that they have no shell. +* UPD: Autoconf updates. +* UPD: Tru64 afpd authentication updates. +* UPD: As always: lots of minor code cleanups. +* FIX: Problems with Photoshop trying to open image files has been + corrected. +* FIX: Preserve special permission bits when creating or modifying + directories. +* FIX: afp_deleteid() now deletes the specified file and not the parent + directory. +* FIX: papd does now announce that it supports binary data to its clients. +* FIX: NetBSD ELF support. +* FIX: acleandir.rc is now installed in the bin directory. +* FIX: megatron does now compile even if compiled with -DDEBUG. +* FIX: Clean up some syslog messages. + +Changes in 1.5.2 +================ + +* NEW: NetBSD support contributed by David Rankin and NetBSD contributors. + This includes a new configure option --enable-netbsd. +* NEW: Add the -client_polling afpd.conf flag to allow for clients to poll + the server every 10 seconds for open window updates. Currently + this is the only way to get asynchronous directory updates. +* UPD: Use separate macro for AFS configure check. +* UPD: Some Perl scripts are now (partially) auto-generated. This improves + out-of-the-box usage of Netatalk. +* UPD: Solaris Kernel Makefile is now auto-generated. This fixes some path + issues, but isn't perfect, yet. Added some Solaris compatibility + fixes to the Kernel sources, too. +* UPD: CNID DB code sync'd with the current CVS version. NOTE: Using this + code requires you to delete _all_ existing .AppleDB directories in + order to avoid database corruption! +* FIX: The file AppleVolumes.system contained wrong line breaks so that + not all file types were properly recognized. +* FIX: AFS compilation would fail due to a misnamed variable. +* FIX: SLP configure check was wrong so SLP did not compile. +* FIX: Fix the way quotas are handled under certain situations. +* FIX: Do not enable debugging code if debugging option is not set. +* FIX: Some problems with wrongly assigned DIDs were fixed. +* FIX: Various bug fixes and code cleanups. + +Changes in 1.5.1 +================ + +* NEW: Added a program called cnid_didname_verify that can be used to + verify the consistency of the CNID database. +* NEW: New afpd option: -timeout. Warning: This still doesn't do what it's + supposed to! +* UPD: Code cleanups and compatibility fixes to macusers. +* UPD: AppleVolumes.system was cleaned up. +* FIX: Really fix Tru64 compilation (see last entry). +* FIX: Hand correct error value back to AFP client when deleting files or + directories fails. +* FIX: Leading or trailing spaces are now forbidden on volumes that have + the AFPVOL_MSWINDOWS flag set. +* FIX: Minor code cleanups and warning fixes. +* FIX: Make quota support work on FreeBSD. + +Changes in 1.5.0 +================ + +* FIX: Compilation on Tru64 systems was broken, since libtool's acinclude.m4 + file on the packagers system did not contain the necessary patch. +* FIX: On some systems, atalkd refuses to start, since it couldn't detect + any interfaces. This was caused by an overzealous validity check. + +Changes in 1.5rc2 +================= + +* FIX: contrib/shell_utils/lp2pap.sh was erased when "make clean" was called. + Now we distribute lp2pap.sh.tmpl instead, and lp2pap.sh is automatically + generated during package build. +* FIX: Some platforms (notably Tru64) don't have the snprintf() call, which + was used in etc/afp/afp_config.c. This call was replaced by sprintf() + and prior bounds checking. + +Changes from the 1.4b1 release: +=============================== + +* Fixed the maximum free/total volume size in afpd. + +* Made ~ the default volume in afpd. + +* Fixed pid file handling and changed setpgrp() to setpgid() in afpd, + papd, and atalkd. + +* Added code to afpd to set the Unix file time stamps with utime(). + +* Fixed a bug in papd's printcap code which limited it to 15 or so + printers. + +* Fixed papd's handling of piped printers. + +* Fixed papd's handling of bad job names. + +* Fixed atalkd to send NBP LKUP packets from NBP port. + +* Added "sync;sync;sync" to Solaris kinstall to help with streams + file corruption. + +* Added nlocalrts to streams ddp.conf. Thanks Thomas Tornblom. + +* Fixed signed extension infinite loop in Solaris module. + +* Moved all the config files to .../config. + +Changes from the 1.3.3 release: +=============================== + +* Added code from Sun Microsystems, Inc (OPCOM) for Solaris support. + See COPYRIGHT. + +* Added support for FreeBSD, mostly changes by Mark Dawson and Julian + Elischer. + +* All sorts of other stuff. + +Changes from the 1.3.1 release: +=============================== + +* Added options to psf's filter names to support accounting on HPs. + !!! NOTE: The location of the filters has changed, see the man + page for where. + +* Added code from Alan Cox to support Linux. + +* Rewrote papd. Now handles dropped connections better. + Configuration has been modernized. !!! NOTE: The format of the + configuration file has changed, but NOT THE NAME. + +* Added Kerberos support to papd. + +* atalkd now removes routes on a SIGTERM. Still can't just restart + it, but it's closer. + +* Changed atalkd and the kernel driver to remove a hack added to + support sending to 0.255. Now the kernel will allow multiple open + sockets with the same port, so long as the addess associated with + the port is different. atalkd now opens a socket for each port on + each interface. + +* atalkd now rewrites its configuration file. If no configuration + file is given, one will be generated. Permissions on the new + configuration file will be inherited from the old one. If there is + no old one, permissions default to 644. Won't rewrite the file if + the owner doesn't have write permission. + +* Removed support for the "AFS Kerberos UAM", in favor of the + "AuthMan UAM". Kerberos support should now be much more + straight-forward. + +* Fixed a bug in afpd which would cause incorrect group calculations + on ultrix machines. + +* Fixed a bug in afpd which causes SimpleText and some other + applications to silently fail to write. There's also a bug in + MacOS, but we can't fix that. + +* Fixed a bad interaction with afpd and AFS which would cause file + writes to not propogate between AFS clients. + +* !!! CHANGED the name(s) of afpd's config files. The new files are + AppleVolumes.system and AppleVolumes.default. If AppleVolumes.system + exists, it is always read, AppleVolumes.default is only read if the + user has no AppleVolumes file. Included a flag "-u" to indicate + which file has precedence. "-u" user wins, otherwise ".system" + wins. + +* Rewrote the AppleVolumes parsing code. Now works. + +* Added a filename extension mapping to afpd. User always takes + precedence, regardless of the "-u" flag. Code to change the type + of all Unix files contributed by Kee Hinckley . + +* afpd now supports both UFS and AFS volumes simultaneously. It also + uses access() to attempt to calculate reasonable Mac permissions + for AFS directories. + +* Changed reporting of file times. Files that are written from Unix + now update the Mac's idea of the files modification time. Unix + mtime is now reported instead of ctime. + +* Added support for a new UAM to afpd. This requires that client + Macs have MacTCP and AuthMan installed. Should make running afpd + for AFS easier. + +* Removed code so that otherwise valid volumes for which the mounting + user has no permission will appear in the volume selection dialog + on the Mac gray-ed out. + +* Added code from Chris Metcalf of MIT to the AppleDouble library + which improves permission inheritance. + +* Added code from G. Paul Ziemba of Alantec, Inc to better report + errors in psf. Also changed psf to use syslog for errors that + users aren't interested in. + +* Added information to psf's man page to better explain the + interaction between psf, pap, and lpd. + +* Make psf/pap/psa do accounting when it's turnes on in + /etc/printcap. + +* Changed pap's error message when there is no printer specified on + the command line and no .paprc is found. Also heavily modified + pap's man page to reflect changes in the "new" version of pap, + including moving it from section 8 to section 1. + +* Fixed a byte-order bug in pap's sequence numbers. Doubt if pap has + ever worked right on little endian machines! + +* Added a flag to pap to optionally close before receiving EOF from + the printer. Off by default. psf calls pap with this option on. + +* Added timeouts to the nbp library calls. This means that processes + won't hang when atalkd dies during boot, thus hanging your + machine. + +Changes from the 1.3 release: +============================= + +* Fixed a bug in afpd which would cause APPL mappings to contain both + mac and unix path names. The fixed code will handle the old + (corrupted) database. + +* Fixed a *very* serious bug which would cause files to be corrupted + when copying to afpd. + +* Fixed a bug in afpd which would cause replies to icon writes to + contain the written icon. + +* Filled in the function code switch in afpd. Previously, a hacker + could probably have used afpd to get unauthorized access to a + machine running afpd. + +* Fixed a bug in the asp portion of libatalk.a which could cause the + malloc()/free() database to be corrupted. + +* Fixed a bug in atalkd's zip query code. With this bug, only the + first N % 255 nets get queried. However, since nets bigger than + 255 are usually pretty unstable, the unqueried for nets will + eventually get done, when N drops by one. + +* Suppressed a spurious error ("route: No such process") in atalkd. + +Changes from the 1.2.1 release: +=============================== + +* atalkd is completely rewritten for phase 2 support. atalkd.conf + from previous version will not work! + +* afpd now has better AFS support. In particular, the configuration + for AFS was made much easier; a number of Kerberos-related + byte-ordering and time problems were found; clear-text passwords + were added (thanks to geeb@umich.edu). + +* afpd now handles Unix permissions much better (thanks to + metcalf@mit.edu). + +* There are many, many more changes, but most are small bug fixes. + +Changes from the 1.2 release: +============================= + +* The Sun support now uses loadable kernel modules (a la VDDRV) + instead of binary patches. As such, it should work on any sunos + greater than 4.1, and is confirmed to work under 4.1.1 and 4.1.2. + +* The DEC support no longer requires source. It also runs under + ultrix 4.1 and 4.2. It still requires patching your kernel, but the + patches are limited to those files available to binary-only sites + -- primarily hooks for things like netatalk. + +* The etc.rc script now uses changes made to nbprgstr (see below). + +* aecho now takes machine names on the command line. + +* nbplkup now takes a command line argument specifying the number of + responses to accept. It also takes its defaults from the NBPLKUP + environment variable. + +* nbprgstr may be used to register a name at any requested port. + +* afpd now logs if an illegal shell is used during login, instead of + silently denying service. + +* A bug in afpd which caused position information for the directory + children of the root of a volume to be ignored has been fixed. + +* Several typos in afpd which would cause include files necessary to + ultrix to be skipped have been fixed. + +* atalkd will no long propagate routes to networks whose zone + it doesn't know. + +* atalkd no longer dumps core if it receives a ZIP GetMyZone request + from a network whose zone it doesn't know. (Since this currently + can only happen from off net, it's not precisely a legal request.) + +* pap and papd (optionally) no longer check the connection id in PAP + DATA responses. Both also maintain the function code in non-first-packet + PAP DATA responses. These changes are work-arounds to deal with + certain AppleTalk printer cards, notably the BridgePort LocalTalk + card for HP LJIIISIs. + +* pap no longer sends an EOF response to each PAP SENDDATA request, + only the first. + +* A bug in papd which would cause it to return a random value when + printing the procset to a piped printer has been fixed. + +* A bug relating to NBP on reverse-endian machines has been fixed. + +* atp_rsel() from libatalk now returns a correct value even if it + hasn't recieved anything yet. + +* atalk_addr() from libatalk no longer accepts addresses in octal + format, since AppleTalk addresses can have leading zeros. Also it + checks that the separator character is a '.'. + +* Pseudo man pages for nbplkup, nbprgstr, and nbpunrgstr, have been + added. + +* The example in the psf(8) man page is now correct. + +* The man pages for changed commands have been updated. + +* The README files for various machine have been updated + appropriately. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..d40b13a --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +3.1.7 \ No newline at end of file diff --git a/abigen.sh b/abigen.sh new file mode 100755 index 0000000..d5a3a2e --- /dev/null +++ b/abigen.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# generate a set of ABI signatures from a shared library + +SHAREDLIB="$1" + +GDBSCRIPT="gdb_syms.$$" + +( +cat < $GDBSCRIPT + +# forcing the terminal avoids a problem on Fedora12 +TERM=none gdb -batch -x $GDBSCRIPT "$SHAREDLIB" < /dev/null | sed -e 's/:\$[0-9]* = /: /g' -e 's/<[0-9a-zA-Z_]*>$//g' -e 's/0x[0-9a-f]* $//g' -e 's/0x[[:xdigit:]]* \("[[:alnum:] _-]*"\)/\1/g' -e 's/0x[[:xdigit:]]* \(<[[:alnum:] _-]*>\)/\1/g' -e 's/{\(.*\)} $/\1/g' +rm -f $GDBSCRIPT diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..9d01b80 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,2082 @@ +# generated automatically by aclocal 1.12.5 -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- +# +# Copyright (C) 1999-2006, 2007, 2008, 2011 Free Software Foundation, Inc. +# Written by Thomas Tanner, 1999 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 18 LTDL_INIT + +# LT_CONFIG_LTDL_DIR(DIRECTORY, [LTDL-MODE]) +# ------------------------------------------ +# DIRECTORY contains the libltdl sources. It is okay to call this +# function multiple times, as long as the same DIRECTORY is always given. +AC_DEFUN([LT_CONFIG_LTDL_DIR], +[AC_BEFORE([$0], [LTDL_INIT]) +_$0($*) +])# LT_CONFIG_LTDL_DIR + +# We break this out into a separate macro, so that we can call it safely +# internally without being caught accidentally by the sed scan in libtoolize. +m4_defun([_LT_CONFIG_LTDL_DIR], +[dnl remove trailing slashes +m4_pushdef([_ARG_DIR], m4_bpatsubst([$1], [/*$])) +m4_case(_LTDL_DIR, + [], [dnl only set lt_ltdl_dir if _ARG_DIR is not simply `.' + m4_if(_ARG_DIR, [.], + [], + [m4_define([_LTDL_DIR], _ARG_DIR) + _LT_SHELL_INIT([lt_ltdl_dir=']_ARG_DIR['])])], + [m4_if(_ARG_DIR, _LTDL_DIR, + [], + [m4_fatal([multiple libltdl directories: `]_LTDL_DIR[', `]_ARG_DIR['])])]) +m4_popdef([_ARG_DIR]) +])# _LT_CONFIG_LTDL_DIR + +# Initialise: +m4_define([_LTDL_DIR], []) + + +# _LT_BUILD_PREFIX +# ---------------- +# If Autoconf is new enough, expand to `${top_build_prefix}', otherwise +# to `${top_builddir}/'. +m4_define([_LT_BUILD_PREFIX], +[m4_ifdef([AC_AUTOCONF_VERSION], + [m4_if(m4_version_compare(m4_defn([AC_AUTOCONF_VERSION]), [2.62]), + [-1], [m4_ifdef([_AC_HAVE_TOP_BUILD_PREFIX], + [${top_build_prefix}], + [${top_builddir}/])], + [${top_build_prefix}])], + [${top_builddir}/])[]dnl +]) + + +# LTDL_CONVENIENCE +# ---------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. LIBLTDL will be prefixed with +# '${top_build_prefix}' if available, otherwise with '${top_builddir}/', +# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single +# quotes!). If your package is not flat and you're not using automake, +# define top_build_prefix, top_builddir, and top_srcdir appropriately +# in your Makefiles. +AC_DEFUN([LTDL_CONVENIENCE], +[AC_BEFORE([$0], [LTDL_INIT])dnl +dnl Although the argument is deprecated and no longer documented, +dnl LTDL_CONVENIENCE used to take a DIRECTORY orgument, if we have one +dnl here make sure it is the same as any other declaration of libltdl's +dnl location! This also ensures lt_ltdl_dir is set when configure.ac is +dnl not yet using an explicit LT_CONFIG_LTDL_DIR. +m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl +_$0() +])# LTDL_CONVENIENCE + +# AC_LIBLTDL_CONVENIENCE accepted a directory argument in older libtools, +# now we have LT_CONFIG_LTDL_DIR: +AU_DEFUN([AC_LIBLTDL_CONVENIENCE], +[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])]) +_LTDL_CONVENIENCE]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBLTDL_CONVENIENCE], []) + + +# _LTDL_CONVENIENCE +# ----------------- +# Code shared by LTDL_CONVENIENCE and LTDL_INIT([convenience]). +m4_defun([_LTDL_CONVENIENCE], +[case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; +esac +LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdlc.la" +LTDLDEPS=$LIBLTDL +LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}" + +AC_SUBST([LIBLTDL]) +AC_SUBST([LTDLDEPS]) +AC_SUBST([LTDLINCL]) + +# For backwards non-gettext consistent compatibility... +INCLTDL="$LTDLINCL" +AC_SUBST([INCLTDL]) +])# _LTDL_CONVENIENCE + + +# LTDL_INSTALLABLE +# ---------------- +# sets LIBLTDL to the link flags for the libltdl installable library +# and LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called from here. If an installed libltdl +# is not found, LIBLTDL will be prefixed with '${top_build_prefix}' if +# available, otherwise with '${top_builddir}/', and LTDLINCL will be +# prefixed with '${top_srcdir}/' (note the single quotes!). If your +# package is not flat and you're not using automake, define top_build_prefix, +# top_builddir, and top_srcdir appropriately in your Makefiles. +# In the future, this macro may have to be called after LT_INIT. +AC_DEFUN([LTDL_INSTALLABLE], +[AC_BEFORE([$0], [LTDL_INIT])dnl +dnl Although the argument is deprecated and no longer documented, +dnl LTDL_INSTALLABLE used to take a DIRECTORY orgument, if we have one +dnl here make sure it is the same as any other declaration of libltdl's +dnl location! This also ensures lt_ltdl_dir is set when configure.ac is +dnl not yet using an explicit LT_CONFIG_LTDL_DIR. +m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl +_$0() +])# LTDL_INSTALLABLE + +# AC_LIBLTDL_INSTALLABLE accepted a directory argument in older libtools, +# now we have LT_CONFIG_LTDL_DIR: +AU_DEFUN([AC_LIBLTDL_INSTALLABLE], +[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])]) +_LTDL_INSTALLABLE]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBLTDL_INSTALLABLE], []) + + +# _LTDL_INSTALLABLE +# ----------------- +# Code shared by LTDL_INSTALLABLE and LTDL_INIT([installable]). +m4_defun([_LTDL_INSTALLABLE], +[if test -f $prefix/lib/libltdl.la; then + lt_save_LDFLAGS="$LDFLAGS" + LDFLAGS="-L$prefix/lib $LDFLAGS" + AC_CHECK_LIB([ltdl], [lt_dlinit], [lt_lib_ltdl=yes]) + LDFLAGS="$lt_save_LDFLAGS" + if test x"${lt_lib_ltdl-no}" = xyes; then + if test x"$enable_ltdl_install" != xyes; then + # Don't overwrite $prefix/lib/libltdl.la without --enable-ltdl-install + AC_MSG_WARN([not overwriting libltdl at $prefix, force with `--enable-ltdl-install']) + enable_ltdl_install=no + fi + elif test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + fi +fi + +# If configure.ac declared an installable ltdl, and the user didn't override +# with --disable-ltdl-install, we will install the shipped libltdl. +case $enable_ltdl_install in + no) ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLDEPS= + LTDLINCL= + ;; + *) enable_ltdl_install=yes + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdl.la" + LTDLDEPS=$LIBLTDL + LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}" + ;; +esac + +AC_SUBST([LIBLTDL]) +AC_SUBST([LTDLDEPS]) +AC_SUBST([LTDLINCL]) + +# For backwards non-gettext consistent compatibility... +INCLTDL="$LTDLINCL" +AC_SUBST([INCLTDL]) +])# LTDL_INSTALLABLE + + +# _LTDL_MODE_DISPATCH +# ------------------- +m4_define([_LTDL_MODE_DISPATCH], +[dnl If _LTDL_DIR is `.', then we are configuring libltdl itself: +m4_if(_LTDL_DIR, [], + [], + dnl if _LTDL_MODE was not set already, the default value is `subproject': + [m4_case(m4_default(_LTDL_MODE, [subproject]), + [subproject], [AC_CONFIG_SUBDIRS(_LTDL_DIR) + _LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"])], + [nonrecursive], [_LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"; lt_libobj_prefix="$lt_ltdl_dir/"])], + [recursive], [], + [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])])dnl +dnl Be careful not to expand twice: +m4_define([$0], []) +])# _LTDL_MODE_DISPATCH + + +# _LT_LIBOBJ(MODULE_NAME) +# ----------------------- +# Like AC_LIBOBJ, except that MODULE_NAME goes into _LT_LIBOBJS instead +# of into LIBOBJS. +AC_DEFUN([_LT_LIBOBJ], [ + m4_pattern_allow([^_LT_LIBOBJS$]) + _LT_LIBOBJS="$_LT_LIBOBJS $1.$ac_objext" +])# _LT_LIBOBJS + + +# LTDL_INIT([OPTIONS]) +# -------------------- +# Clients of libltdl can use this macro to allow the installer to +# choose between a shipped copy of the ltdl sources or a preinstalled +# version of the library. If the shipped ltdl sources are not in a +# subdirectory named libltdl, the directory name must be given by +# LT_CONFIG_LTDL_DIR. +AC_DEFUN([LTDL_INIT], +[dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +dnl We need to keep our own list of libobjs separate from our parent project, +dnl and the easiest way to do that is redefine the AC_LIBOBJs macro while +dnl we look for our own LIBOBJs. +m4_pushdef([AC_LIBOBJ], m4_defn([_LT_LIBOBJ])) +m4_pushdef([AC_LIBSOURCES]) + +dnl If not otherwise defined, default to the 1.5.x compatible subproject mode: +m4_if(_LTDL_MODE, [], + [m4_define([_LTDL_MODE], m4_default([$2], [subproject])) + m4_if([-1], [m4_bregexp(_LTDL_MODE, [\(subproject\|\(non\)?recursive\)])], + [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])]) + +AC_ARG_WITH([included_ltdl], + [AS_HELP_STRING([--with-included-ltdl], + [use the GNU ltdl sources included here])]) + +if test "x$with_included_ltdl" != xyes; then + # We are not being forced to use the included libltdl sources, so + # decide whether there is a useful installed version we can use. + AC_CHECK_HEADER([ltdl.h], + [AC_CHECK_DECL([lt_dlinterface_register], + [AC_CHECK_LIB([ltdl], [lt_dladvise_preload], + [with_included_ltdl=no], + [with_included_ltdl=yes])], + [with_included_ltdl=yes], + [AC_INCLUDES_DEFAULT + #include ])], + [with_included_ltdl=yes], + [AC_INCLUDES_DEFAULT] + ) +fi + +dnl If neither LT_CONFIG_LTDL_DIR, LTDL_CONVENIENCE nor LTDL_INSTALLABLE +dnl was called yet, then for old times' sake, we assume libltdl is in an +dnl eponymous directory: +AC_PROVIDE_IFELSE([LT_CONFIG_LTDL_DIR], [], [_LT_CONFIG_LTDL_DIR([libltdl])]) + +AC_ARG_WITH([ltdl_include], + [AS_HELP_STRING([--with-ltdl-include=DIR], + [use the ltdl headers installed in DIR])]) + +if test -n "$with_ltdl_include"; then + if test -f "$with_ltdl_include/ltdl.h"; then : + else + AC_MSG_ERROR([invalid ltdl include directory: `$with_ltdl_include']) + fi +else + with_ltdl_include=no +fi + +AC_ARG_WITH([ltdl_lib], + [AS_HELP_STRING([--with-ltdl-lib=DIR], + [use the libltdl.la installed in DIR])]) + +if test -n "$with_ltdl_lib"; then + if test -f "$with_ltdl_lib/libltdl.la"; then : + else + AC_MSG_ERROR([invalid ltdl library directory: `$with_ltdl_lib']) + fi +else + with_ltdl_lib=no +fi + +case ,$with_included_ltdl,$with_ltdl_include,$with_ltdl_lib, in + ,yes,no,no,) + m4_case(m4_default(_LTDL_TYPE, [convenience]), + [convenience], [_LTDL_CONVENIENCE], + [installable], [_LTDL_INSTALLABLE], + [m4_fatal([unknown libltdl build type: ]_LTDL_TYPE)]) + ;; + ,no,no,no,) + # If the included ltdl is not to be used, then use the + # preinstalled libltdl we found. + AC_DEFINE([HAVE_LTDL], [1], + [Define this if a modern libltdl is already installed]) + LIBLTDL=-lltdl + LTDLDEPS= + LTDLINCL= + ;; + ,no*,no,*) + AC_MSG_ERROR([`--with-ltdl-include' and `--with-ltdl-lib' options must be used together]) + ;; + *) with_included_ltdl=no + LIBLTDL="-L$with_ltdl_lib -lltdl" + LTDLDEPS= + LTDLINCL="-I$with_ltdl_include" + ;; +esac +INCLTDL="$LTDLINCL" + +# Report our decision... +AC_MSG_CHECKING([where to find libltdl headers]) +AC_MSG_RESULT([$LTDLINCL]) +AC_MSG_CHECKING([where to find libltdl library]) +AC_MSG_RESULT([$LIBLTDL]) + +_LTDL_SETUP + +dnl restore autoconf definition. +m4_popdef([AC_LIBOBJ]) +m4_popdef([AC_LIBSOURCES]) + +AC_CONFIG_COMMANDS_PRE([ + _ltdl_libobjs= + _ltdl_ltlibobjs= + if test -n "$_LT_LIBOBJS"; then + # Remove the extension. + _lt_sed_drop_objext='s/\.o$//;s/\.obj$//' + for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | sed "$_lt_sed_drop_objext" | sort -u`; do + _ltdl_libobjs="$_ltdl_libobjs $lt_libobj_prefix$i.$ac_objext" + _ltdl_ltlibobjs="$_ltdl_ltlibobjs $lt_libobj_prefix$i.lo" + done + fi + AC_SUBST([ltdl_LIBOBJS], [$_ltdl_libobjs]) + AC_SUBST([ltdl_LTLIBOBJS], [$_ltdl_ltlibobjs]) +]) + +# Only expand once: +m4_define([LTDL_INIT]) +])# LTDL_INIT + +# Old names: +AU_DEFUN([AC_LIB_LTDL], [LTDL_INIT($@)]) +AU_DEFUN([AC_WITH_LTDL], [LTDL_INIT($@)]) +AU_DEFUN([LT_WITH_LTDL], [LTDL_INIT($@)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIB_LTDL], []) +dnl AC_DEFUN([AC_WITH_LTDL], []) +dnl AC_DEFUN([LT_WITH_LTDL], []) + + +# _LTDL_SETUP +# ----------- +# Perform all the checks necessary for compilation of the ltdl objects +# -- including compiler checks and header checks. This is a public +# interface mainly for the benefit of libltdl's own configure.ac, most +# other users should call LTDL_INIT instead. +AC_DEFUN([_LTDL_SETUP], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_SYS_MODULE_EXT])dnl +AC_REQUIRE([LT_SYS_MODULE_PATH])dnl +AC_REQUIRE([LT_SYS_DLSEARCH_PATH])dnl +AC_REQUIRE([LT_LIB_DLLOAD])dnl +AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl +AC_REQUIRE([LT_FUNC_DLSYM_USCORE])dnl +AC_REQUIRE([LT_SYS_DLOPEN_DEPLIBS])dnl +AC_REQUIRE([gl_FUNC_ARGZ])dnl + +m4_require([_LT_CHECK_OBJDIR])dnl +m4_require([_LT_HEADER_DLFCN])dnl +m4_require([_LT_CHECK_DLPREOPEN])dnl +m4_require([_LT_DECL_SED])dnl + +dnl Don't require this, or it will be expanded earlier than the code +dnl that sets the variables it relies on: +_LT_ENABLE_INSTALL + +dnl _LTDL_MODE specific code must be called at least once: +_LTDL_MODE_DISPATCH + +# In order that ltdl.c can compile, find out the first AC_CONFIG_HEADERS +# the user used. This is so that ltdl.h can pick up the parent projects +# config.h file, The first file in AC_CONFIG_HEADERS must contain the +# definitions required by ltdl.c. +# FIXME: Remove use of undocumented AC_LIST_HEADERS (2.59 compatibility). +AC_CONFIG_COMMANDS_PRE([dnl +m4_pattern_allow([^LT_CONFIG_H$])dnl +m4_ifset([AH_HEADER], + [LT_CONFIG_H=AH_HEADER], + [m4_ifset([AC_LIST_HEADERS], + [LT_CONFIG_H=`echo "AC_LIST_HEADERS" | $SED 's,^[[ ]]*,,;s,[[ :]].*$,,'`], + [])])]) +AC_SUBST([LT_CONFIG_H]) + +AC_CHECK_HEADERS([unistd.h dl.h sys/dl.h dld.h mach-o/dyld.h dirent.h], + [], [], [AC_INCLUDES_DEFAULT]) + +AC_CHECK_FUNCS([closedir opendir readdir], [], [AC_LIBOBJ([lt__dirent])]) +AC_CHECK_FUNCS([strlcat strlcpy], [], [AC_LIBOBJ([lt__strl])]) + +m4_pattern_allow([LT_LIBEXT])dnl +AC_DEFINE_UNQUOTED([LT_LIBEXT],["$libext"],[The archive extension]) + +name= +eval "lt_libprefix=\"$libname_spec\"" +m4_pattern_allow([LT_LIBPREFIX])dnl +AC_DEFINE_UNQUOTED([LT_LIBPREFIX],["$lt_libprefix"],[The archive prefix]) + +name=ltdl +eval "LTDLOPEN=\"$libname_spec\"" +AC_SUBST([LTDLOPEN]) +])# _LTDL_SETUP + + +# _LT_ENABLE_INSTALL +# ------------------ +m4_define([_LT_ENABLE_INSTALL], +[AC_ARG_ENABLE([ltdl-install], + [AS_HELP_STRING([--enable-ltdl-install], [install libltdl])]) + +case ,${enable_ltdl_install},${enable_ltdl_convenience} in + *yes*) ;; + *) enable_ltdl_convenience=yes ;; +esac + +m4_ifdef([AM_CONDITIONAL], +[AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) + AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno)]) +])# _LT_ENABLE_INSTALL + + +# LT_SYS_DLOPEN_DEPLIBS +# --------------------- +AC_DEFUN([LT_SYS_DLOPEN_DEPLIBS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CACHE_CHECK([whether deplibs are loaded by dlopen], + [lt_cv_sys_dlopen_deplibs], + [# PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + lt_cv_sys_dlopen_deplibs=unknown + case $host_os in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + lt_cv_sys_dlopen_deplibs=unknown + ;; + aix[[4-9]]*) + lt_cv_sys_dlopen_deplibs=yes + ;; + amigaos*) + case $host_cpu in + powerpc) + lt_cv_sys_dlopen_deplibs=no + ;; + esac + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + lt_cv_sys_dlopen_deplibs=yes + ;; + freebsd* | dragonfly*) + lt_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | k*bsd*-gnu | kopensolaris*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + lt_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + lt_cv_sys_dlopen_deplibs=yes + ;; + interix*) + lt_cv_sys_dlopen_deplibs=yes + ;; + irix[[12345]]*|irix6.[[01]]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + lt_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + lt_cv_sys_dlopen_deplibs=yes + ;; + netbsd*) + lt_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + lt_cv_sys_dlopen_deplibs=yes + ;; + osf[[1234]]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explicitly say `no'. + lt_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + lt_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + lt_cv_sys_dlopen_deplibs=yes + ;; + qnx*) + lt_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + lt_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + ]) +if test "$lt_cv_sys_dlopen_deplibs" != yes; then + AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], + [Define if the OS needs help to load dependent libraries for dlopen().]) +fi +])# LT_SYS_DLOPEN_DEPLIBS + +# Old name: +AU_ALIAS([AC_LTDL_SYS_DLOPEN_DEPLIBS], [LT_SYS_DLOPEN_DEPLIBS]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], []) + + +# LT_SYS_MODULE_EXT +# ----------------- +AC_DEFUN([LT_SYS_MODULE_EXT], +[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl +AC_CACHE_CHECK([which extension is used for runtime loadable modules], + [libltdl_cv_shlibext], +[ +module=yes +eval libltdl_cv_shlibext=$shrext_cmds +module=no +eval libltdl_cv_shrext=$shrext_cmds + ]) +if test -n "$libltdl_cv_shlibext"; then + m4_pattern_allow([LT_MODULE_EXT])dnl + AC_DEFINE_UNQUOTED([LT_MODULE_EXT], ["$libltdl_cv_shlibext"], + [Define to the extension used for runtime loadable modules, say, ".so".]) +fi +if test "$libltdl_cv_shrext" != "$libltdl_cv_shlibext"; then + m4_pattern_allow([LT_SHARED_EXT])dnl + AC_DEFINE_UNQUOTED([LT_SHARED_EXT], ["$libltdl_cv_shrext"], + [Define to the shared library suffix, say, ".dylib".]) +fi +])# LT_SYS_MODULE_EXT + +# Old name: +AU_ALIAS([AC_LTDL_SHLIBEXT], [LT_SYS_MODULE_EXT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LTDL_SHLIBEXT], []) + + +# LT_SYS_MODULE_PATH +# ------------------ +AC_DEFUN([LT_SYS_MODULE_PATH], +[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl +AC_CACHE_CHECK([which variable specifies run-time module search path], + [lt_cv_module_path_var], [lt_cv_module_path_var="$shlibpath_var"]) +if test -n "$lt_cv_module_path_var"; then + m4_pattern_allow([LT_MODULE_PATH_VAR])dnl + AC_DEFINE_UNQUOTED([LT_MODULE_PATH_VAR], ["$lt_cv_module_path_var"], + [Define to the name of the environment variable that determines the run-time module search path.]) +fi +])# LT_SYS_MODULE_PATH + +# Old name: +AU_ALIAS([AC_LTDL_SHLIBPATH], [LT_SYS_MODULE_PATH]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LTDL_SHLIBPATH], []) + + +# LT_SYS_DLSEARCH_PATH +# -------------------- +AC_DEFUN([LT_SYS_DLSEARCH_PATH], +[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl +AC_CACHE_CHECK([for the default library search path], + [lt_cv_sys_dlsearch_path], + [lt_cv_sys_dlsearch_path="$sys_lib_dlsearch_path_spec"]) +if test -n "$lt_cv_sys_dlsearch_path"; then + sys_dlsearch_path= + for dir in $lt_cv_sys_dlsearch_path; do + if test -z "$sys_dlsearch_path"; then + sys_dlsearch_path="$dir" + else + sys_dlsearch_path="$sys_dlsearch_path$PATH_SEPARATOR$dir" + fi + done + m4_pattern_allow([LT_DLSEARCH_PATH])dnl + AC_DEFINE_UNQUOTED([LT_DLSEARCH_PATH], ["$sys_dlsearch_path"], + [Define to the system default library search path.]) +fi +])# LT_SYS_DLSEARCH_PATH + +# Old name: +AU_ALIAS([AC_LTDL_SYSSEARCHPATH], [LT_SYS_DLSEARCH_PATH]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LTDL_SYSSEARCHPATH], []) + + +# _LT_CHECK_DLPREOPEN +# ------------------- +m4_defun([_LT_CHECK_DLPREOPEN], +[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + [libltdl_cv_preloaded_symbols], + [if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + ]) +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1], + [Define if libtool can extract symbol lists from object files.]) +fi +])# _LT_CHECK_DLPREOPEN + + +# LT_LIB_DLLOAD +# ------------- +AC_DEFUN([LT_LIB_DLLOAD], +[m4_pattern_allow([^LT_DLLOADERS$]) +LT_DLLOADERS= +AC_SUBST([LT_DLLOADERS]) + +AC_LANG_PUSH([C]) + +LIBADD_DLOPEN= +AC_SEARCH_LIBS([dlopen], [dl], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + if test "$ac_cv_search_dlopen" != "none required" ; then + LIBADD_DLOPEN="-ldl" + fi + libltdl_cv_lib_dl_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H +# include +#endif + ]], [[dlopen(0, 0);]])], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + libltdl_cv_func_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"], + [AC_CHECK_LIB([svld], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"])])]) +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DLOPEN" + AC_CHECK_FUNCS([dlerror]) + LIBS="$lt_save_LIBS" +fi +AC_SUBST([LIBADD_DLOPEN]) + +LIBADD_SHL_LOAD= +AC_CHECK_FUNC([shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"], + [AC_CHECK_LIB([dld], [shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la" + LIBADD_SHL_LOAD="-ldld"])]) +AC_SUBST([LIBADD_SHL_LOAD]) + +case $host_os in +darwin[[1567]].*) +# We only want this for pre-Mac OS X 10.4. + AC_CHECK_FUNC([_dyld_func_lookup], + [AC_DEFINE([HAVE_DYLD], [1], + [Define if you have the _dyld_func_lookup function.]) + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dyld.la"]) + ;; +beos*) + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}load_add_on.la" + ;; +cygwin* | mingw* | os2* | pw32*) + AC_CHECK_DECLS([cygwin_conv_path], [], [], [[#include ]]) + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}loadlibrary.la" + ;; +esac + +AC_CHECK_LIB([dld], [dld_link], + [AC_DEFINE([HAVE_DLD], [1], + [Define if you have the GNU dld library.]) + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dld_link.la"]) +AC_SUBST([LIBADD_DLD_LINK]) + +m4_pattern_allow([^LT_DLPREOPEN$]) +LT_DLPREOPEN= +if test -n "$LT_DLLOADERS" +then + for lt_loader in $LT_DLLOADERS; do + LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen $lt_loader " + done + AC_DEFINE([HAVE_LIBDLLOADER], [1], + [Define if libdlloader will be built on this platform]) +fi +AC_SUBST([LT_DLPREOPEN]) + +dnl This isn't used anymore, but set it for backwards compatibility +LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD" +AC_SUBST([LIBADD_DL]) + +AC_LANG_POP +])# LT_LIB_DLLOAD + +# Old name: +AU_ALIAS([AC_LTDL_DLLIB], [LT_LIB_DLLOAD]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LTDL_DLLIB], []) + + +# LT_SYS_SYMBOL_USCORE +# -------------------- +# does the compiler prefix global symbols with an underscore? +AC_DEFUN([LT_SYS_SYMBOL_USCORE], +[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +AC_CACHE_CHECK([for _ prefix in compiled symbols], + [lt_cv_sys_symbol_underscore], + [lt_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext <<_LT_EOF +void nm_test_func(){} +int main(){nm_test_func;return 0;} +_LT_EOF + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + lt_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.c >&AS_MESSAGE_LOG_FD + fi + rm -rf conftest* + ]) + sys_symbol_underscore=$lt_cv_sys_symbol_underscore + AC_SUBST([sys_symbol_underscore]) +])# LT_SYS_SYMBOL_USCORE + +# Old name: +AU_ALIAS([AC_LTDL_SYMBOL_USCORE], [LT_SYS_SYMBOL_USCORE]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LTDL_SYMBOL_USCORE], []) + + +# LT_FUNC_DLSYM_USCORE +# -------------------- +AC_DEFUN([LT_FUNC_DLSYM_USCORE], +[AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl +if test x"$lt_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + [libltdl_cv_need_uscore], + [libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DLOPEN" + _LT_TRY_DLOPEN_SELF( + [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], + [], [libltdl_cv_need_uscore=cross]) + LIBS="$save_LIBS" + ]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE([NEED_USCORE], [1], + [Define if dlsym() requires a leading underscore in symbol names.]) +fi +])# LT_FUNC_DLSYM_USCORE + +# Old name: +AU_ALIAS([AC_LTDL_DLSYM_USCORE], [LT_FUNC_DLSYM_USCORE]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LTDL_DLSYM_USCORE], []) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright © 2004 Scott James Remnant . +# +# 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[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. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES + +# Copyright (C) 2002-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.12' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.12.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.12.5])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], +[$0: two- and three-arguments forms are deprecated. For more info, see: +http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +dnl Support for Objective C++ was only introduced in Autoconf 2.65, +dnl but we still cater to Autoconf 2.62. +m4_ifdef([AC_PROG_OBJCXX], +[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_CC_C_O +# -------------- +# Like AC_PROG_CC_C_O, but changed for automake. +AC_DEFUN([AM_PROG_CC_C_O], +[AC_REQUIRE([AC_PROG_CC_C_O])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of '-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([macros/afs-check.m4]) +m4_include([macros/ax_pthread.m4]) +m4_include([macros/cnid-backend.m4]) +m4_include([macros/config-checks.m4]) +m4_include([macros/db3-check.m4]) +m4_include([macros/grep-check.m4]) +m4_include([macros/gssapi-check.m4]) +m4_include([macros/iconv.m4]) +m4_include([macros/largefile-check.m4]) +m4_include([macros/libgcrypt.m4]) +m4_include([macros/libtool.m4]) +m4_include([macros/ltoptions.m4]) +m4_include([macros/ltsugar.m4]) +m4_include([macros/ltversion.m4]) +m4_include([macros/lt~obsolete.m4]) +m4_include([macros/netatalk.m4]) +m4_include([macros/pam-check.m4]) +m4_include([macros/perl-check.m4]) +m4_include([macros/ps-check.m4]) +m4_include([macros/quota-check.m4]) +m4_include([macros/ssl-check.m4]) +m4_include([macros/summary.m4]) +m4_include([macros/tcp-wrappers.m4]) +m4_include([macros/util.m4]) +m4_include([macros/zeroconf.m4]) diff --git a/bin/Makefile.am b/bin/Makefile.am new file mode 100644 index 0000000..9aedd4b --- /dev/null +++ b/bin/Makefile.am @@ -0,0 +1,7 @@ +# Makefile.am for bin/ + +SUBDIRS = afppasswd cnid megatron misc + +if HAVE_ATFUNCS +SUBDIRS += ad +endif diff --git a/bin/Makefile.in b/bin/Makefile.in new file mode 100644 index 0000000..3d49f36 --- /dev/null +++ b/bin/Makefile.in @@ -0,0 +1,707 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for bin/ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_ATFUNCS_TRUE@am__append_1 = ad +subdir = bin +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = afppasswd cnid megatron misc ad +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = afppasswd cnid megatron misc $(am__append_1) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# 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/bin/ad/Makefile.am b/bin/ad/Makefile.am new file mode 100644 index 0000000..e7b2c14 --- /dev/null +++ b/bin/ad/Makefile.am @@ -0,0 +1,24 @@ +# Makefile.am for bin/ad/ + +noinst_HEADERS = ad.h + +if USE_BDB +bin_PROGRAMS = ad + +ad_SOURCES = \ + ad.c \ + ad_find.c \ + ad_util.c \ + ad_ls.c \ + ad_cp.c \ + ad_mv.c \ + ad_rm.c \ + ad_set.c + +ad_CFLAGS = -D_PATH_AD=\"$(bindir)/ad\" + +ad_LDADD = \ + $(top_builddir)/libatalk/libatalk.la \ + @ACL_LIBS@ @MYSQL_LIBS@ + +endif diff --git a/bin/ad/Makefile.in b/bin/ad/Makefile.in new file mode 100644 index 0000000..c266092 --- /dev/null +++ b/bin/ad/Makefile.in @@ -0,0 +1,844 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for bin/ad/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@USE_BDB_TRUE@bin_PROGRAMS = ad$(EXEEXT) +subdir = bin/ad +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__ad_SOURCES_DIST = ad.c ad_find.c ad_util.c ad_ls.c ad_cp.c ad_mv.c \ + ad_rm.c ad_set.c +@USE_BDB_TRUE@am_ad_OBJECTS = ad-ad.$(OBJEXT) ad-ad_find.$(OBJEXT) \ +@USE_BDB_TRUE@ ad-ad_util.$(OBJEXT) ad-ad_ls.$(OBJEXT) \ +@USE_BDB_TRUE@ ad-ad_cp.$(OBJEXT) ad-ad_mv.$(OBJEXT) \ +@USE_BDB_TRUE@ ad-ad_rm.$(OBJEXT) ad-ad_set.$(OBJEXT) +ad_OBJECTS = $(am_ad_OBJECTS) +@USE_BDB_TRUE@ad_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ad_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ad_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(ad_SOURCES) +DIST_SOURCES = $(am__ad_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_HEADERS = ad.h +@USE_BDB_TRUE@ad_SOURCES = \ +@USE_BDB_TRUE@ ad.c \ +@USE_BDB_TRUE@ ad_find.c \ +@USE_BDB_TRUE@ ad_util.c \ +@USE_BDB_TRUE@ ad_ls.c \ +@USE_BDB_TRUE@ ad_cp.c \ +@USE_BDB_TRUE@ ad_mv.c \ +@USE_BDB_TRUE@ ad_rm.c \ +@USE_BDB_TRUE@ ad_set.c + +@USE_BDB_TRUE@ad_CFLAGS = -D_PATH_AD=\"$(bindir)/ad\" +@USE_BDB_TRUE@ad_LDADD = \ +@USE_BDB_TRUE@ $(top_builddir)/libatalk/libatalk.la \ +@USE_BDB_TRUE@ @ACL_LIBS@ @MYSQL_LIBS@ + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/ad/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/ad/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +ad$(EXEEXT): $(ad_OBJECTS) $(ad_DEPENDENCIES) $(EXTRA_ad_DEPENDENCIES) + @rm -f ad$(EXEEXT) + $(AM_V_CCLD)$(ad_LINK) $(ad_OBJECTS) $(ad_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad_cp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad_find.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad_ls.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad_mv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad_rm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad_set.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad-ad_util.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +ad-ad.o: ad.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad.o -MD -MP -MF $(DEPDIR)/ad-ad.Tpo -c -o ad-ad.o `test -f 'ad.c' || echo '$(srcdir)/'`ad.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad.Tpo $(DEPDIR)/ad-ad.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad.c' object='ad-ad.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad.o `test -f 'ad.c' || echo '$(srcdir)/'`ad.c + +ad-ad.obj: ad.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad.obj -MD -MP -MF $(DEPDIR)/ad-ad.Tpo -c -o ad-ad.obj `if test -f 'ad.c'; then $(CYGPATH_W) 'ad.c'; else $(CYGPATH_W) '$(srcdir)/ad.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad.Tpo $(DEPDIR)/ad-ad.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad.c' object='ad-ad.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad.obj `if test -f 'ad.c'; then $(CYGPATH_W) 'ad.c'; else $(CYGPATH_W) '$(srcdir)/ad.c'; fi` + +ad-ad_find.o: ad_find.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_find.o -MD -MP -MF $(DEPDIR)/ad-ad_find.Tpo -c -o ad-ad_find.o `test -f 'ad_find.c' || echo '$(srcdir)/'`ad_find.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_find.Tpo $(DEPDIR)/ad-ad_find.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_find.c' object='ad-ad_find.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_find.o `test -f 'ad_find.c' || echo '$(srcdir)/'`ad_find.c + +ad-ad_find.obj: ad_find.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_find.obj -MD -MP -MF $(DEPDIR)/ad-ad_find.Tpo -c -o ad-ad_find.obj `if test -f 'ad_find.c'; then $(CYGPATH_W) 'ad_find.c'; else $(CYGPATH_W) '$(srcdir)/ad_find.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_find.Tpo $(DEPDIR)/ad-ad_find.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_find.c' object='ad-ad_find.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_find.obj `if test -f 'ad_find.c'; then $(CYGPATH_W) 'ad_find.c'; else $(CYGPATH_W) '$(srcdir)/ad_find.c'; fi` + +ad-ad_util.o: ad_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_util.o -MD -MP -MF $(DEPDIR)/ad-ad_util.Tpo -c -o ad-ad_util.o `test -f 'ad_util.c' || echo '$(srcdir)/'`ad_util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_util.Tpo $(DEPDIR)/ad-ad_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_util.c' object='ad-ad_util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_util.o `test -f 'ad_util.c' || echo '$(srcdir)/'`ad_util.c + +ad-ad_util.obj: ad_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_util.obj -MD -MP -MF $(DEPDIR)/ad-ad_util.Tpo -c -o ad-ad_util.obj `if test -f 'ad_util.c'; then $(CYGPATH_W) 'ad_util.c'; else $(CYGPATH_W) '$(srcdir)/ad_util.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_util.Tpo $(DEPDIR)/ad-ad_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_util.c' object='ad-ad_util.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_util.obj `if test -f 'ad_util.c'; then $(CYGPATH_W) 'ad_util.c'; else $(CYGPATH_W) '$(srcdir)/ad_util.c'; fi` + +ad-ad_ls.o: ad_ls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_ls.o -MD -MP -MF $(DEPDIR)/ad-ad_ls.Tpo -c -o ad-ad_ls.o `test -f 'ad_ls.c' || echo '$(srcdir)/'`ad_ls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_ls.Tpo $(DEPDIR)/ad-ad_ls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_ls.c' object='ad-ad_ls.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_ls.o `test -f 'ad_ls.c' || echo '$(srcdir)/'`ad_ls.c + +ad-ad_ls.obj: ad_ls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_ls.obj -MD -MP -MF $(DEPDIR)/ad-ad_ls.Tpo -c -o ad-ad_ls.obj `if test -f 'ad_ls.c'; then $(CYGPATH_W) 'ad_ls.c'; else $(CYGPATH_W) '$(srcdir)/ad_ls.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_ls.Tpo $(DEPDIR)/ad-ad_ls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_ls.c' object='ad-ad_ls.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_ls.obj `if test -f 'ad_ls.c'; then $(CYGPATH_W) 'ad_ls.c'; else $(CYGPATH_W) '$(srcdir)/ad_ls.c'; fi` + +ad-ad_cp.o: ad_cp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_cp.o -MD -MP -MF $(DEPDIR)/ad-ad_cp.Tpo -c -o ad-ad_cp.o `test -f 'ad_cp.c' || echo '$(srcdir)/'`ad_cp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_cp.Tpo $(DEPDIR)/ad-ad_cp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_cp.c' object='ad-ad_cp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_cp.o `test -f 'ad_cp.c' || echo '$(srcdir)/'`ad_cp.c + +ad-ad_cp.obj: ad_cp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_cp.obj -MD -MP -MF $(DEPDIR)/ad-ad_cp.Tpo -c -o ad-ad_cp.obj `if test -f 'ad_cp.c'; then $(CYGPATH_W) 'ad_cp.c'; else $(CYGPATH_W) '$(srcdir)/ad_cp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_cp.Tpo $(DEPDIR)/ad-ad_cp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_cp.c' object='ad-ad_cp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_cp.obj `if test -f 'ad_cp.c'; then $(CYGPATH_W) 'ad_cp.c'; else $(CYGPATH_W) '$(srcdir)/ad_cp.c'; fi` + +ad-ad_mv.o: ad_mv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_mv.o -MD -MP -MF $(DEPDIR)/ad-ad_mv.Tpo -c -o ad-ad_mv.o `test -f 'ad_mv.c' || echo '$(srcdir)/'`ad_mv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_mv.Tpo $(DEPDIR)/ad-ad_mv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_mv.c' object='ad-ad_mv.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_mv.o `test -f 'ad_mv.c' || echo '$(srcdir)/'`ad_mv.c + +ad-ad_mv.obj: ad_mv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_mv.obj -MD -MP -MF $(DEPDIR)/ad-ad_mv.Tpo -c -o ad-ad_mv.obj `if test -f 'ad_mv.c'; then $(CYGPATH_W) 'ad_mv.c'; else $(CYGPATH_W) '$(srcdir)/ad_mv.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_mv.Tpo $(DEPDIR)/ad-ad_mv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_mv.c' object='ad-ad_mv.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_mv.obj `if test -f 'ad_mv.c'; then $(CYGPATH_W) 'ad_mv.c'; else $(CYGPATH_W) '$(srcdir)/ad_mv.c'; fi` + +ad-ad_rm.o: ad_rm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_rm.o -MD -MP -MF $(DEPDIR)/ad-ad_rm.Tpo -c -o ad-ad_rm.o `test -f 'ad_rm.c' || echo '$(srcdir)/'`ad_rm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_rm.Tpo $(DEPDIR)/ad-ad_rm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_rm.c' object='ad-ad_rm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_rm.o `test -f 'ad_rm.c' || echo '$(srcdir)/'`ad_rm.c + +ad-ad_rm.obj: ad_rm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_rm.obj -MD -MP -MF $(DEPDIR)/ad-ad_rm.Tpo -c -o ad-ad_rm.obj `if test -f 'ad_rm.c'; then $(CYGPATH_W) 'ad_rm.c'; else $(CYGPATH_W) '$(srcdir)/ad_rm.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_rm.Tpo $(DEPDIR)/ad-ad_rm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_rm.c' object='ad-ad_rm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_rm.obj `if test -f 'ad_rm.c'; then $(CYGPATH_W) 'ad_rm.c'; else $(CYGPATH_W) '$(srcdir)/ad_rm.c'; fi` + +ad-ad_set.o: ad_set.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_set.o -MD -MP -MF $(DEPDIR)/ad-ad_set.Tpo -c -o ad-ad_set.o `test -f 'ad_set.c' || echo '$(srcdir)/'`ad_set.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_set.Tpo $(DEPDIR)/ad-ad_set.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_set.c' object='ad-ad_set.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_set.o `test -f 'ad_set.c' || echo '$(srcdir)/'`ad_set.c + +ad-ad_set.obj: ad_set.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -MT ad-ad_set.obj -MD -MP -MF $(DEPDIR)/ad-ad_set.Tpo -c -o ad-ad_set.obj `if test -f 'ad_set.c'; then $(CYGPATH_W) 'ad_set.c'; else $(CYGPATH_W) '$(srcdir)/ad_set.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ad-ad_set.Tpo $(DEPDIR)/ad-ad_set.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ad_set.c' object='ad-ad_set.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ad_CFLAGS) $(CFLAGS) -c -o ad-ad_set.obj `if test -f 'ad_set.c'; then $(CYGPATH_W) 'ad_set.c'; else $(CYGPATH_W) '$(srcdir)/ad_set.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS + + +# 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/bin/ad/ad.c b/bin/ad/ad.c new file mode 100644 index 0000000..fc8563c --- /dev/null +++ b/bin/ad/ad.c @@ -0,0 +1,90 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ad.h" + +static void usage_main(void) +{ + printf("Usage: ad ls|cp|rm|mv|set|find [file|dir, ...]\n"); + printf(" ad -v|--version\n"); +} + +static void show_version(void) +{ + printf("ad (Netatalk %s)\n", VERSION); +} + +int main(int argc, char **argv) +{ + AFPObj obj = { 0 }; + + if (argc < 2) { + usage_main(); + return 1; + } + + if (afp_config_parse(&obj, "ad") != 0) + return 1; + + setuplog("default:note", "/dev/tty"); + + if (load_volumes(&obj, lv_none) != 0) + return 1; + + if (STRCMP(argv[1], ==, "ls")) + return ad_ls(argc - 1, argv + 1, &obj); + else if (STRCMP(argv[1], ==, "cp")) + return ad_cp(argc - 1, argv + 1, &obj); + else if (STRCMP(argv[1], ==, "rm")) + return ad_rm(argc - 1, argv + 1, &obj); + else if (STRCMP(argv[1], ==, "mv")) + return ad_mv(argc, argv, &obj); + else if (STRCMP(argv[1], ==, "set")) + return ad_set(argc - 1, argv + 1, &obj); + else if (STRCMP(argv[1], ==, "find")) + return ad_find(argc, argv, &obj); + else if (STRCMP(argv[1], ==, "-v")) { + show_version(); + return 1; + } + else if (STRCMP(argv[1], ==, "--version")) { + show_version(); + return 1; + } + else { + usage_main(); + return 1; + } + + return 0; +} diff --git a/bin/ad/ad.h b/bin/ad/ad.h new file mode 100644 index 0000000..9155900 --- /dev/null +++ b/bin/ad/ad.h @@ -0,0 +1,85 @@ +/* + Copyright (c) 2009,2011 Frank Lahm + + 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. +*/ + +#ifndef AD_H +#define AD_H + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DIR_DOT_OR_DOTDOT(a) \ + ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0)) + +#ifndef TIMESPEC_TO_TIMEVAL +#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ + } +#endif + +#define ADVOL_V2_OR_EA(ad) ((ad) == AD_VERSION2 || (ad) == AD_VERSION_EA) + +enum logtype {STD, DBG}; + +#define SLOG(...) \ + _log(STD, __VA_ARGS__) + +#define ERROR(...) \ + do { \ + _log(STD, __VA_ARGS__); \ + exit(1); \ + } while (0) + +typedef struct { + struct vol *vol; + char db_stamp[ADEDLEN_PRIVSYN]; +} afpvol_t; + +extern int log_verbose; /* Logging flag */ +extern void _log(enum logtype lt, char *fmt, ...); + +extern int ad_ls(int argc, char **argv, AFPObj *obj); +extern int ad_cp(int argc, char **argv, AFPObj *obj); +extern int ad_rm(int argc, char **argv, AFPObj *obj); +extern int ad_mv(int argc, char **argv, AFPObj *obj); +extern int ad_set(int argc, char **argv, AFPObj *obj); +extern int ad_find(int argc, char **argv, AFPObj *obj); + +/* ad_util.c */ +extern int openvol(AFPObj *obj, const char *path, afpvol_t *vol); +extern void closevol(afpvol_t *vol); +extern cnid_t cnid_for_paths_parent(const afpvol_t *vol, const char *path, cnid_t *did); +extern char *utompath(const struct vol *, const char *); +extern int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path, size_t buflen); + +typedef struct { + char *p_end;/* pointer to NULL at end of path */ + char *target_end;/* pointer to end of target base */ + char p_path[MAXPATHLEN + 2];/* pointer to the start of a path */ +} PATH_T; + +extern PATH_T to; +extern int fflag, iflag, lflag, nflag, pflag, vflag; + +#endif /* AD_H */ diff --git a/bin/ad/ad_cp.c b/bin/ad/ad_cp.c new file mode 100644 index 0000000..5cefe96 --- /dev/null +++ b/bin/ad/ad_cp.c @@ -0,0 +1,1020 @@ +/* + * Copyright (c) 2010, Frank Lahm + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * David Hitz of Auspex Systems Inc. + * + * 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. + * 4. 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. + */ + +/* + * Cp copies source files to target files. + * + * The global PATH_T structure "to" always contains the path to the + * current target file. Since fts(3) does not change directories, + * this path can be either absolute or dot-relative. + * + * The basic algorithm is to initialize "to" and use fts(3) to traverse + * the file hierarchy rooted in the argument list. A trivial case is the + * case of 'cp file1 file2'. The more interesting case is the case of + * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the + * path (relative to the root of the traversal) is appended to dir (stored + * in "to") to form the final target path. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ad.h" + +#define STRIP_TRAILING_SLASH(p) { \ + while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \ + *--(p).p_end = 0; \ + } + +static char emptystring[] = ""; + +PATH_T to = { to.p_path, emptystring, "" }; +enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; + +int fflag, iflag, nflag, pflag, vflag; +mode_t mask; + +cnid_t ppdid, pdid, did; /* current dir CNID and parent did*/ + +static afpvol_t svolume, dvolume; +static enum op type; +static int Rflag; +static volatile sig_atomic_t alarmed; +static int badcp, rval; +static int ftw_options = FTW_MOUNT | FTW_PHYS | FTW_ACTIONRETVAL; + +/* Forward declarations */ +static int copy(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf); +static int ftw_copy_file(const struct FTW *, const char *, const struct stat *, int); +static int ftw_copy_link(const struct FTW *, const char *, const struct stat *, int); +static int setfile(const struct stat *, int); +// static int preserve_dir_acls(const struct stat *, char *, char *); +static int preserve_fd_acls(int, int); + +static void upfunc(void) +{ + did = pdid; + pdid = ppdid; +} + +/* + SIGNAL handling: + catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. +*/ + +static void sig_handler(int signo) +{ + alarmed = 1; + return; +} + +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_handler; + sv.sa_flags = SA_RESTART; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGTERM, &sv, NULL) < 0) + ERROR("error in sigaction(SIGTERM): %s", strerror(errno)); + + if (sigaction(SIGINT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGINT): %s", strerror(errno)); + + memset(&sv, 0, sizeof(struct sigaction)); + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + + if (sigaction(SIGABRT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGABRT): %s", strerror(errno)); + + if (sigaction(SIGHUP, &sv, NULL) < 0) + ERROR("error in sigaction(SIGHUP): %s", strerror(errno)); + + if (sigaction(SIGQUIT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGQUIT): %s", strerror(errno)); +} + +static void usage_cp(void) +{ + printf( + "Usage: ad cp [-R] [-aipvf] \n" + " ad cp [-R] [-aipvfx] \n\n" + "In the first synopsis form, the cp utility copies the contents of the source_file to the\n" + "target_file. In the second synopsis form, the contents of each named source_file is copied to the\n" + "destination target_directory. The names of the files themselves are not changed. If cp detects an\n" + "attempt to copy a file to itself, the copy will fail.\n\n" + "Netatalk AFP volumes are detected by means of their \".AppleDesktop\" directory\n" + "which is located in their volume root. When a copy targetting an AFP volume\n" + "is detected, its CNID database daemon is connected and all copies will also\n" + "go through the CNID database.\n" + "AppleDouble files are also copied and created as needed when the target is\n" + "an AFP volume.\n\n" + "The following options are available:\n\n" + " -a Archive mode. Same as -Rp.\n\n" + " -f For each existing destination pathname, remove it and create a new\n" + " file, without prompting for confirmation regardless of its permis-\n" + " sions. (The -f option overrides any previous -i or -n options.)\n\n" + " -i Cause cp to write a prompt to the standard error output before\n" + " copying a file that would overwrite an existing file. If the\n" + " response from the standard input begins with the character 'y' or\n" + " 'Y', the file copy is attempted. (The -i option overrides any pre-\n" + " vious -f or -n options.)\n\n" + " -n Do not overwrite an existing file. (The -n option overrides any\n" + " previous -f or -i options.)\n\n" + " -p Cause cp to preserve the following attributes of each source file\n" + " in the copy: modification time, access time, file flags, file mode,\n" + " user ID, and group ID, as allowed by permissions.\n" + " If the user ID and group ID cannot be preserved, no error message\n" + " is displayed and the exit value is not altered.\n\n" + " -R If source_file designates a directory, cp copies the directory and\n" + " the entire subtree connected at that point.If the source_file\n" + " ends in a /, the contents of the directory are copied rather than\n" + " the directory itself.\n\n" + " -v Cause cp to be verbose, showing files as they are copied.\n\n" + " -x File system mount points are not traversed.\n\n" + ); + exit(EXIT_FAILURE); +} + +int ad_cp(int argc, char *argv[], AFPObj *obj) +{ + struct stat to_stat, tmp_stat; + int r, ch, have_trailing_slash; + char *target; +#if 0 + afpvol_t srcvol; + afpvol_t dstvol; +#endif + + ppdid = pdid = htonl(1); + did = htonl(2); + + while ((ch = getopt(argc, argv, "afinpRvx")) != -1) + switch (ch) { + case 'a': + pflag = 1; + Rflag = 1; + break; + case 'f': + fflag = 1; + iflag = nflag = 0; + break; + case 'i': + iflag = 1; + fflag = nflag = 0; + break; + case 'n': + nflag = 1; + fflag = iflag = 0; + break; + case 'p': + pflag = 1; + break; + case 'R': + Rflag = 1; + break; + case 'v': + vflag = 1; + break; + case 'x': + ftw_options |= FTW_MOUNT; + break; + default: + usage_cp(); + break; + } + argc -= optind; + argv += optind; + + if (argc < 2) + usage_cp(); + + set_signal(); + cnid_init(); + + /* Save the target base in "to". */ + target = argv[--argc]; + if ((strlcpy(to.p_path, target, PATH_MAX)) >= PATH_MAX) + ERROR("%s: name too long", target); + + to.p_end = to.p_path + strlen(to.p_path); + if (to.p_path == to.p_end) { + *to.p_end++ = '.'; + *to.p_end = 0; + } + have_trailing_slash = (to.p_end[-1] == '/'); + if (have_trailing_slash) + STRIP_TRAILING_SLASH(to); + to.target_end = to.p_end; + + /* Set end of argument list */ + argv[argc] = NULL; + + /* + * Cp has two distinct cases: + * + * cp [-R] source target + * cp [-R] source1 ... sourceN directory + * + * In both cases, source can be either a file or a directory. + * + * In (1), the target becomes a copy of the source. That is, if the + * source is a file, the target will be a file, and likewise for + * directories. + * + * In (2), the real target is not directory, but "directory/source". + */ + r = stat(to.p_path, &to_stat); + if (r == -1 && errno != ENOENT) + ERROR("%s", to.p_path); + if (r == -1 || !S_ISDIR(to_stat.st_mode)) { + /* + * Case (1). Target is not a directory. + */ + if (argc > 1) + ERROR("%s is not a directory", to.p_path); + + /* + * Need to detect the case: + *cp -R dir foo + * Where dir is a directory and foo does not exist, where + * we want pathname concatenations turned on but not for + * the initial mkdir(). + */ + if (r == -1) { + lstat(*argv, &tmp_stat); + + if (S_ISDIR(tmp_stat.st_mode) && Rflag) + type = DIR_TO_DNE; + else + type = FILE_TO_FILE; + } else + type = FILE_TO_FILE; + + if (have_trailing_slash && type == FILE_TO_FILE) { + if (r == -1) + ERROR("directory %s does not exist", to.p_path); + else + ERROR("%s is not a directory", to.p_path); + } + } else + /* + * Case (2). Target is a directory. + */ + type = FILE_TO_DIR; + + /* + * Keep an inverted copy of the umask, for use in correcting + * permissions on created directories when not using -p. + */ + mask = ~umask(0777); + umask(~mask); + +#if 0 + /* Inhereting perms in ad_mkdir etc requires this */ + ad_setfuid(0); +#endif + + /* Load .volinfo file for destination*/ + openvol(obj, to.p_path, &dvolume); + + for (int i = 0; argv[i] != NULL; i++) { + /* Load .volinfo file for source */ + openvol(obj, argv[i], &svolume); + + if (nftw(argv[i], copy, upfunc, 20, ftw_options) == -1) { + if (alarmed) { + SLOG("...break"); + } else { + SLOG("Error: %s: %s", argv[i], strerror(errno)); + } + closevol(&svolume); + closevol(&dvolume); + } + } + return rval; +} + +static int copy(const char *path, + const struct stat *statp, + int tflag, + struct FTW *ftw) +{ + static int base = 0; + + struct stat to_stat; + int dne; + size_t nlen; + const char *p; + char *target_mid; + + if (alarmed) + return -1; + + /* This currently doesn't work with "." */ + if (strcmp(path, ".") == 0) { + ERROR("\".\" not supported"); + } + const char *dir = strrchr(path, '/'); + if (dir == NULL) + dir = path; + else + dir++; + if (!dvolume.vol->vfs->vfs_validupath(dvolume.vol, dir)) + return FTW_SKIP_SUBTREE; + + /* + * If we are in case (2) above, we need to append the + * source name to the target name. + */ + if (type != FILE_TO_FILE) { + /* + * Need to remember the roots of traversals to create + * correct pathnames. If there's a directory being + * copied to a non-existent directory, e.g. + * cp -R a/dir noexist + * the resulting path name should be noexist/foo, not + * noexist/dir/foo (where foo is a file in dir), which + * is the case where the target exists. + * + * Also, check for "..". This is for correct path + * concatenation for paths ending in "..", e.g. + * cp -R .. /tmp + * Paths ending in ".." are changed to ".". This is + * tricky, but seems the easiest way to fix the problem. + * + * XXX + * Since the first level MUST be FTS_ROOTLEVEL, base + * is always initialized. + */ + if (ftw->level == 0) { + if (type != DIR_TO_DNE) { + base = ftw->base; + + if (strcmp(&path[base], "..") == 0) + base += 1; + } else + base = strlen(path); + } + + p = &path[base]; + nlen = strlen(path) - base; + target_mid = to.target_end; + if (*p != '/' && target_mid[-1] != '/') + *target_mid++ = '/'; + *target_mid = 0; + if (target_mid - to.p_path + nlen >= PATH_MAX) { + SLOG("%s%s: name too long (not copied)", to.p_path, p); + badcp = rval = 1; + return 0; + } + (void)strncat(target_mid, p, nlen); + to.p_end = target_mid + nlen; + *to.p_end = 0; + STRIP_TRAILING_SLASH(to); + } + + /* Not an error but need to remember it happened */ + if (stat(to.p_path, &to_stat) == -1) + dne = 1; + else { + if (to_stat.st_dev == statp->st_dev && + to_stat.st_ino == statp->st_ino) { + SLOG("%s and %s are identical (not copied).", to.p_path, path); + badcp = rval = 1; + if (S_ISDIR(statp->st_mode)) + /* without using glibc extension FTW_ACTIONRETVAL cant handle this */ + return FTW_SKIP_SUBTREE; + return 0; + } + if (!S_ISDIR(statp->st_mode) && + S_ISDIR(to_stat.st_mode)) { + SLOG("cannot overwrite directory %s with " + "non-directory %s", + to.p_path, path); + badcp = rval = 1; + return 0; + } + dne = 0; + } + + /* Convert basename to appropiate volume encoding */ + if (dvolume.vol->v_path) { + if ((convert_dots_encoding(&svolume, &dvolume, to.p_path, MAXPATHLEN)) == -1) { + SLOG("Error converting name for %s", to.p_path); + badcp = rval = 1; + return -1; + } + } + + switch (statp->st_mode & S_IFMT) { + case S_IFLNK: + if (ftw_copy_link(ftw, path, statp, !dne)) + badcp = rval = 1; + break; + case S_IFDIR: + if (!Rflag) { + SLOG("%s is a directory", path); + badcp = rval = 1; + return -1; + } + /* + * If the directory doesn't exist, create the new + * one with the from file mode plus owner RWX bits, + * modified by the umask. Trade-off between being + * able to write the directory (if from directory is + * 555) and not causing a permissions race. If the + * umask blocks owner writes, we fail.. + */ + if (dne) { + if (mkdir(to.p_path, statp->st_mode | S_IRWXU) < 0) + ERROR("mkdir: %s: %s", to.p_path, strerror(errno)); + } else if (!S_ISDIR(to_stat.st_mode)) { + errno = ENOTDIR; + ERROR("%s", to.p_path); + } + + /* Create ad dir and copy ".Parent" */ + if (dvolume.vol->v_path && ADVOL_V2_OR_EA(dvolume.vol->v_adouble)) { + mode_t omask = umask(0); + if (dvolume.vol->v_adouble == AD_VERSION2) { + /* Create ".AppleDouble" dir */ + bstring addir = bfromcstr(to.p_path); + bcatcstr(addir, "/.AppleDouble"); + mkdir(cfrombstr(addir), 02777); + bdestroy(addir); + } + + if (svolume.vol->v_path && ADVOL_V2_OR_EA(svolume.vol->v_adouble)) { + /* copy metadata file */ + if (dvolume.vol->vfs->vfs_copyfile(dvolume.vol, -1, path, to.p_path)) { + SLOG("Error copying adouble for %s -> %s", path, to.p_path); + badcp = rval = 1; + break; + } + } + + /* Get CNID of Parent and add new childir to CNID database */ + ppdid = pdid; + if ((did = cnid_for_path(dvolume.vol->v_cdb, dvolume.vol->v_path, to.p_path, &pdid)) == CNID_INVALID) { + SLOG("Error resolving CNID for %s", to.p_path); + badcp = rval = 1; + return -1; + } + + struct adouble ad; + struct stat st; + if (lstat(to.p_path, &st) != 0) { + badcp = rval = 1; + break; + } + ad_init(&ad, dvolume.vol); + if (ad_open(&ad, to.p_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) { + ERROR("Error opening adouble for: %s", to.p_path); + } + ad_setid( &ad, st.st_dev, st.st_ino, did, pdid, dvolume.db_stamp); + if (dvolume.vol->v_adouble == AD_VERSION2) + ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path))); + ad_setdate(&ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime); + ad_setdate(&ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime); + ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime); + ad_setdate(&ad, AD_DATE_BACKUP, AD_DATE_START); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + + umask(omask); + } + + if (pflag) { + if (setfile(statp, -1)) + rval = 1; +#if 0 + if (preserve_dir_acls(statp, curr->fts_accpath, to.p_path) != 0) + rval = 1; +#endif + } + break; + + case S_IFBLK: + case S_IFCHR: + SLOG("%s is a device file (not copied).", path); + break; + case S_IFSOCK: + SLOG("%s is a socket (not copied).", path); + break; + case S_IFIFO: + SLOG("%s is a FIFO (not copied).", path); + break; + default: + if (ftw_copy_file(ftw, path, statp, dne)) + badcp = rval = 1; + + if (dvolume.vol->v_path && ADVOL_V2_OR_EA(dvolume.vol->v_adouble)) { + + mode_t omask = umask(0); + if (svolume.vol->v_path && ADVOL_V2_OR_EA(svolume.vol->v_adouble)) { + /* copy ad-file */ + if (dvolume.vol->vfs->vfs_copyfile(dvolume.vol, -1, path, to.p_path)) { + SLOG("Error copying adouble for %s -> %s", path, to.p_path); + badcp = rval = 1; + break; + } + } + + /* Get CNID of Parent and add new childir to CNID database */ + pdid = did; + cnid_t cnid; + if ((cnid = cnid_for_path(dvolume.vol->v_cdb, dvolume.vol->v_path, to.p_path, &did)) == CNID_INVALID) { + SLOG("Error resolving CNID for %s", to.p_path); + badcp = rval = 1; + return -1; + } + + struct adouble ad; + struct stat st; + if (lstat(to.p_path, &st) != 0) { + badcp = rval = 1; + break; + } + ad_init(&ad, dvolume.vol); + if (ad_open(&ad, to.p_path, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) { + ERROR("Error opening adouble for: %s", to.p_path); + } + ad_setid( &ad, st.st_dev, st.st_ino, cnid, did, dvolume.db_stamp); + if (dvolume.vol->v_adouble == AD_VERSION2) + ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path))); + ad_setdate(&ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime); + ad_setdate(&ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime); + ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime); + ad_setdate(&ad, AD_DATE_BACKUP, AD_DATE_START); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + umask(omask); + } + break; + } + if (vflag && !badcp) + (void)printf("%s -> %s\n", path, to.p_path); + + return 0; +} + +/* Memory strategy threshold, in pages: if physmem is larger then this, use a large buffer */ +#define PHYSPAGES_THRESHOLD (32*1024) + +/* Maximum buffer size in bytes - do not allow it to grow larger than this */ +#define BUFSIZE_MAX (2*1024*1024) + +/* Small (default) buffer size in bytes. It's inefficient for this to be smaller than MAXPHYS */ +#define MAXPHYS (64 * 1024) +#define BUFSIZE_SMALL (MAXPHYS) + +static int ftw_copy_file(const struct FTW *entp, + const char *spath, + const struct stat *sp, + int dne) +{ + static char *buf = NULL; + static size_t bufsize; + ssize_t wcount; + size_t wresid; + off_t wtotal; + int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0; + char *bufp; + char *p; + + if ((from_fd = open(spath, O_RDONLY, 0)) == -1) { + SLOG("%s: %s", spath, strerror(errno)); + return (1); + } + + /* + * If the file exists and we're interactive, verify with the user. + * If the file DNE, set the mode to be the from file, minus setuid + * bits, modified by the umask; arguably wrong, but it makes copying + * executables work right and it's been that way forever. (The + * other choice is 666 or'ed with the execute bits on the from file + * modified by the umask.) + */ + if (!dne) { +#define YESNO "(y/n [n]) " + if (nflag) { + if (vflag) + printf("%s not overwritten\n", to.p_path); + (void)close(from_fd); + return (0); + } else if (iflag) { + (void)fprintf(stderr, "overwrite %s? %s", + to.p_path, YESNO); + checkch = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + if (checkch != 'y' && checkch != 'Y') { + (void)close(from_fd); + (void)fprintf(stderr, "not overwritten\n"); + return (1); + } + } + + if (fflag) { + /* remove existing destination file name, + * create a new file */ + (void)unlink(to.p_path); + (void)dvolume.vol->vfs->vfs_deletefile(dvolume.vol, -1, to.p_path); + to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, + sp->st_mode & ~(S_ISUID | S_ISGID)); + } else { + /* overwrite existing destination file name */ + to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0); + } + } else { + to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, + sp->st_mode & ~(S_ISUID | S_ISGID)); + } + + if (to_fd == -1) { + SLOG("%s: %s", to.p_path, strerror(errno)); + (void)close(from_fd); + return (1); + } + + rval = 0; + + /* + * Mmap and write if less than 8M (the limit is so we don't totally + * trash memory on big files. This is really a minor hack, but it + * wins some CPU back. + * Some filesystems, such as smbnetfs, don't support mmap, + * so this is a best-effort attempt. + */ + + if (S_ISREG(sp->st_mode) && sp->st_size > 0 && + sp->st_size <= 8 * 1024 * 1024 && + (p = mmap(NULL, (size_t)sp->st_size, PROT_READ, + MAP_SHARED, from_fd, (off_t)0)) != MAP_FAILED) { + wtotal = 0; + for (bufp = p, wresid = sp->st_size; ; + bufp += wcount, wresid -= (size_t)wcount) { + wcount = write(to_fd, bufp, wresid); + if (wcount <= 0) + break; + wtotal += wcount; + if (wcount >= (ssize_t)wresid) + break; + } + if (wcount != (ssize_t)wresid) { + SLOG("%s: %s", to.p_path, strerror(errno)); + rval = 1; + } + /* Some systems don't unmap on close(2). */ + if (munmap(p, sp->st_size) < 0) { + SLOG("%s: %s", spath, strerror(errno)); + rval = 1; + } + } else { + if (buf == NULL) { + /* + * Note that buf and bufsize are static. If + * malloc() fails, it will fail at the start + * and not copy only some files. + */ + if (sysconf(_SC_PHYS_PAGES) > + PHYSPAGES_THRESHOLD) + bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8); + else + bufsize = BUFSIZE_SMALL; + buf = malloc(bufsize); + if (buf == NULL) + ERROR("Not enough memory"); + + } + wtotal = 0; + while ((rcount = read(from_fd, buf, bufsize)) > 0) { + for (bufp = buf, wresid = rcount; ; + bufp += wcount, wresid -= wcount) { + wcount = write(to_fd, bufp, wresid); + if (wcount <= 0) + break; + wtotal += wcount; + if (wcount >= (ssize_t)wresid) + break; + } + if (wcount != (ssize_t)wresid) { + SLOG("%s: %s", to.p_path, strerror(errno)); + rval = 1; + break; + } + } + if (rcount < 0) { + SLOG("%s: %s", spath, strerror(errno)); + rval = 1; + } + } + + /* + * Don't remove the target even after an error. The target might + * not be a regular file, or its attributes might be important, + * or its contents might be irreplaceable. It would only be safe + * to remove it if we created it and its length is 0. + */ + + if (pflag && setfile(sp, to_fd)) + rval = 1; + if (pflag && preserve_fd_acls(from_fd, to_fd) != 0) + rval = 1; + if (close(to_fd)) { + SLOG("%s: %s", to.p_path, strerror(errno)); + rval = 1; + } + + (void)close(from_fd); + + return (rval); +} + +static int ftw_copy_link(const struct FTW *p, + const char *spath, + const struct stat *sstp, + int exists) +{ + int len; + char llink[PATH_MAX]; + + if ((len = readlink(spath, llink, sizeof(llink) - 1)) == -1) { + SLOG("readlink: %s: %s", spath, strerror(errno)); + return (1); + } + llink[len] = '\0'; + if (exists && unlink(to.p_path)) { + SLOG("unlink: %s: %s", to.p_path, strerror(errno)); + return (1); + } + if (symlink(llink, to.p_path)) { + SLOG("symlink: %s: %s", llink, strerror(errno)); + return (1); + } + return (pflag ? setfile(sstp, -1) : 0); +} + +static int setfile(const struct stat *fs, int fd) +{ + static struct timeval tv[2]; + struct stat ts; + int rval, gotstat, islink, fdval; + mode_t mode; + + rval = 0; + fdval = fd != -1; + islink = !fdval && S_ISLNK(fs->st_mode); + mode = fs->st_mode & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO); + +#if defined(__FreeBSD__) + TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); + TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); +#else + TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim); + TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim); +#endif + + if (utimes(to.p_path, tv)) { + SLOG("utimes: %s", to.p_path); + rval = 1; + } + if (fdval ? fstat(fd, &ts) : + (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts))) + gotstat = 0; + else { + gotstat = 1; + ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | + S_IRWXU | S_IRWXG | S_IRWXO; + } + /* + * Changing the ownership probably won't succeed, unless we're root + * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting + * the mode; current BSD behavior is to remove all setuid bits on + * chown. If chown fails, lose setuid/setgid bits. + */ + if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) + if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : + (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) : + chown(to.p_path, fs->st_uid, fs->st_gid))) { + if (errno != EPERM) { + SLOG("chown: %s: %s", to.p_path, strerror(errno)); + rval = 1; + } + mode &= ~(S_ISUID | S_ISGID); + } + + if (!gotstat || mode != ts.st_mode) + if (fdval ? fchmod(fd, mode) : chmod(to.p_path, mode)) { + SLOG("chmod: %s: %s", to.p_path, strerror(errno)); + rval = 1; + } + +#ifdef HAVE_ST_FLAGS + if (!gotstat || fs->st_flags != ts.st_flags) + if (fdval ? + fchflags(fd, fs->st_flags) : + (islink ? lchflags(to.p_path, fs->st_flags) : + chflags(to.p_path, fs->st_flags))) { + SLOG("chflags: %s: %s", to.p_path, strerror(errno)); + rval = 1; + } +#endif + + return (rval); +} + +static int preserve_fd_acls(int source_fd, int dest_fd) +{ +#if 0 + acl_t acl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; + + ret = fpathconf(source_fd, _PC_ACL_NFS4); + if (ret > 0 ) { + acl_supported = 1; + acl_type = ACL_TYPE_NFS4; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", to.p_path); + return (1); + } + if (acl_supported == 0) { + ret = fpathconf(source_fd, _PC_ACL_EXTENDED); + if (ret > 0 ) { + acl_supported = 1; + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", + to.p_path); + return (1); + } + } + if (acl_supported == 0) + return (0); + + acl = acl_get_fd_np(source_fd, acl_type); + if (acl == NULL) { + warn("failed to get acl entries while setting %s", to.p_path); + return (1); + } + if (acl_is_trivial_np(acl, &trivial)) { + warn("acl_is_trivial() failed for %s", to.p_path); + acl_free(acl); + return (1); + } + if (trivial) { + acl_free(acl); + return (0); + } + if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) { + warn("failed to set acl entries for %s", to.p_path); + acl_free(acl); + return (1); + } + acl_free(acl); +#endif + return (0); +} + +#if 0 +static int preserve_dir_acls(const struct stat *fs, char *source_dir, char *dest_dir) +{ + acl_t (*aclgetf)(const char *, acl_type_t); + int (*aclsetf)(const char *, acl_type_t, acl_t); + struct acl *aclp; + acl_t acl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; + + ret = pathconf(source_dir, _PC_ACL_NFS4); + if (ret > 0) { + acl_supported = 1; + acl_type = ACL_TYPE_NFS4; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_dir); + return (1); + } + if (acl_supported == 0) { + ret = pathconf(source_dir, _PC_ACL_EXTENDED); + if (ret > 0) { + acl_supported = 1; + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", + source_dir); + return (1); + } + } + if (acl_supported == 0) + return (0); + + /* + * If the file is a link we will not follow it + */ + if (S_ISLNK(fs->st_mode)) { + aclgetf = acl_get_link_np; + aclsetf = acl_set_link_np; + } else { + aclgetf = acl_get_file; + aclsetf = acl_set_file; + } + if (acl_type == ACL_TYPE_ACCESS) { + /* + * Even if there is no ACL_TYPE_DEFAULT entry here, a zero + * size ACL will be returned. So it is not safe to simply + * check the pointer to see if the default ACL is present. + */ + acl = aclgetf(source_dir, ACL_TYPE_DEFAULT); + if (acl == NULL) { + warn("failed to get default acl entries on %s", + source_dir); + return (1); + } + aclp = &acl->ats_acl; + if (aclp->acl_cnt != 0 && aclsetf(dest_dir, + ACL_TYPE_DEFAULT, acl) < 0) { + warn("failed to set default acl entries on %s", + dest_dir); + acl_free(acl); + return (1); + } + acl_free(acl); + } + acl = aclgetf(source_dir, acl_type); + if (acl == NULL) { + warn("failed to get acl entries on %s", source_dir); + return (1); + } + if (acl_is_trivial_np(acl, &trivial)) { + warn("acl_is_trivial() failed on %s", source_dir); + acl_free(acl); + return (1); + } + if (trivial) { + acl_free(acl); + return (0); + } + if (aclsetf(dest_dir, acl_type, acl) < 0) { + warn("failed to set acl entries on %s", dest_dir); + acl_free(acl); + return (1); + } + acl_free(acl); + return (0); +} +#endif diff --git a/bin/ad/ad_find.c b/bin/ad/ad_find.c new file mode 100644 index 0000000..093414a --- /dev/null +++ b/bin/ad/ad_find.c @@ -0,0 +1,176 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ad.h" + +static volatile sig_atomic_t alarmed; + +/* + SIGNAL handling: + catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. +*/ + +static void sig_handler(int signo) +{ + alarmed = 1; + return; +} + +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_handler; + sv.sa_flags = SA_RESTART; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGTERM, &sv, NULL) < 0) + ERROR("error in sigaction(SIGTERM): %s", strerror(errno)); + + if (sigaction(SIGINT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGINT): %s", strerror(errno)); + + memset(&sv, 0, sizeof(struct sigaction)); + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + + if (sigaction(SIGABRT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGABRT): %s", strerror(errno)); + + if (sigaction(SIGHUP, &sv, NULL) < 0) + ERROR("error in sigaction(SIGHUP): %s", strerror(errno)); + + if (sigaction(SIGQUIT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGQUIT): %s", strerror(errno)); +} + +static void usage_find(void) +{ + printf( + "Usage: ad find [-v VOLUME_PATH] NAME\n" + ); +} + +int ad_find(int argc, char **argv, AFPObj *obj) +{ + int c, ret; + afpvol_t vol; + const char *srchvol = getcwdpath(); + + while ((c = getopt(argc-1, &argv[1], ":v:")) != -1) { + switch(c) { + case 'v': + srchvol = strdup(optarg); + break; + case ':': + case '?': + usage_find(); + return -1; + break; + } + + } + optind++; + + if ((argc - optind) != 1) { + usage_find(); + exit(1); + } + + set_signal(); + cnid_init(); + + if (openvol(obj, srchvol, &vol) != 0) + ERROR("Cant open volume \"%s\"", srchvol); + + uint16_t flags = CONV_TOLOWER; + char namebuf[MAXPATHLEN + 1]; + if (convert_charset(vol.vol->v_volcharset, + vol.vol->v_volcharset, + vol.vol->v_maccharset, + argv[optind], + strlen(argv[optind]), + namebuf, + MAXPATHLEN, + &flags) == (size_t)-1) { + ERROR("conversion error"); + } + + int count; + char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)]; + if ((count = cnid_find(vol.vol->v_cdb, + namebuf, + strlen(namebuf), + resbuf, + sizeof(resbuf))) < 1) { + ret = 1; + } else { + ret = 0; + cnid_t cnid; + char *bufp = resbuf; + bstring sep = bfromcstr("/"); + while (count--) { + memcpy(&cnid, bufp, sizeof(cnid_t)); + bufp += sizeof(cnid_t); + + bstring path = NULL; + bstring volpath = bfromcstr(vol.vol->v_path); + BSTRING_STRIP_SLASH(volpath); + char buffer[12 + MAXPATHLEN + 1]; + int buflen = 12 + MAXPATHLEN + 1; + char *name; + cnid_t did = cnid; + struct bstrList *pathlist = bstrListCreateMin(32); + + while (did != DIRDID_ROOT) { + if ((name = cnid_resolve(vol.vol->v_cdb, &did, buffer, buflen)) == NULL) + goto next; + bstrListPush(pathlist, bfromcstr(name)); + } + bstrListPush(pathlist, volpath); + path = bjoinInv(pathlist, sep); + + printf("%s\n", cfrombstr(path)); + + next: + bstrListDestroy(pathlist); + bdestroy(path); + } + bdestroy(sep); + } + + closevol(&vol); + + return ret; +} diff --git a/bin/ad/ad_ls.c b/bin/ad/ad_ls.c new file mode 100644 index 0000000..b5947e1 --- /dev/null +++ b/bin/ad/ad_ls.c @@ -0,0 +1,687 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "ad.h" + +#define ADv2_DIRNAME ".AppleDouble" + +#define DIR_DOT_OR_DOTDOT(a) \ + ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0)) + +static volatile sig_atomic_t alarmed; + +/* ls options */ +static int ls_a; +static int ls_l; +static int ls_R; +static int ls_d; +static int ls_u; + +/* Used for pretty printing */ +static int first = 1; +static int recursion; + +static char *netatalk_dirs[] = { + ADv2_DIRNAME, + ".AppleDB", + ".AppleDesktop", + NULL +}; + +static char *labels[] = { + "---", + "gry", + "gre", + "vio", + "blu", + "yel", + "red", + "ora" +}; + +/* + SIGNAL handling: + catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. +*/ + +static void sig_handler(int signo) +{ + alarmed = 1; + return; +} + +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_handler; + sv.sa_flags = SA_RESTART; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGTERM, &sv, NULL) < 0) + ERROR("error in sigaction(SIGTERM): %s", strerror(errno)); + + if (sigaction(SIGINT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGINT): %s", strerror(errno)); + + memset(&sv, 0, sizeof(struct sigaction)); + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + + if (sigaction(SIGABRT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGABRT): %s", strerror(errno)); + + if (sigaction(SIGHUP, &sv, NULL) < 0) + ERROR("error in sigaction(SIGHUP): %s", strerror(errno)); + + if (sigaction(SIGQUIT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGQUIT): %s", strerror(errno)); +} + +/* + Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" + Returns pointer to name or NULL. +*/ +static const char *check_netatalk_dirs(const char *name) +{ + int c; + + for (c=0; netatalk_dirs[c]; c++) { + if ((strcmp(name, netatalk_dirs[c])) == 0) + return netatalk_dirs[c]; + } + return NULL; +} + + +static void usage_ls(void) +{ + printf( + "Usage: ad ls [-dRl[u]] [file|dir, ...]\n\n" + " -l Long Output [-u: unix info]:\n" + " \n\n" + " FinderFlags (valid for (f)ile and/or (d)irectory):\n" + " d = On Desktop (f/d)\n" + " e = Hidden extension (f/d)\n" + " m = Shared (can run multiple times) (f)\n" + " n = No INIT resources (f)\n" + " i = Inited (f/d)\n" + " c = Custom icon (f/d)\n" + " t = Stationery (f)\n" + " s = Name locked (f/d)\n" + " b = Bundle (f/d)\n" + " v = Invisible (f/d)\n" + " a = Alias file (f/d)\n\n" + " AFPAttributes:\n" + " y = System (f/d)\n" + " w = No write (f)\n" + " p = Needs backup (f/d)\n" + " r = No rename (f/d)\n" + " l = No delete (f/d)\n" + " o = No copy (f)\n\n" + " Note: any letter appearing in uppercase means the flag is set\n" + " but it's a directory for which the flag is not allowed.\n" + ); +} + +static void print_numlinks(const struct stat *statp) +{ + printf("%5ld", (long)statp->st_nlink); +} + +static void print_owner(const struct stat *statp) +{ + struct passwd *pwd = getpwuid(statp->st_uid); + + if (pwd == NULL) + printf(" %-8ld", (long)statp->st_uid); + else + printf(" %-8s", pwd->pw_name); +} + +static void print_group(const struct stat *statp) +{ + struct group *grp = getgrgid(statp->st_gid); + + if (grp == NULL) + printf(" %-8ld", (long)statp->st_gid); + else + printf(" %-8s", grp->gr_name); +} + +static void print_size(const struct stat *statp) +{ + switch (statp->st_mode & S_IFMT) { + case S_IFCHR: + case S_IFBLK: + printf("%4u,%4u", (unsigned)(statp->st_rdev >> 8), + (unsigned)(statp->st_rdev & 0xFF)); + break; + default: + printf("%9lu", (unsigned long)statp->st_size); + } +} + +static void print_date(const struct stat *statp) +{ + time_t now; + double diff; + char buf[100], *fmt; + + if (time(&now) == -1) { + printf(" ????????????"); + return; + } + diff = difftime(now, statp->st_mtime); + if (diff < 0 || diff > 60 * 60 * 24 * 182.5) + fmt = "%b %e %Y"; + else + fmt = "%b %e %H:%M"; + strftime(buf, sizeof(buf), fmt, localtime(&statp->st_mtime)); + printf(" %s", buf); +} + +static void print_flags(char *path, afpvol_t *vol, const struct stat *st) +{ + int adflags = 0; + struct adouble ad; + char *FinderInfo; + uint16_t FinderFlags; + uint16_t AFPattributes; + char type[5] = "----"; + char creator[5] = "----"; + int i; + uint32_t cnid; + + if (S_ISDIR(st->st_mode)) + adflags = ADFLAGS_DIR; + + if (vol->vol == NULL || vol->vol->v_path == NULL) + return; + + ad_init(&ad, vol->vol); + + if ( ad_metadata(path, adflags, &ad) < 0 ) + return; + + FinderInfo = ad_entry(&ad, ADEID_FINDERI); + + memcpy(&FinderFlags, FinderInfo + 8, 2); + FinderFlags = ntohs(FinderFlags); + + memcpy(type, FinderInfo, 4); + memcpy(creator, FinderInfo + 4, 4); + + ad_getattr(&ad, &AFPattributes); + AFPattributes = ntohs(AFPattributes); + + /* + Finder flags. Lowercase means valid, uppercase means invalid because + object is a dir and flag is only valid for files. + */ + putchar(' '); + if (FinderFlags & FINDERINFO_ISONDESK) + putchar('d'); + else + putchar('-'); + + if (FinderFlags & FINDERINFO_HIDEEXT) + putchar('e'); + else + putchar('-'); + + if (FinderFlags & FINDERINFO_ISHARED) { + if (adflags & ADFLAGS_DIR) + putchar('M'); + else + putchar('m'); + } else + putchar('-'); + + if (FinderFlags & FINDERINFO_HASNOINITS) { + if (adflags & ADFLAGS_DIR) + putchar('N'); + else + putchar('n'); + } else + putchar('-'); + + if (FinderFlags & FINDERINFO_HASBEENINITED) + putchar('i'); + else + putchar('-'); + + if (FinderFlags & FINDERINFO_HASCUSTOMICON) + putchar('c'); + else + putchar('-'); + + if (FinderFlags & FINDERINFO_ISSTATIONNERY) { + if (adflags & ADFLAGS_DIR) + putchar('T'); + else + putchar('t'); + } else + putchar('-'); + + if (FinderFlags & FINDERINFO_NAMELOCKED) + putchar('s'); + else + putchar('-'); + + if (FinderFlags & FINDERINFO_HASBUNDLE) + putchar('b'); + else + putchar('-'); + + if (FinderFlags & FINDERINFO_INVISIBLE) + putchar('v'); + else + putchar('-'); + + if (FinderFlags & FINDERINFO_ISALIAS) + putchar('a'); + else + putchar('-'); + + putchar(' '); + + /* AFP attributes */ + if (AFPattributes & ATTRBIT_SYSTEM) + putchar('y'); + else + putchar('-'); + + if (AFPattributes & ATTRBIT_NOWRITE) { + if (adflags & ADFLAGS_DIR) + putchar('W'); + else + putchar('w'); + } else + putchar('-'); + + if (AFPattributes & ATTRBIT_BACKUP) + putchar('p'); + else + putchar('-'); + + if (AFPattributes & ATTRBIT_NORENAME) + putchar('r'); + else + putchar('-'); + + if (AFPattributes & ATTRBIT_NODELETE) + putchar('l'); + else + putchar('-'); + + if (AFPattributes & ATTRBIT_NOCOPY) { + if (adflags & ADFLAGS_DIR) + putchar('O'); + else + putchar('o'); + } else + putchar('-'); + + /* Color */ + printf(" %s ", labels[(FinderFlags & FINDERINFO_COLOR) >> 1]); + + /* Type & Creator */ + for(i=0; i<4; i++) { + if (isalnum(type[i])) + putchar(type[i]); + else + putchar('-'); + } + putchar(' '); + for(i=0; i<4; i++) { + if (isalnum(creator[i])) + putchar(creator[i]); + else + putchar('-'); + } + putchar(' '); + + /* CNID */ + cnid = ad_forcegetid(&ad); + if (cnid) + printf(" %10u ", ntohl(cnid)); + else + printf(" !ADVOL_CACHE "); + + ad_close(&ad, ADFLAGS_HF); +} + +#define TYPE(b) ((st->st_mode & (S_IFMT)) == (b)) +#define MODE(b) ((st->st_mode & (b)) == (b)) + +static void print_mode(const struct stat *st) +{ + if (TYPE(S_IFBLK)) + putchar('b'); + else if (TYPE(S_IFCHR)) + putchar('c'); + else if (TYPE(S_IFDIR)) + putchar('d'); + else if (TYPE(S_IFIFO)) + putchar('p'); + else if (TYPE(S_IFREG)) + putchar('-'); + else if (TYPE(S_IFLNK)) + putchar('l'); + else if (TYPE(S_IFSOCK)) + putchar('s'); + else + putchar('?'); + putchar(MODE(S_IRUSR) ? 'r' : '-'); + putchar(MODE(S_IWUSR) ? 'w' : '-'); + if (MODE(S_ISUID)) { + if (MODE(S_IXUSR)) + putchar('s'); + else + putchar('S'); + } + else if (MODE(S_IXUSR)) + putchar('x'); + else + putchar('-'); + putchar(MODE(S_IRGRP) ? 'r' : '-'); + putchar(MODE(S_IWGRP) ? 'w' : '-'); + if (MODE(S_ISGID)) { + if (MODE(S_IXGRP)) + putchar('s'); + else + putchar('S'); + } + else if (MODE(S_IXGRP)) + putchar('x'); + else + putchar('-'); + putchar(MODE(S_IROTH) ? 'r' : '-'); + putchar(MODE(S_IWOTH) ? 'w' : '-'); + if (MODE(S_IFDIR) && MODE(S_ISVTX)) { + if (MODE(S_IXOTH)) + putchar('t'); + else + putchar('T'); + } + else if (MODE(S_IXOTH)) + putchar('x'); + else + putchar('-'); +} +#undef TYPE +#undef MODE + +static int ad_print(char *path, const struct stat *st, afpvol_t *vol) +{ + if ( ! ls_l) { + printf("%s ", path); + if (ls_d) + printf("\n"); + return 0; + } + + /* Long output */ + if (ls_u) { + print_mode(st); + print_numlinks(st); + print_owner(st); + print_group(st); + print_size(st); + print_date(st); + } + print_flags(path, vol, st); + printf(" %s\n", path); + + + return 0; +} + +static int ad_ls_r(char *path, afpvol_t *vol) +{ + int ret = 0, cwd, dirprinted = 0, dirempty; + const char *name; + char *tmp; + static char cwdpath[MAXPATHLEN+1]; + DIR *dp; + struct dirent *ep; + static struct stat st; /* Save some stack space */ + + if ( first) + cwdpath[0] = 0; + else + strcat(cwdpath, "/"); + + strcat(cwdpath, path); + first = 0; + + if (lstat(path, &st) < 0) { + perror("Can't stat"); + return -1; + } + /* If its a file or a dir with -d option call ad_print and return */ + if (S_ISREG(st.st_mode) || ls_d) + return ad_print(path, &st, vol); + + /* Its a dir: chdir to it remembering where we started */ + if ((cwd = open(".", O_RDONLY)) == -1) { + perror("Cant open ."); + return -1; + } + if (chdir(path) != 0) { + perror("Cant chdir"); + close(cwd); + return -1; + } + + if ((dp = opendir (".")) == NULL) { + perror("Couldn't opendir ."); + return -1; + } + + /* First run: print everything */ + dirempty = 1; + while ((ep = readdir (dp))) { + if (alarmed) { + ret = -1; + goto exit; + } + + /* Check if its "." or ".." */ + if (DIR_DOT_OR_DOTDOT(ep->d_name)) + continue; + + /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */ + if ((name = check_netatalk_dirs(ep->d_name)) != NULL) + continue; + + if ((ep->d_name[0] == '.') && ! ls_a) + continue; + + dirempty = 0; + + if (recursion && ! dirprinted) { + printf("\n%s:\n", cwdpath); + dirprinted = 1; + } + + if (lstat(ep->d_name, &st) < 0) { + perror("Can't stat"); + return -1; + } + + ret = ad_print(ep->d_name, &st, vol); + if (ret != 0) + goto exit; + } + + if (! ls_l && ! dirempty) + printf("\n"); + + /* Second run: recurse to dirs */ + if (ls_R) { + rewinddir(dp); + while ((ep = readdir (dp))) { + if (alarmed) { + ret = -1; + goto exit; + } + + /* Check if its "." or ".." */ + if (DIR_DOT_OR_DOTDOT(ep->d_name)) + continue; + + /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */ + if ((name = check_netatalk_dirs(ep->d_name)) != NULL) + continue; + + if ((ret = lstat(ep->d_name, &st)) < 0) { + perror("Can't stat"); + goto exit; + } + + /* Recursion */ + if (S_ISDIR(st.st_mode)) { + recursion = 1; + ret = ad_ls_r(ep->d_name, vol); + } + if (ret != 0) + goto exit; + } + } + +exit: + closedir(dp); + fchdir(cwd); + close(cwd); + + tmp = strrchr(cwdpath, '/'); + if (tmp) + *tmp = 0; + + return ret; +} + +int ad_ls(int argc, char **argv, AFPObj *obj) +{ + int c, firstarg; + afpvol_t vol; + struct stat st; + + while ((c = getopt(argc, argv, ":adlRu")) != -1) { + switch(c) { + case 'a': + ls_a = 1; + break; + case 'd': + ls_d = 1; + break; + case 'l': + ls_l = 1; + break; + case 'R': + ls_R = 1; + break; + case 'u': + ls_u = 1; + break; + case ':': + case '?': + usage_ls(); + return -1; + break; + } + + } + + set_signal(); + cnid_init(); + + if ((argc - optind) == 0) { + openvol(obj, ".", &vol); + ad_ls_r(".", &vol); + closevol(&vol); + } + else { + int havefile = 0; + + firstarg = optind; + + /* First run: only print files from argv paths */ + while(optind < argc) { + if (stat(argv[optind], &st) != 0) + goto next; + if (S_ISDIR(st.st_mode)) + goto next; + + havefile = 1; + first = 1; + recursion = 0; + + openvol(obj, argv[optind], &vol); + ad_ls_r(argv[optind], &vol); + closevol(&vol); + next: + optind++; + } + if (havefile && (! ls_l)) + printf("\n"); + + /* Second run: print dirs */ + optind = firstarg; + while(optind < argc) { + if (stat(argv[optind], &st) != 0) + goto next2; + if ( ! S_ISDIR(st.st_mode)) + goto next2; + if ((optind > firstarg) || havefile) + printf("\n%s:\n", argv[optind]); + + first = 1; + recursion = 0; + + openvol(obj, argv[optind], &vol); + ad_ls_r(argv[optind], &vol); + closevol(&vol); + + next2: + optind++; + } + + + } + + return 0; +} diff --git a/bin/ad/ad_mv.c b/bin/ad/ad_mv.c new file mode 100644 index 0000000..3fdf1ea --- /dev/null +++ b/bin/ad/ad_mv.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2010, Frank Lahm + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ad.h" + +#define STRIP_TRAILING_SLASH(p) { \ + while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \ + *--(p).p_end = 0; \ + } + +static int fflg, iflg, nflg, vflg; + +static afpvol_t svolume, dvolume; +static cnid_t did, pdid; +static volatile sig_atomic_t alarmed; + +static int copy(const char *, const char *); +static int do_move(const char *, const char *); + +/* + SIGNAL handling: + catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. +*/ + +static void sig_handler(int signo) +{ + alarmed = 1; + return; +} + +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_handler; + sv.sa_flags = SA_RESTART; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGTERM, &sv, NULL) < 0) + ERROR("error in sigaction(SIGTERM): %s", strerror(errno)); + + if (sigaction(SIGINT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGINT): %s", strerror(errno)); + + memset(&sv, 0, sizeof(struct sigaction)); + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + + if (sigaction(SIGABRT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGABRT): %s", strerror(errno)); + + if (sigaction(SIGHUP, &sv, NULL) < 0) + ERROR("error in sigaction(SIGHUP): %s", strerror(errno)); + + if (sigaction(SIGQUIT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGQUIT): %s", strerror(errno)); +} + +static void usage_mv(void) +{ + printf( + "Usage: ad mv [-f | -i | -n] [-v] source target\n" + " ad mv [-f | -i | -n] [-v] source ... directory\n\n" + "Move files around within an AFP volume, updating the CNID\n" + "database as needed. If either:\n" + " - source or destination is not an AFP volume\n" + " - source volume != destinatio volume\n" + "the files are copied and removed from the source.\n\n" + "The following options are available:\n\n" + " -f Do not prompt for confirmation before overwriting the destination\n" + " path. (The -f option overrides any previous -i or -n options.)\n" + " -i Cause mv to write a prompt to standard error before moving a file\n" + " that would overwrite an existing file. If the response from the\n" + " standard input begins with the character `y' or `Y', the move is\n" + " attempted. (The -i option overrides any previous -f or -n\n" + " options.)\n" + " -n Do not overwrite an existing file. (The -n option overrides any\n" + " previous -f or -i options.)\n" + " -v Cause mv to be verbose, showing files after they are moved.\n" + ); + exit(EXIT_FAILURE); +} + +int ad_mv(int argc, char *argv[], AFPObj *obj) +{ + size_t baselen, len; + int rval; + char *p, *endp; + struct stat sb; + int ch; + char path[MAXPATHLEN]; + + + pdid = htonl(1); + did = htonl(2); + + argc--; + argv++; + + while ((ch = getopt(argc, argv, "finv")) != -1) + switch (ch) { + case 'i': + iflg = 1; + fflg = nflg = 0; + break; + case 'f': + fflg = 1; + iflg = nflg = 0; + break; + case 'n': + nflg = 1; + fflg = iflg = 0; + break; + case 'v': + vflg = 1; + break; + default: + usage_mv(); + } + + argc -= optind; + argv += optind; + + if (argc < 2) + usage_mv(); + + set_signal(); + cnid_init(); + if (openvol(obj, argv[argc - 1], &dvolume) != 0) { + SLOG("Error opening CNID database for source \"%s\": ", argv[argc - 1]); + return 1; + } + + /* + * If the stat on the target fails or the target isn't a directory, + * try the move. More than 2 arguments is an error in this case. + */ + if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) { + if (argc > 2) + usage_mv(); + if (openvol(obj, argv[0], &svolume) != 0) { + SLOG("Error opening CNID database for destination \"%s\": ", argv[0]); + return 1; + } + rval = do_move(argv[0], argv[1]); + closevol(&svolume); + closevol(&dvolume); + return 1; + } + + /* It's a directory, move each file into it. */ + if (strlen(argv[argc - 1]) > sizeof(path) - 1) + ERROR("%s: destination pathname too long", *argv); + + (void)strcpy(path, argv[argc - 1]); + baselen = strlen(path); + endp = &path[baselen]; + if (!baselen || *(endp - 1) != '/') { + *endp++ = '/'; + ++baselen; + } + + for (rval = 0; --argc; ++argv) { + /* + * Find the last component of the source pathname. It + * may have trailing slashes. + */ + p = *argv + strlen(*argv); + while (p != *argv && p[-1] == '/') + --p; + while (p != *argv && p[-1] != '/') + --p; + + if ((baselen + (len = strlen(p))) >= PATH_MAX) { + SLOG("%s: destination pathname too long", *argv); + rval = 1; + } else { + memmove(endp, p, (size_t)len + 1); + openvol(obj, *argv, &svolume); + + if (do_move(*argv, path)) + rval = 1; + closevol(&svolume); + } + } + + closevol(&dvolume); + return rval; +} + +static int do_move(const char *from, const char *to) +{ + struct stat sb; + int ask, ch, first; + + /* + * Check access. If interactive and file exists, ask user if it + * should be replaced. Otherwise if file exists but isn't writable + * make sure the user wants to clobber it. + */ + if (!fflg && !access(to, F_OK)) { + + /* prompt only if source exist */ + if (lstat(from, &sb) == -1) { + SLOG("%s: %s", from, strerror(errno)); + return (1); + } + + ask = 0; + if (nflg) { + if (vflg) + printf("%s not overwritten\n", to); + return (0); + } else if (iflg) { + (void)fprintf(stderr, "overwrite %s? (y/n [n]) ", to); + ask = 1; + } else if (access(to, W_OK) && !stat(to, &sb)) { + (void)fprintf(stderr, "override for %s? (y/n [n]) ", to); + ask = 1; + } + if (ask) { + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + if (first != 'y' && first != 'Y') { + (void)fprintf(stderr, "not overwritten\n"); + return (0); + } + } + } + + int mustcopy = 0; + /* + * Besides the usual EXDEV we copy instead of moving if + * 1) source AFP volume != dest AFP volume + * 2) either source or dest isn't even an AFP volume + */ + if (!svolume.vol->v_path + || !dvolume.vol->v_path + || strcmp(svolume.vol->v_path, dvolume.vol->v_path) != 0) + mustcopy = 1; + + cnid_t cnid = 0; + if (!mustcopy) { + if ((cnid = cnid_for_path(svolume.vol->v_cdb, svolume.vol->v_path, from, &did)) == CNID_INVALID) { + SLOG("Couldn't resolve CNID for %s", from); + return -1; + } + + if (stat(from, &sb) != 0) { + SLOG("Cant stat %s: %s", to, strerror(errno)); + return -1; + } + + if (rename(from, to) != 0) { + if (errno == EXDEV) { + mustcopy = 1; + char path[MAXPATHLEN]; + + /* + * If the source is a symbolic link and is on another + * filesystem, it can be recreated at the destination. + */ + if (lstat(from, &sb) == -1) { + SLOG("%s: %s", from, strerror(errno)); + return (-1); + } + if (!S_ISLNK(sb.st_mode)) { + /* Can't mv(1) a mount point. */ + if (realpath(from, path) == NULL) { + SLOG("cannot resolve %s: %s: %s", from, path, strerror(errno)); + return (1); + } + } + } else { /* != EXDEV */ + SLOG("rename %s to %s: %s", from, to, strerror(errno)); + return (1); + } + } /* rename != 0*/ + + switch (sb.st_mode & S_IFMT) { + case S_IFREG: + if (dvolume.vol->vfs->vfs_renamefile(dvolume.vol, -1, from, to) != 0) { + SLOG("Error moving adouble file for %s", from); + return -1; + } + break; + case S_IFDIR: + break; + default: + SLOG("Not a file or dir: %s", from); + return -1; + } + + /* get CNID of new parent dir */ + cnid_t newpdid, newdid; + if ((newdid = cnid_for_paths_parent(&dvolume, to, &newpdid)) == CNID_INVALID) { + SLOG("Couldn't resolve CNID for parent of %s", to); + return -1; + } + + if (stat(to, &sb) != 0) { + SLOG("Cant stat %s: %s", to, strerror(errno)); + return 1; + } + + char *p = strdup(to); + char *name = basename(p); + if (cnid_update(dvolume.vol->v_cdb, cnid, &sb, newdid, name, strlen(name)) != 0) { + SLOG("Cant update CNID for: %s", to); + return 1; + } + free(p); + + struct adouble ad; + ad_init(&ad, dvolume.vol); + if (ad_open(&ad, to, S_ISDIR(sb.st_mode) ? (ADFLAGS_DIR | ADFLAGS_HF | ADFLAGS_RDWR) : ADFLAGS_HF | ADFLAGS_RDWR) != 0) { + SLOG("Error opening adouble for: %s", to); + return 1; + } + ad_setid(&ad, sb.st_dev, sb.st_ino, cnid, newdid, dvolume.db_stamp); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + + if (vflg) + printf("%s -> %s\n", from, to); + return (0); + } + + if (mustcopy) + return copy(from, to); + + /* If we get here it's an error */ + return -1; +} + +static int copy(const char *from, const char *to) +{ + struct stat sb; + int pid, status; + + if (lstat(to, &sb) == 0) { + /* Destination path exists. */ + if (S_ISDIR(sb.st_mode)) { + if (rmdir(to) != 0) { + SLOG("rmdir %s: %s", to, strerror(errno)); + return (1); + } + } else { + if (unlink(to) != 0) { + SLOG("unlink %s: %s", to, strerror(errno)); + return (1); + } + } + } else if (errno != ENOENT) { + SLOG("%s: %s", to, strerror(errno)); + return (1); + } + + /* Copy source to destination. */ + if (!(pid = fork())) { + execl(_PATH_AD, "ad", "cp", vflg ? "-Rpv" : "-Rp", from, to, (char *)NULL); + _exit(1); + } + while ((waitpid(pid, &status, 0)) == -1) { + if (errno == EINTR) + continue; + SLOG("%s cp -R %s %s: waitpid: %s", _PATH_AD, from, to, strerror(errno)); + return (1); + } + if (!WIFEXITED(status)) { + SLOG("%s cp -R %s %s: did not terminate normally", _PATH_AD, from, to); + return (1); + } + switch (WEXITSTATUS(status)) { + case 0: + break; + default: + SLOG("%s cp -R %s %s: terminated with %d (non-zero) status", + _PATH_AD, from, to, WEXITSTATUS(status)); + return (1); + } + + /* Delete the source. */ + if (!(pid = fork())) { + execl(_PATH_AD, "ad", "rm", "-R", from, (char *)NULL); + _exit(1); + } + while ((waitpid(pid, &status, 0)) == -1) { + if (errno == EINTR) + continue; + SLOG("%s rm -R %s: waitpid: %s", _PATH_AD, from, strerror(errno)); + return (1); + } + if (!WIFEXITED(status)) { + SLOG("%s rm -R %s: did not terminate normally", _PATH_AD, from); + return (1); + } + switch (WEXITSTATUS(status)) { + case 0: + break; + default: + SLOG("%s rm -R %s: terminated with %d (non-zero) status", + _PATH_AD, from, WEXITSTATUS(status)); + return (1); + } + return 0; +} diff --git a/bin/ad/ad_rm.c b/bin/ad/ad_rm.c new file mode 100644 index 0000000..b32e659 --- /dev/null +++ b/bin/ad/ad_rm.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2010, Frank Lahm + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ad.h" + +#define STRIP_TRAILING_SLASH(p) { \ + while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \ + *--(p).p_end = 0; \ + } + +static afpvol_t volume; + +static cnid_t did, pdid; +static int Rflag; +static volatile sig_atomic_t alarmed; +static int badrm, rval; + +static char *netatalk_dirs[] = { + ".AppleDB", + ".AppleDesktop", + NULL +}; + +/* Forward declarations */ +static int rm(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf); + +/* + Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" + Returns pointer to name or NULL. +*/ +static const char *check_netatalk_dirs(const char *name) +{ + int c; + + for (c=0; netatalk_dirs[c]; c++) { + if ((strcmp(name, netatalk_dirs[c])) == 0) + return netatalk_dirs[c]; + } + return NULL; +} + +static void upfunc(void) +{ + did = pdid; +} + +/* + SIGNAL handling: + catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. +*/ + +static void sig_handler(int signo) +{ + alarmed = 1; + return; +} + +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_handler; + sv.sa_flags = SA_RESTART; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGTERM, &sv, NULL) < 0) + ERROR("error in sigaction(SIGTERM): %s", strerror(errno)); + + if (sigaction(SIGINT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGINT): %s", strerror(errno)); + + memset(&sv, 0, sizeof(struct sigaction)); + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + + if (sigaction(SIGABRT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGABRT): %s", strerror(errno)); + + if (sigaction(SIGHUP, &sv, NULL) < 0) + ERROR("error in sigaction(SIGHUP): %s", strerror(errno)); + + if (sigaction(SIGQUIT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGQUIT): %s", strerror(errno)); +} + +static void usage_rm(void) +{ + printf( + "Usage: ad rm [-vR] [ ...]\n\n" + "The rm utility attempts to remove the non-directory type files specified\n" + "on the command line.\n" + "If the files and directories reside on an AFP volume, the corresponding\n" + "CNIDs are deleted from the volumes database.\n\n" + "The options are as follows:\n\n" + " -R Attempt to remove the file hierarchy rooted in each file argument.\n" + " -v Be verbose when deleting files, showing them as they are removed.\n" + ); + exit(EXIT_FAILURE); +} + +int ad_rm(int argc, char *argv[], AFPObj *obj) +{ + int ch; + + pdid = htonl(1); + did = htonl(2); + + while ((ch = getopt(argc, argv, "vR")) != -1) + switch (ch) { + case 'R': + Rflag = 1; + break; + case 'v': + vflag = 1; + break; + default: + usage_rm(); + break; + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage_rm(); + + set_signal(); + cnid_init(); + + /* Set end of argument list */ + argv[argc] = NULL; + + for (int i = 0; argv[i] != NULL; i++) { + /* Load .volinfo file for source */ + openvol(obj, argv[i], &volume); + + if (nftw(argv[i], rm, upfunc, 20, FTW_DEPTH | FTW_PHYS) == -1) { + if (alarmed) { + SLOG("...break"); + } else { + SLOG("Error: %s", argv[i]); + } + closevol(&volume); + } + } + return rval; +} + +static int rm(const char *path, + const struct stat *statp, + int tflag, + struct FTW *ftw) +{ + cnid_t cnid; + + if (alarmed) + return -1; + + const char *dir = strrchr(path, '/'); + if (dir == NULL) + dir = path; + else + dir++; + if (check_netatalk_dirs(dir) != NULL) + return FTW_SKIP_SUBTREE; + + switch (statp->st_mode & S_IFMT) { + + case S_IFLNK: + if (volume.vol->v_path) { + if ((volume.vol->v_adouble == AD_VERSION2) + && (strstr(path, ".AppleDouble") != NULL)) { + /* symlink inside adouble dir */ + if (unlink(path) != 0) + badrm = rval = 1; + break; + } + + /* Get CNID of Parent and add new childir to CNID database */ + pdid = did; + if ((cnid = cnid_for_path(volume.vol->v_cdb, volume.vol->v_path, path, &did)) == CNID_INVALID) { + SLOG("Error resolving CNID for %s", path); + return -1; + } + if (cnid_delete(volume.vol->v_cdb, cnid) != 0) { + SLOG("Error removing CNID %u for %s", ntohl(cnid), path); + return -1; + } + } + + if (unlink(path) != 0) { + badrm = rval = 1; + break; + } + + break; + + case S_IFDIR: + if (!Rflag) { + SLOG("%s is a directory", path); + return FTW_SKIP_SUBTREE; + } + + if (volume.vol->v_path) { + if ((volume.vol->v_adouble == AD_VERSION2) + && (strstr(path, ".AppleDouble") != NULL)) { + /* should be adouble dir itself */ + if (rmdir(path) != 0) { + SLOG("Error removing dir \"%s\": %s", path, strerror(errno)); + badrm = rval = 1; + return -1; + } + break; + } + + /* Get CNID of Parent and add new childir to CNID database */ + if ((did = cnid_for_path(volume.vol->v_cdb, volume.vol->v_path, path, &pdid)) == CNID_INVALID) { + SLOG("Error resolving CNID for %s", path); + return -1; + } + if (cnid_delete(volume.vol->v_cdb, did) != 0) { + SLOG("Error removing CNID %u for %s", ntohl(did), path); + return -1; + } + } + + if (rmdir(path) != 0) { + SLOG("Error removing dir \"%s\": %s", path, strerror(errno)); + badrm = rval = 1; + return -1; + } + + break; + + case S_IFBLK: + case S_IFCHR: + SLOG("%s is a device file.", path); + badrm = rval = 1; + break; + + case S_IFSOCK: + SLOG("%s is a socket.", path); + badrm = rval = 1; + break; + + case S_IFIFO: + SLOG("%s is a FIFO.", path); + badrm = rval = 1; + break; + + default: + if (volume.vol->v_path) { + if ((volume.vol->v_adouble == AD_VERSION2) + && (strstr(path, ".AppleDouble") != NULL)) { + /* file in adouble dir */ + if (unlink(path) != 0) + badrm = rval = 1; + break; + } + + /* Get CNID of Parent and add new childir to CNID database */ + pdid = did; + if ((cnid = cnid_for_path(volume.vol->v_cdb, volume.vol->v_path, path, &did)) == CNID_INVALID) { + SLOG("Error resolving CNID for %s", path); + return -1; + } + if (cnid_delete(volume.vol->v_cdb, cnid) != 0) { + SLOG("Error removing CNID %u for %s", ntohl(cnid), path); + return -1; + } + + /* Ignore errors, because with -R adouble stuff is always alread gone */ + volume.vol->vfs->vfs_deletefile(volume.vol, -1, path); + } + + if (unlink(path) != 0) { + badrm = rval = 1; + break; + } + + break; + } + + if (vflag && !badrm) + (void)printf("%s\n", path); + + return 0; +} diff --git a/bin/ad/ad_set.c b/bin/ad/ad_set.c new file mode 100644 index 0000000..af82509 --- /dev/null +++ b/bin/ad/ad_set.c @@ -0,0 +1,330 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "ad.h" + +#define ADv2_DIRNAME ".AppleDouble" + +#define DIR_DOT_OR_DOTDOT(a) \ + ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0)) + +static const char *labels[] = { + "none", + "grey", + "green", + "violet", + "blue", + "yellow", + "red", + "orange", + NULL +}; + +static char *new_label; +static char *new_type; +static char *new_creator; +static char *new_flags; +static char *new_attributes; + +static void usage_set(void) +{ + printf( + "Usage: ad set [-t TYPE] [-c CREATOR] [-l label] [-f flags] [-a attributes] file|dir \n\n" + " Color Label:\n" + " none | grey | green | violet | blue | yellow | red | orange\n\n" + " FinderFlags:\n" + " d = On Desktop (f/d)\n" + " e = Hidden extension (f/d)\n" + " m = Shared (can run multiple times) (f)\n" + " n = No INIT resources (f)\n" + " i = Inited (f/d)\n" + " c = Custom icon (f/d)\n" + " t = Stationery (f)\n" + " s = Name locked (f/d)\n" + " b = Bundle (f/d)\n" + " v = Invisible (f/d)\n" + " a = Alias file (f/d)\n\n" + " AFPAttributes:\n" + " y = System (f/d)\n" + " w = No write (f)\n" + " p = Needs backup (f/d)\n" + " r = No rename (f/d)\n" + " l = No delete (f/d)\n" + " o = No copy (f)\n\n" + " Uppercase letter sets the flag, lowercase removes the flag\n" + " f = valid for files\n" + " d = valid for directories\n" + + ); +} + +static void change_type(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_type) +{ + char *FinderInfo; + + if ((FinderInfo = ad_entry(ad, ADEID_FINDERI))) + memcpy(FinderInfo, new_type, 4); +} + +static void change_creator(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_creator) +{ + char *FinderInfo; + + if ((FinderInfo = ad_entry(ad, ADEID_FINDERI))) + memcpy(FinderInfo + 4, new_creator, 4); + +} + +static void change_label(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_label) +{ + char *FinderInfo; + const char **color = &labels[0]; + uint16_t FinderFlags; + unsigned char color_count = 0; + + if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)) == NULL) + return; + + while (*color) { + if (strcasecmp(*color, new_label) == 0) { + /* get flags */ + memcpy(&FinderFlags, FinderInfo + 8, 2); + FinderFlags = ntohs(FinderFlags); + + /* change value */ + FinderFlags &= ~FINDERINFO_COLOR; + FinderFlags |= color_count << 1; + + /* copy it back */ + FinderFlags = ntohs(FinderFlags); + memcpy(FinderInfo + 8, &FinderFlags, 2); + + break; + } + color++; + color_count++; + } +} + +static void change_attributes(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_attributes) +{ + uint16_t AFPattributes; + + ad_getattr(ad, &AFPattributes); + AFPattributes = ntohs(AFPattributes); + + if (S_ISREG(st->st_mode)) { + if (strchr(new_attributes, 'W')) + AFPattributes |= ATTRBIT_NOWRITE; + if (strchr(new_attributes, 'w')) + AFPattributes &= ~ATTRBIT_NOWRITE; + + if (strchr(new_attributes, 'O')) + AFPattributes |= ATTRBIT_NOCOPY; + if (strchr(new_attributes, 'o')) + AFPattributes &= ~ATTRBIT_NOCOPY; + } + + if (strchr(new_attributes, 'Y')) + AFPattributes |= ATTRBIT_SYSTEM; + if (strchr(new_attributes, 'y')) + AFPattributes &= ~ATTRBIT_SYSTEM; + + if (strchr(new_attributes, 'P')) + AFPattributes |= ATTRBIT_BACKUP; + if (strchr(new_attributes, 'p')) + AFPattributes &= ~ATTRBIT_BACKUP; + + if (strchr(new_attributes, 'R')) + AFPattributes |= ATTRBIT_NORENAME; + if (strchr(new_attributes, 'r')) + AFPattributes &= ~ATTRBIT_NORENAME; + + if (strchr(new_attributes, 'L')) + AFPattributes |= ATTRBIT_NODELETE; + if (strchr(new_attributes, 'l')) + AFPattributes &= ~ATTRBIT_NODELETE; + + AFPattributes = ntohs(AFPattributes); + ad_setattr(ad, AFPattributes); +} + +static void change_flags(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_flags) +{ + char *FinderInfo; + uint16_t FinderFlags; + + if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)) == NULL) + return; + + memcpy(&FinderFlags, FinderInfo + 8, 2); + FinderFlags = ntohs(FinderFlags); + + if (S_ISREG(st->st_mode)) { + if (strchr(new_flags, 'M')) + FinderFlags |= FINDERINFO_ISHARED; + if (strchr(new_flags, 'm')) + FinderFlags &= ~FINDERINFO_ISHARED; + + if (strchr(new_flags, 'N')) + FinderFlags |= FINDERINFO_HASNOINITS; + if (strchr(new_flags, 'n')) + FinderFlags &= ~FINDERINFO_HASNOINITS; + + if (strchr(new_flags, 'T')) + FinderFlags |= FINDERINFO_ISSTATIONNERY; + if (strchr(new_flags, 't')) + FinderFlags &= ~FINDERINFO_ISSTATIONNERY; + } + + if (strchr(new_flags, 'D')) + FinderFlags |= FINDERINFO_ISONDESK; + if (strchr(new_flags, 'd')) + FinderFlags &= ~FINDERINFO_ISONDESK; + + if (strchr(new_flags, 'E')) + FinderFlags |= FINDERINFO_HIDEEXT; + if (strchr(new_flags, 'e')) + FinderFlags &= ~FINDERINFO_HIDEEXT; + + if (strchr(new_flags, 'I')) + FinderFlags |= FINDERINFO_HASBEENINITED; + if (strchr(new_flags, 'i')) + FinderFlags &= ~FINDERINFO_HASBEENINITED; + + if (strchr(new_flags, 'C')) + FinderFlags |= FINDERINFO_HASCUSTOMICON; + if (strchr(new_flags, 'c')) + FinderFlags &= ~FINDERINFO_HASCUSTOMICON; + + if (strchr(new_flags, 'S')) + FinderFlags |= FINDERINFO_NAMELOCKED; + if (strchr(new_flags, 's')) + FinderFlags &= ~FINDERINFO_NAMELOCKED; + + if (strchr(new_flags, 'B')) + FinderFlags |= FINDERINFO_HASBUNDLE; + if (strchr(new_flags, 'b')) + FinderFlags &= ~FINDERINFO_HASBUNDLE; + + if (strchr(new_flags, 'V')) + FinderFlags |= FINDERINFO_INVISIBLE; + if (strchr(new_flags, 'v')) + FinderFlags &= ~FINDERINFO_INVISIBLE; + + if (strchr(new_flags, 'A')) + FinderFlags |= FINDERINFO_ISALIAS; + if (strchr(new_flags, 'a')) + FinderFlags &= ~FINDERINFO_ISALIAS; + + FinderFlags = ntohs(FinderFlags); + memcpy(FinderInfo + 8, &FinderFlags, 2); +} + +int ad_set(int argc, char **argv, AFPObj *obj) +{ + int c; + afpvol_t vol; + struct stat st; + int adflags = 0; + struct adouble ad; + + while ((c = getopt(argc, argv, ":l:t:c:f:a:")) != -1) { + switch(c) { + case 'l': + new_label = strdup(optarg); + break; + case 't': + new_type = strdup(optarg); + break; + case 'c': + new_creator = strdup(optarg); + break; + case 'f': + new_flags = strdup(optarg); + break; + case 'a': + new_attributes = strdup(optarg); + break; + case ':': + case '?': + usage_set(); + return -1; + break; + } + + } + + if (argc <= optind) + exit(1); + + cnid_init(); + + openvol(obj, argv[optind], &vol); + if (vol.vol->v_path == NULL) + exit(1); + + if (stat(argv[optind], &st) != 0) { + perror("stat"); + exit(1); + } + + if (S_ISDIR(st.st_mode)) + adflags = ADFLAGS_DIR; + + ad_init(&ad, vol.vol); + + if (ad_open(&ad, argv[optind], adflags | ADFLAGS_HF | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666) < 0) + goto exit; + + if (new_label) + change_label(argv[optind], &vol, &st, &ad, new_label); + if (new_type) + change_type(argv[optind], &vol, &st, &ad, new_type); + if (new_creator) + change_creator(argv[optind], &vol, &st, &ad, new_creator); + if (new_flags) + change_flags(argv[optind], &vol, &st, &ad, new_flags); + if (new_attributes) + change_attributes(argv[optind], &vol, &st, &ad, new_attributes); + + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + +exit: + closevol(&vol); + + return 0; +} diff --git a/bin/ad/ad_util.c b/bin/ad/ad_util.c new file mode 100644 index 0000000..27f42b0 --- /dev/null +++ b/bin/ad/ad_util.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2009 Frank Lahm + * Copyright (c) 1991, 1993, 1994 + * 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. + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SOLARIS_ACLS +#include +#endif /* HAVE_SOLARIS_ACLS */ +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif + +#ifdef HAVE_POSIX_ACLS +#include +#include +#endif /* HAVE_POSIX_ACLS */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "ad.h" + +int log_verbose; /* Logging flag */ + +void _log(enum logtype lt, char *fmt, ...) +{ + int len; + static char logbuffer[1024]; + va_list args; + + if ( (lt == STD) || (log_verbose == 1)) { + va_start(args, fmt); + len = vsnprintf(logbuffer, 1023, fmt, args); + va_end(args); + logbuffer[1023] = 0; + + printf("%s\n", logbuffer); + } +} + +/*! + * Load volinfo and initialize struct vol + * + * Only opens "dbd" volumes ! + * + * @param path (r) path to evaluate + * @param vol (rw) structure to initialize + * + * @returns 0 on success, exits on error + */ +int openvol(AFPObj *obj, const char *path, afpvol_t *vol) +{ + int flags = 0; + + memset(vol, 0, sizeof(afpvol_t)); + + if ((vol->vol = getvolbypath(obj, path)) == NULL) + return -1; + + if (STRCMP(vol->vol->v_cnidscheme, != , "dbd")) + ERROR("\"%s\" isn't a \"dbd\" CNID volume!", vol->vol->v_path); + + /* Sanity checks to ensure we can touch this volume */ + if (vol->vol->v_adouble != AD_VERSION2 + && vol->vol->v_adouble != AD_VERSION_EA) + ERROR("Unsupported adouble versions: %u", vol->vol->v_adouble); + + if (vol->vol->v_vfs_ea != AFPVOL_EA_SYS) + ERROR("Unsupported Extended Attributes option: %u", vol->vol->v_vfs_ea); + + if ((vol->vol->v_flags & AFPVOL_NODEV)) + flags |= CNID_FLAG_NODEV; + + if ((vol->vol->v_cdb = cnid_open(vol->vol, + "dbd", + flags)) == NULL) + ERROR("Cant initialize CNID database connection for %s", vol->vol->v_path); + + cnid_getstamp(vol->vol->v_cdb, + vol->db_stamp, + sizeof(vol->db_stamp)); + + return 0; +} + +void closevol(afpvol_t *vol) +{ + if (vol->vol) { + if (vol->vol->v_cdb) { + cnid_close(vol->vol->v_cdb); + vol->vol->v_cdb = NULL; + } + } + memset(vol, 0, sizeof(afpvol_t)); +} + +/* + Taken form afpd/desktop.c +*/ +char *utompath(const struct vol *vol, const char *upath) +{ + static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */ + char *m; + const char *u; + uint16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX; + size_t outlen; + + if (!upath) + return NULL; + + m = mpath; + u = upath; + outlen = strlen(upath); + + if ((vol->v_casefold & AFPVOL_UTOMUPPER)) + flags |= CONV_TOUPPER; + else if ((vol->v_casefold & AFPVOL_UTOMLOWER)) + flags |= CONV_TOLOWER; + + if ((vol->v_flags & AFPVOL_EILSEQ)) { + flags |= CONV__EILSEQ; + } + + /* convert charsets */ + if ((size_t)-1 == ( outlen = convert_charset(vol->v_volcharset, + CH_UTF8_MAC, + vol->v_maccharset, + u, outlen, mpath, MAXPATHLEN, &flags)) ) { + SLOG("Conversion from %s to %s for %s failed.", + vol->v_volcodepage, vol->v_maccodepage, u); + return NULL; + } + + return(m); +} + + +/*! + * Convert dot encoding of basename _in place_ + * + * path arg can be "[/][dir/ | ...]filename". It will be converted in place + * possible encoding ".file" as ":2efile" which means the result will be + * longer then the original which means provide a big enough buffer. + * + * @param svol (r) source volume + * @param dvol (r) destinatio volume + * @param path (rw) path to convert _in place_ + * @param buflen (r) size of path buffer (max strlen == buflen -1) + * + * @returns 0 on sucess, -1 on error + */ +int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path, size_t buflen) +{ + static charset_t from = (charset_t) -1; + static char buf[MAXPATHLEN+2]; + char *bname = stripped_slashes_basename(path); + int pos = bname - path; + uint16_t flags = 0; + + if ( ! svol->vol->v_path) { + /* no source volume: escape special chars (eg ':') */ + from = dvol->vol->v_volcharset; /* src = dst charset */ + if (dvol->vol->v_adouble == AD_VERSION2) + flags |= CONV_ESCAPEHEX; + } else { + from = svol->vol->v_volcharset; + } + + int len = convert_charset(from, + dvol->vol->v_volcharset, + dvol->vol->v_maccharset, + bname, strlen(bname), + buf, MAXPATHLEN, + &flags); + if (len == -1) + return -1; + + if (strlcpy(bname, buf, MAXPATHLEN - pos) > MAXPATHLEN - pos) + return -1; + return 0; +} + +/*! + * Resolves CNID of a given paths parent directory + * + * path might be: + * (a) relative: + * "dir/subdir" with cwd: "/afp_volume/topdir" + * (b) absolute: + * "/afp_volume/dir/subdir" + * + * path MUST be pointing inside vol, this is usually the case as vol has been build from + * path using loadvolinfo and friends. + * + * @param vol (r) pointer to afpvol_t + * @param path (r) path, see above + * @param did (rw) parent CNID of returned CNID + * + * @returns CNID of path + */ +cnid_t cnid_for_paths_parent(const afpvol_t *vol, + const char *path, + cnid_t *did) +{ + EC_INIT; + + cnid_t cnid; + bstring rpath = NULL; + bstring statpath = NULL; + struct bstrList *l = NULL; + struct stat st; + + *did = htonl(1); + cnid = htonl(2); + + EC_NULL(rpath = rel_path_in_vol(path, vol->vol->v_path)); + EC_NULL(statpath = bfromcstr(vol->vol->v_path)); + + l = bsplit(rpath, '/'); + if (l->qty == 1) + /* only one path element, means parent dir cnid is volume root = 2 */ + goto EC_CLEANUP; + for (int i = 0; i < (l->qty - 1); i++) { + *did = cnid; + EC_ZERO(bconcat(statpath, l->entry[i])); + EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st), + "lstat(rpath: %s, elem: %s): %s: %s", + cfrombstr(rpath), cfrombstr(l->entry[i]), + cfrombstr(statpath), strerror(errno)); + + if ((cnid = cnid_add(vol->vol->v_cdb, + &st, + *did, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + 0)) == CNID_INVALID) { + EC_FAIL; + } + EC_ZERO(bcatcstr(statpath, "/")); + } + +EC_CLEANUP: + bdestroy(rpath); + bstrListDestroy(l); + bdestroy(statpath); + if (ret != 0) + return CNID_INVALID; + + return cnid; +} + diff --git a/bin/afppasswd/Makefile.am b/bin/afppasswd/Makefile.am new file mode 100644 index 0000000..578eac1 --- /dev/null +++ b/bin/afppasswd/Makefile.am @@ -0,0 +1,20 @@ +# Makefile.am for bin/afppasswd/ + +pkgconfdir = @PKGCONFDIR@ + +if HAVE_OPENSSL +bin_PROGRAMS = afppasswd +else +bin_PROGRAMS = +endif + +afppasswd_SOURCES = afppasswd.c +afppasswd_LDADD = $(top_builddir)/libatalk/libatalk.la @SSL_LIBS@ @MYSQL_LIBS@ + +AM_CFLAGS = @SSL_CFLAGS@ -I$(top_srcdir)/sys \ + -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" + +install-exec-hook: +if HAVE_OPENSSL + chmod u+s $(DESTDIR)$(bindir)/afppasswd +endif diff --git a/bin/afppasswd/Makefile.in b/bin/afppasswd/Makefile.in new file mode 100644 index 0000000..8a14d73 --- /dev/null +++ b/bin/afppasswd/Makefile.in @@ -0,0 +1,709 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for bin/afppasswd/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_OPENSSL_TRUE@bin_PROGRAMS = afppasswd$(EXEEXT) +subdir = bin/afppasswd +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_afppasswd_OBJECTS = afppasswd.$(OBJEXT) +afppasswd_OBJECTS = $(am_afppasswd_OBJECTS) +afppasswd_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(afppasswd_SOURCES) +DIST_SOURCES = $(afppasswd_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgconfdir = @PKGCONFDIR@ +afppasswd_SOURCES = afppasswd.c +afppasswd_LDADD = $(top_builddir)/libatalk/libatalk.la @SSL_LIBS@ @MYSQL_LIBS@ +AM_CFLAGS = @SSL_CFLAGS@ -I$(top_srcdir)/sys \ + -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/afppasswd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/afppasswd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +afppasswd$(EXEEXT): $(afppasswd_OBJECTS) $(afppasswd_DEPENDENCIES) $(EXTRA_afppasswd_DEPENDENCIES) + @rm -f afppasswd$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(afppasswd_OBJECTS) $(afppasswd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afppasswd.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-exec-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS + + +install-exec-hook: +@HAVE_OPENSSL_TRUE@ chmod u+s $(DESTDIR)$(bindir)/afppasswd + +# 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/bin/afppasswd/afppasswd.c b/bin/afppasswd/afppasswd.c new file mode 100644 index 0000000..f5778a5 --- /dev/null +++ b/bin/afppasswd/afppasswd.c @@ -0,0 +1,354 @@ +/* + * Copyright 1999 (c) Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + * format of the password file: + * name:****************:****************:******** + * password last login date failed usage count + * + * ***'s are illegal. they're just place holders for hex values. hex + * values that represent actual numbers are in network byte order. + * + * last login date is currently a 4-byte number representing seconds + * since 1970 (UTC). there's enough space to extend it to 8 bytes. + * + * the last two fields aren't currently used by the randnum uams. + * + * root syntax: afppasswd [-c] [-a] [-p path] [-f] [username] + * user syntax: afppasswd + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef USE_CRACKLIB +#include +#endif /* USE_CRACKLIB */ + +#define OPT_ISROOT (1 << 0) +#define OPT_CREATE (1 << 1) +#define OPT_FORCE (1 << 2) +#define OPT_ADDUSER (1 << 3) +#define OPT_NOCRACK (1 << 4) + +#define PASSWD_ILLEGAL '*' + +#define FORMAT ":****************:****************:********\n" +#define FORMAT_LEN 44 +#define OPTIONS "cafnu:p:" +#define UID_START 100 + +#define HEXPASSWDLEN 16 +#define PASSWDLEN 8 + +static char buf[MAXPATHLEN + 1]; + +/* if newpwd is null, convert buf from hex to binary. if newpwd isn't + * null, convert newpwd to hex and save it in buf. */ +#define unhex(x) (isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A') +static void convert_passwd(char *buf, char *newpwd, const int keyfd) +{ + uint8_t key[HEXPASSWDLEN]; + Key_schedule schedule; + unsigned int i, j; + + if (!newpwd) { + /* convert to binary */ + for (i = j = 0; i < sizeof(key); i += 2, j++) + buf[j] = (unhex(buf[i]) << 4) | unhex(buf[i + 1]); + if (j <= DES_KEY_SZ) + memset(buf + j, 0, sizeof(key) - j); + } + + if (keyfd > -1) { + lseek(keyfd, 0, SEEK_SET); + read(keyfd, key, sizeof(key)); + /* convert to binary */ + for (i = j = 0; i < sizeof(key); i += 2, j++) + key[j] = (unhex(key[i]) << 4) | unhex(key[i + 1]); + if (j <= DES_KEY_SZ) + memset(key + j, 0, sizeof(key) - j); + key_sched((C_Block *) key, schedule); + memset(key, 0, sizeof(key)); + if (newpwd) { + ecb_encrypt((C_Block *) newpwd, (C_Block *) newpwd, schedule, + DES_ENCRYPT); + } else { + /* decrypt the password */ + ecb_encrypt((C_Block *) buf, (C_Block *) buf, schedule, DES_DECRYPT); + } + memset(&schedule, 0, sizeof(schedule)); + } + + if (newpwd) { + const unsigned char hextable[] = "0123456789ABCDEF"; + + /* convert to hex */ + for (i = j = 0; i < DES_KEY_SZ; i++, j += 2) { + buf[j] = hextable[(newpwd[i] & 0xF0) >> 4]; + buf[j + 1] = hextable[newpwd[i] & 0x0F]; + } + } +} + +/* this matches the code in uam_randnum.c */ +static int update_passwd(const char *path, const char *name, int flags) +{ + char password[PASSWDLEN + 1], *p, *passwd; + FILE *fp; + off_t pos; + int keyfd = -1, err = 0; + + if ((fp = fopen(path, "r+")) == NULL) { + fprintf(stderr, "afppasswd: can't open %s\n", path); + return -1; + } + + /* open the key file if it exists */ + strcpy(buf, path); + if (strlen(path) < sizeof(buf) - 5) { + strcat(buf, ".key"); + keyfd = open(buf, O_RDONLY); + } + + pos = ftell(fp); + memset(buf, 0, sizeof(buf)); + while (fgets(buf, sizeof(buf), fp)) { + if ((p = strchr(buf, ':'))) { + /* check for a match */ + if (strlen(name) == (p - buf) && + strncmp(buf, name, p - buf) == 0) { + p++; + if (!(flags & OPT_ISROOT) && (*p == PASSWD_ILLEGAL)) { + fprintf(stderr, "Your password is disabled. Please see your administrator.\n"); + break; + } + goto found_entry; + } + } + pos = ftell(fp); + memset(buf, 0, sizeof(buf)); + } + + if (flags & OPT_ADDUSER) { + strcpy(buf, name); + strcat(buf, FORMAT); + p = strchr(buf, ':') + 1; + fwrite(buf, strlen(buf), 1, fp); + } else { + fprintf(stderr, "afppasswd: can't find %s in %s\n", name, path); + err = -1; + goto update_done; + } + +found_entry: + /* need to verify against old password */ + if ((flags & OPT_ISROOT) == 0) { + passwd = getpass("Enter OLD AFP password: "); + convert_passwd(p, NULL, keyfd); + if (strncmp(passwd, p, PASSWDLEN)) { + fprintf(stderr, "afppasswd: invalid password.\n"); + err = -1; + goto update_done; + } + } + + /* new password */ + passwd = getpass("Enter NEW AFP password: "); + memcpy(password, passwd, sizeof(password)); + password[PASSWDLEN] = '\0'; +#ifdef USE_CRACKLIB + if (!(flags & OPT_NOCRACK)) { + if (passwd = FascistCheck(password, _PATH_CRACKLIB)) { + fprintf(stderr, "Error: %s\n", passwd); + err = -1; + goto update_done; + } + } +#endif /* USE_CRACKLIB */ + + passwd = getpass("Enter NEW AFP password again: "); + if (strcmp(passwd, password) == 0) { + struct flock lock; + int fd = fileno(fp); + + convert_passwd(p, password, keyfd); + lock.l_type = F_WRLCK; + lock.l_start = pos; + lock.l_len = 1; + lock.l_whence = SEEK_SET; + fseek(fp, pos, SEEK_SET); + fcntl(fd, F_SETLKW, &lock); + fwrite(buf, p - buf + HEXPASSWDLEN, 1, fp); + lock.l_type = F_UNLCK; + fcntl(fd, F_SETLK, &lock); + printf("afppasswd: updated password.\n"); + + } else { + fprintf(stderr, "afppasswd: passwords don't match!\n"); + err = -1; + } + +update_done: + if (keyfd > -1) + close(keyfd); + fclose(fp); + return err; +} + + +/* creates a file with all the password entries */ +static int create_file(const char *path, uid_t minuid) +{ + struct passwd *pwd; + int fd, len, err = 0; + + + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0600)) < 0) { + fprintf(stderr, "afppasswd: can't create %s\n", path); + return -1; + } + + setpwent(); + while ((pwd = getpwent())) { + if (pwd->pw_uid < minuid) + continue; + /* a little paranoia */ + if (strlen(pwd->pw_name) + FORMAT_LEN > sizeof(buf) - 1) + continue; + strcpy(buf, pwd->pw_name); + strcat(buf, FORMAT); + len = strlen(buf); + if (write(fd, buf, len) != len) { + fprintf(stderr, "afppasswd: problem writing to %s: %s\n", path, + strerror(errno)); + err = -1; + break; + } + } + endpwent(); + close(fd); + + return err; +} + + +int main(int argc, char **argv) +{ + struct stat st; + int flags; + uid_t uid_min = UID_START, uid; + char *path = _PATH_AFPDPWFILE; + int i, err = 0; + + extern char *optarg; + extern int optind; + + flags = ((uid = getuid()) == 0) ? OPT_ISROOT : 0; + + if (((flags & OPT_ISROOT) == 0) && (argc > 1)) { + fprintf(stderr, "afppasswd (Netatalk %s)\n", VERSION); + fprintf(stderr, "Usage: afppasswd [-acfn] [-u minuid] [-p path] [username]\n"); + fprintf(stderr, " -a add a new user\n"); + fprintf(stderr, " -c create and initialize password file or specific user\n"); + fprintf(stderr, " -f force an action\n"); +#ifdef USE_CRACKLIB + fprintf(stderr, " -n disable cracklib checking of passwords\n"); +#endif /* USE_CRACKLIB */ + fprintf(stderr, " -u uid minimum uid to use, defaults to 100\n"); + fprintf(stderr, " -p path path to afppasswd file\n"); + return -1; + } + + while ((i = getopt(argc, argv, OPTIONS)) != EOF) { + switch (i) { + case 'c': /* create and initialize password file or specific user */ + flags |= OPT_CREATE; + break; + case 'a': /* add a new user */ + flags |= OPT_ADDUSER; + break; + case 'f': /* force an action */ + flags |= OPT_FORCE; + break; + case 'u': /* minimum uid to use. default is 100 */ + uid_min = atoi(optarg); + break; +#ifdef USE_CRACKLIB + case 'n': /* disable CRACKLIB check */ + flags |= OPT_NOCRACK; + break; +#endif /* USE_CRACKLIB */ + case 'p': /* path to afppasswd file */ + path = optarg; + break; + default: + err++; + break; + } + } + + if (err || (optind + ((flags & OPT_CREATE) ? 0 : + (flags & OPT_ISROOT)) != argc)) { +#ifdef USE_CRACKLIB + fprintf(stderr, "Usage: afppasswd [-acfn] [-u minuid] [-p path] [username]\n"); +#else /* USE_CRACKLIB */ + fprintf(stderr, "Usage: afppasswd [-acf] [-u minuid] [-p path] [username]\n"); +#endif /* USE_CRACKLIB */ + fprintf(stderr, " -a add a new user\n"); + fprintf(stderr, " -c create and initialize password file or specific user\n"); + fprintf(stderr, " -f force an action\n"); +#ifdef USE_CRACKLIB + fprintf(stderr, " -n disable cracklib checking of passwords\n"); +#endif /* USE_CRACKLIB */ + fprintf(stderr, " -u uid minimum uid to use, defaults to 100\n"); + fprintf(stderr, " -p path path to afppasswd file\n"); + return -1; + } + + i = stat(path, &st); + if (flags & OPT_CREATE) { + if ((flags & OPT_ISROOT) == 0) { + fprintf(stderr, "afppasswd: only root can create the password file.\n"); + return -1; + } + + if (!i && ((flags & OPT_FORCE) == 0)) { + fprintf(stderr, "afppasswd: password file already exists.\n"); + return -1; + } + return create_file(path, uid_min); + + } else { + struct passwd *pwd = NULL; + + if (i < 0) { + fprintf(stderr, "afppasswd: %s doesn't exist.\n", path); + return -1; + } + + /* if we're root, we need to specify the username */ + pwd = (flags & OPT_ISROOT) ? getpwnam(argv[optind]) : getpwuid(uid); + if (pwd) + return update_passwd(path, pwd->pw_name, flags); + + fprintf(stderr, "afppasswd: can't get password entry.\n"); + return -1; + } +} diff --git a/bin/cnid/Makefile.am b/bin/cnid/Makefile.am new file mode 100644 index 0000000..2ade6f5 --- /dev/null +++ b/bin/cnid/Makefile.am @@ -0,0 +1,7 @@ +# Makefile.am for bin/cnid/ + +EXTRA_DIST = cnid2_create.in + +if USE_BDB +bin_SCRIPTS = cnid2_create +endif diff --git a/bin/cnid/Makefile.in b/bin/cnid/Makefile.in new file mode 100644 index 0000000..f83c91c --- /dev/null +++ b/bin/cnid/Makefile.in @@ -0,0 +1,590 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for bin/cnid/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = bin/cnid +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/cnid2_create.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = cnid2_create +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" +SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = cnid2_create.in +@USE_BDB_TRUE@bin_SCRIPTS = cnid2_create +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/cnid/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/cnid/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +cnid2_create: $(top_builddir)/config.status $(srcdir)/cnid2_create.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binSCRIPTS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binSCRIPTS + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binSCRIPTS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-binSCRIPTS + + +# 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/bin/cnid/cnid2_create.in b/bin/cnid/cnid2_create.in new file mode 100755 index 0000000..c3e3ffd --- /dev/null +++ b/bin/cnid/cnid2_create.in @@ -0,0 +1,361 @@ +#!@PERL@ + +# +# Upgrade version 1 CNID databases to version 2 +# +# +# Copyright (C) Joerg Lenneis 2003 +# All Rights Reserved. See COPYING. +# +# + +use strict; + + +### Globals + +my $toplevel = $ARGV[0]; + +# Assume our current directory is .AppleDB in the share directory as the default. + +$toplevel = ".." unless $toplevel; + +# Main file information data structure. Each entry in did_table points +# to a list of hashes. Key is a DID and each list member is a hash +# describing a file or directory in the directory corresponding to the +# DID. n_entries is the number of items found, output_list contains +# all entries that are eventually written to the output file. + +my %did_table; +my $n_entries; +my @output_list; + +# RootInfo values in the new format + +my $ri_cnid = "00000000"; +my $ri_dev = "1122334400000000"; +my $ri_ino = "0000000000000000"; +my $ri_did = "00000000"; +my $ri_hexname = "526f6f74496e666f00"; # RootInfo\0 + + +# Current CNID found in didname.db +my $current_cnid; + +# Largest CNID from cnid.db, used if we cannot find the current CNID in didname.db +my $max_cnid; + +# Number of bogus/invalid entries found in the DB +my $errors_found; + +# Filenames + +my $didname_dump = "didname.dump"; +my $cnid_dump = "cnid.dump"; +my $cnid2_dump = "cnid2.dump"; + +### Subroutines + +sub skip_header($) +{ + my $handle = shift; + my $header_ok; + + while (<$handle>) { + chomp; + if ($_ eq "HEADER=END") { + $header_ok = 1; + last; + } + } + die "No valid header found, invalid input file?" unless $header_ok; +} + +sub print_eentry($$) +{ + my $reason = shift; + my $entry = shift; + + printf "??:%s %-9s%-9s%-9s%-9s%s\n", + $reason, + $entry->{cnid}, + $entry->{dev}, + $entry->{ino}, + $entry->{did}, + $entry->{name}; + + $errors_found++; +} + +sub find_current_cnid() +{ + my $key; + my $val; + my $cnid; + my $compare = " " . $ri_did . $ri_hexname; + + # get rid of "00" at the end, RootInfo in the old format does not have a trailing \0 + + $compare =~ s/00$//; + + open DIDNAME, "< $didname_dump" or die "Unable to open $didname_dump: $!"; + skip_header(*DIDNAME); + + while (1) { + $key = ; + chomp $key; + last if $key eq "DATA=END"; + $val = ; + chomp $val; + last unless defined($key) and defined($val); + if ($key eq $compare) { + # \00\00\00\00RootInfo + $val =~ s/^ //; + $cnid = $val; + last; + } + } + close DIDNAME; + return $cnid; +} + +sub verify_entry($) +{ + my $entry = shift; + + if (length($entry->{cnid}) != 8 or length($entry->{name}) == 0) { + print_eentry("fmt", $entry); + return 0; + } else { + return 1; + } +} + +sub create_did_table() +{ + my $data_ok; + my $key; + my $val; + my $len; + my $i; + my $name; + my $cmax; + + open CNID, "< $cnid_dump" or die "Unable to open $cnid_dump: $!"; + skip_header(*CNID); + + while (1) { + $key = ; + chomp $key; + $key =~ s/^ //; + if ($key eq "DATA=END") { + $data_ok = 1; + last; + } + my $val = ; + chomp $val; + $val =~ s/^ //; + + last unless defined($key) and defined($val); + + # We do not worry about converting any of the + # integer values into binary form. They are in network byte order, + # so we know how to extend them. We just treat them as hexadecimal ASCII strings. + # The file name is also stored as a proper string, since we need to + # look for it in the file system. + + my $entry; + + $entry->{cnid} = $key; + $entry->{dev} = substr($val, 0, 8); + $entry->{ino} = substr($val, 8, 8); + $entry->{did} = substr($val, 16, 8); + $entry->{hexname} = substr($val, 24); + + $len = length($entry->{hexname}) - 2; + $i = 0; + $name = ''; + while ($i < $len) { + $name .= chr(hex(substr($entry->{hexname}, $i, 2))); + $i += 2; + } + $entry->{name} = $name; + + if (verify_entry($entry)) { + push @{$did_table{$entry->{did}}}, $entry; + $n_entries++; + $cmax = $entry->{cnid} if $entry->{cnid} gt $cmax; + } + } + close CNID; + die "No valid end of data found, invalid input file?" unless $data_ok; + return $cmax; +} + +sub output_header($$$) +{ + my $handle = shift; + my $dbname = shift; + my $n = shift; + + printf $handle "VERSION=3\nformat=bytevalue\ndatabase=%s\ntype=btree\nHEADER=END\n", $dbname; +} + +sub expand_did_table($$) +{ + my $did = shift; + my $basename = shift; + my $entry; + my $name; + + foreach $entry (@{$did_table{$did}}) { + $name = $basename . "/" . $entry->{name}; + + if ( -e $name ) { + if ( -d $name ) { + $entry->{type} = "00000001"; + } else { + $entry->{type} = "00000000"; + } + } else { + + # The file/dir does not exist in the file system. This could result + # from a non-afpd rename that has not yet been picked up by afpd and is + # fixable. We need a guess at the type, though. + + if ($did_table{$entry->{cnid}} and scalar(@{$did_table{$entry->{cnid}}}) > 0) { + + # We have entries hanging off this entry in our table, + # so this must be a directory + $entry->{type} = "00000001"; + } else { + # If this is actually an empty directory that was renamed, + # the entry will be deleted by afpd on the next access, + # so this should be safe + $entry->{type} = "00000000"; + } + } + + $entry->{reached} = 1; + push @output_list, $entry; + expand_did_table($entry->{cnid}, $name); + } +} + +sub find_unreachable() +{ + my $did; + my $list; + my $entry; + + while (($did, $list) = each %did_table) { + foreach $entry (@{$list}) { + print_eentry("reach", $entry) unless $entry->{reached}; + } + } +} + +sub find_duplicates() +{ + my %seen_cnid; + my %seen_devino; + my %seen_didname; + my $cnid; + my $devino; + my $didname; + my $err; + my $entry; + + for (my $i = 0; $i < scalar(@output_list); $i++) { + $err = 0; + $entry = $output_list[$i]; + $cnid = $entry->{cnid}; + $devino = $entry->{dev} . $entry->{ino}; + $didname = $entry->{did} . $entry->{name}; + if ($seen_cnid{$cnid}) { + print_eentry("exist_cnid", $entry); + $err++; + } + if ($seen_cnid{$cnid}) { + print_eentry("dupl_cnid", $entry); + $err++; + } + if ($seen_devino{$devino}) { + print_eentry("dupl_devino", $entry); + $err++; + } + if ($seen_didname{$didname}) { + print_eentry("dupl_didname", $entry); + $err++; + } + if ($err) { + splice(@output_list, $i, 1); + } else { + $seen_cnid{$cnid} = 1; + $seen_devino{$devino} = 1; + $seen_didname{$didname} = 1; + } + } +} + + +print "Finding the current CNID from $didname_dump\n"; +$current_cnid = find_current_cnid(); +print "Reading in entries from $cnid_dump\n"; +$max_cnid = create_did_table(); +print "Found $n_entries entries\n"; + +if (not $current_cnid) { + print "Warning: could not find a valid entry for the current CNID in $didname_dump.\n"; + print "Using maximum CNID value $max_cnid from $cnid_dump instead\n"; + $current_cnid = $max_cnid; +} else { + print "Current CNID is $current_cnid\n"; +} + +print "Building directory tree according to cnid.db\n"; +expand_did_table("00000002", $toplevel); + +if ($n_entries > scalar(@output_list)) { + print "Looking for unreachable nodes in the directory tree:\n"; + find_unreachable(); +} + +print "Looking for duplicate entries\n"; +find_duplicates(); + +print "Creating $cnid2_dump\n"; +open CNID2, "> $cnid2_dump" or die "Unable to open $cnid2_dump for writing: $!"; +output_header(*CNID2, "cnid2.db", scalar(@output_list) + 1); +foreach my $entry (@output_list) { + print CNID2 " ", $entry->{cnid}, "\n"; + print CNID2 " ", $entry->{cnid}, + "00000000", $entry->{dev}, "00000000", $entry->{ino}, + $entry->{type}, + $entry->{did}, $entry->{hexname}, "\n"; +} +print CNID2 " ", $ri_cnid, "\n"; +print CNID2 " ", $ri_cnid, $ri_dev, $ri_ino, $current_cnid, $ri_did, $ri_hexname, "\n"; +print CNID2 "DATA=END\n"; + +output_header(*CNID2, "devino.db", scalar(@output_list) + 1); +foreach my $entry (@output_list) { + print CNID2 " ", "00000000", $entry->{dev}, "00000000", $entry->{ino}, "\n"; + print CNID2 " ", $entry->{cnid}, "\n"; +} +print CNID2 " ", $ri_dev, $ri_ino, "\n"; +print CNID2 " ", $ri_cnid, "\n"; +print CNID2 "DATA=END\n"; + +output_header(*CNID2, "didname.db", scalar(@output_list) + 1); +foreach my $entry (@output_list) { + print CNID2 " ", $entry->{did}, $entry->{hexname}, "\n"; + print CNID2 " ", $entry->{cnid}, "\n"; +} +print CNID2 " ", $ri_did, $ri_hexname, "\n"; +print CNID2 " ", $ri_cnid, "\n"; +print CNID2 "DATA=END\n"; + +close CNID2; + +exit 0; diff --git a/bin/megatron/Makefile.am b/bin/megatron/Makefile.am new file mode 100644 index 0000000..3032efa --- /dev/null +++ b/bin/megatron/Makefile.am @@ -0,0 +1,4 @@ +# Makefile.am for bin/megatron/ + +# EXTRADIST = asingle.c hqx.c macbin.c megatron.c nad.c updcrc.c \ +# asingle.h megatron.h hqx.h macbin.h nad.h updcrc.h diff --git a/bin/megatron/Makefile.in b/bin/megatron/Makefile.in new file mode 100644 index 0000000..faedacf --- /dev/null +++ b/bin/megatron/Makefile.in @@ -0,0 +1,519 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for bin/megatron/ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = bin/megatron +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/megatron/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/megatron/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +# EXTRADIST = asingle.c hqx.c macbin.c megatron.c nad.c updcrc.c \ +# asingle.h megatron.h hqx.h macbin.h nad.h updcrc.h + +# 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/bin/misc/Makefile.am b/bin/misc/Makefile.am new file mode 100644 index 0000000..2cbb8d0 --- /dev/null +++ b/bin/misc/Makefile.am @@ -0,0 +1,23 @@ +# Makefile.am for bin/misc + +pkgconfdir = @PKGCONFDIR@ +bin_PROGRAMS = + +noinst_PROGRAMS = netacnv logger_test fce + +netacnv_SOURCES = netacnv.c +netacnv_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ + +logger_test_SOURCES = logger_test.c +logger_test_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ + +fce_SOOURCE = fce.c +fce_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ +fce_CFLAGS = -I$(top_srcdir)/include + +bin_PROGRAMS += afpldaptest +afpldaptest_SOURCES = uuidtest.c +afpldaptest_CFLAGS = -D_PATH_CONFDIR=\"$(pkgconfdir)/\" @LDAP_CFLAGS@ +afpldaptest_LDFLAGS = @LDAP_LDFLAGS@ +afpldaptest_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ + diff --git a/bin/misc/Makefile.in b/bin/misc/Makefile.in new file mode 100644 index 0000000..4690035 --- /dev/null +++ b/bin/misc/Makefile.in @@ -0,0 +1,779 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for bin/misc + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = afpldaptest$(EXEEXT) +noinst_PROGRAMS = netacnv$(EXEEXT) logger_test$(EXEEXT) fce$(EXEEXT) +subdir = bin/misc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am_afpldaptest_OBJECTS = afpldaptest-uuidtest.$(OBJEXT) +afpldaptest_OBJECTS = $(am_afpldaptest_OBJECTS) +afpldaptest_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +afpldaptest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(afpldaptest_CFLAGS) \ + $(CFLAGS) $(afpldaptest_LDFLAGS) $(LDFLAGS) -o $@ +fce_SOURCES = fce.c +fce_OBJECTS = fce-fce.$(OBJEXT) +fce_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +fce_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(fce_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am_logger_test_OBJECTS = logger_test.$(OBJEXT) +logger_test_OBJECTS = $(am_logger_test_OBJECTS) +logger_test_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +am_netacnv_OBJECTS = netacnv.$(OBJEXT) +netacnv_OBJECTS = $(am_netacnv_OBJECTS) +netacnv_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(afpldaptest_SOURCES) fce.c $(logger_test_SOURCES) \ + $(netacnv_SOURCES) +DIST_SOURCES = $(afpldaptest_SOURCES) fce.c $(logger_test_SOURCES) \ + $(netacnv_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgconfdir = @PKGCONFDIR@ +netacnv_SOURCES = netacnv.c +netacnv_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ +logger_test_SOURCES = logger_test.c +logger_test_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ +fce_SOOURCE = fce.c +fce_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ +fce_CFLAGS = -I$(top_srcdir)/include +afpldaptest_SOURCES = uuidtest.c +afpldaptest_CFLAGS = -D_PATH_CONFDIR=\"$(pkgconfdir)/\" @LDAP_CFLAGS@ +afpldaptest_LDFLAGS = @LDAP_LDFLAGS@ +afpldaptest_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/misc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/misc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +afpldaptest$(EXEEXT): $(afpldaptest_OBJECTS) $(afpldaptest_DEPENDENCIES) $(EXTRA_afpldaptest_DEPENDENCIES) + @rm -f afpldaptest$(EXEEXT) + $(AM_V_CCLD)$(afpldaptest_LINK) $(afpldaptest_OBJECTS) $(afpldaptest_LDADD) $(LIBS) +fce$(EXEEXT): $(fce_OBJECTS) $(fce_DEPENDENCIES) $(EXTRA_fce_DEPENDENCIES) + @rm -f fce$(EXEEXT) + $(AM_V_CCLD)$(fce_LINK) $(fce_OBJECTS) $(fce_LDADD) $(LIBS) +logger_test$(EXEEXT): $(logger_test_OBJECTS) $(logger_test_DEPENDENCIES) $(EXTRA_logger_test_DEPENDENCIES) + @rm -f logger_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(logger_test_OBJECTS) $(logger_test_LDADD) $(LIBS) +netacnv$(EXEEXT): $(netacnv_OBJECTS) $(netacnv_DEPENDENCIES) $(EXTRA_netacnv_DEPENDENCIES) + @rm -f netacnv$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(netacnv_OBJECTS) $(netacnv_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpldaptest-uuidtest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fce-fce.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netacnv.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +afpldaptest-uuidtest.o: uuidtest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpldaptest_CFLAGS) $(CFLAGS) -MT afpldaptest-uuidtest.o -MD -MP -MF $(DEPDIR)/afpldaptest-uuidtest.Tpo -c -o afpldaptest-uuidtest.o `test -f 'uuidtest.c' || echo '$(srcdir)/'`uuidtest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpldaptest-uuidtest.Tpo $(DEPDIR)/afpldaptest-uuidtest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uuidtest.c' object='afpldaptest-uuidtest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpldaptest_CFLAGS) $(CFLAGS) -c -o afpldaptest-uuidtest.o `test -f 'uuidtest.c' || echo '$(srcdir)/'`uuidtest.c + +afpldaptest-uuidtest.obj: uuidtest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpldaptest_CFLAGS) $(CFLAGS) -MT afpldaptest-uuidtest.obj -MD -MP -MF $(DEPDIR)/afpldaptest-uuidtest.Tpo -c -o afpldaptest-uuidtest.obj `if test -f 'uuidtest.c'; then $(CYGPATH_W) 'uuidtest.c'; else $(CYGPATH_W) '$(srcdir)/uuidtest.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpldaptest-uuidtest.Tpo $(DEPDIR)/afpldaptest-uuidtest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uuidtest.c' object='afpldaptest-uuidtest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpldaptest_CFLAGS) $(CFLAGS) -c -o afpldaptest-uuidtest.obj `if test -f 'uuidtest.c'; then $(CYGPATH_W) 'uuidtest.c'; else $(CYGPATH_W) '$(srcdir)/uuidtest.c'; fi` + +fce-fce.o: fce.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fce_CFLAGS) $(CFLAGS) -MT fce-fce.o -MD -MP -MF $(DEPDIR)/fce-fce.Tpo -c -o fce-fce.o `test -f 'fce.c' || echo '$(srcdir)/'`fce.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fce-fce.Tpo $(DEPDIR)/fce-fce.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fce.c' object='fce-fce.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fce_CFLAGS) $(CFLAGS) -c -o fce-fce.o `test -f 'fce.c' || echo '$(srcdir)/'`fce.c + +fce-fce.obj: fce.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fce_CFLAGS) $(CFLAGS) -MT fce-fce.obj -MD -MP -MF $(DEPDIR)/fce-fce.Tpo -c -o fce-fce.obj `if test -f 'fce.c'; then $(CYGPATH_W) 'fce.c'; else $(CYGPATH_W) '$(srcdir)/fce.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fce-fce.Tpo $(DEPDIR)/fce-fce.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fce.c' object='fce-fce.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fce_CFLAGS) $(CFLAGS) -c -o fce-fce.obj `if test -f 'fce.c'; then $(CYGPATH_W) 'fce.c'; else $(CYGPATH_W) '$(srcdir)/fce.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS + + +# 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/bin/misc/fce.c b/bin/misc/fce.c new file mode 100644 index 0000000..cd767e9 --- /dev/null +++ b/bin/misc/fce.c @@ -0,0 +1,202 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MAXBUFLEN 1024 + +static char *fce_ev_names[] = { + "", + "FCE_FILE_MODIFY", + "FCE_FILE_DELETE", + "FCE_DIR_DELETE", + "FCE_FILE_CREATE", + "FCE_DIR_CREATE", + "FCE_FILE_MOVE", + "FCE_DIR_MOVE", + "FCE_LOGIN", + "FCE_LOGOUT" +}; + +static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet) +{ + unsigned char *p = buf; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + + memcpy(&packet->fcep_magic[0], p, sizeof(packet->fcep_magic)); + p += sizeof(packet->fcep_magic); + + packet->fcep_version = *p++; + + if (packet->fcep_version > 1) + packet->fcep_options = *p++; + + packet->fcep_event = *p++; + + if (packet->fcep_version > 1) + /* padding */ + p++; + + if (packet->fcep_version > 1) + /* reserved */ + p += 8; + + memcpy(&packet->fcep_event_id, p, sizeof(packet->fcep_event_id)); + p += sizeof(packet->fcep_event_id); + packet->fcep_event_id = ntohl(packet->fcep_event_id); + + if (packet->fcep_options & FCE_EV_INFO_PID) { + memcpy(&packet->fcep_pid, p, sizeof(packet->fcep_pid)); + packet->fcep_pid = hton64(packet->fcep_pid); + p += sizeof(packet->fcep_pid); + } + + if (packet->fcep_options & FCE_EV_INFO_USER) { + memcpy(&packet->fcep_userlen, p, sizeof(packet->fcep_userlen)); + packet->fcep_userlen = ntohs(packet->fcep_userlen); + p += sizeof(packet->fcep_userlen); + + memcpy(&packet->fcep_user[0], p, packet->fcep_userlen); + packet->fcep_user[packet->fcep_userlen] = 0; /* 0 terminate strings */ + p += packet->fcep_userlen; + } + + /* path */ + memcpy(&packet->fcep_pathlen1, p, sizeof(packet->fcep_pathlen1)); + p += sizeof(packet->fcep_pathlen1); + packet->fcep_pathlen1 = ntohs(packet->fcep_pathlen1); + + memcpy(&packet->fcep_path1[0], p, packet->fcep_pathlen1); + packet->fcep_path1[packet->fcep_pathlen1] = 0; /* 0 terminate strings */ + p += packet->fcep_pathlen1; + + if (packet->fcep_options & FCE_EV_INFO_SRCPATH) { + memcpy(&packet->fcep_pathlen2, p, sizeof(packet->fcep_pathlen2)); + p += sizeof(packet->fcep_pathlen2); + packet->fcep_pathlen2 = ntohs(packet->fcep_pathlen2); + memcpy(&packet->fcep_path2[0], p, packet->fcep_pathlen2); + packet->fcep_path2[packet->fcep_pathlen2] = 0; /* 0 terminate strings */ + p += packet->fcep_pathlen2; + } + + return 0; +} + +int main(int argc, char **argv) +{ + int sockfd, rv, c; + struct addrinfo hints, *servinfo, *p; + int numbytes; + struct sockaddr_storage their_addr; + char buf[MAXBUFLEN]; + socklen_t addr_len; + char s[INET6_ADDRSTRLEN]; + char *host = "localhost"; + + while ((c = getopt(argc, argv, "h:")) != -1) { + switch(c) { + case 'h': + host = strdup(optarg); + break; + } + } + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4 + hints.ai_socktype = SOCK_DGRAM; + + if ((rv = getaddrinfo(host, FCE_DEFAULT_PORT_STRING, &hints, &servinfo)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + return 1; + } + + // loop through all the results and bind to the first we can + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + perror("listener: socket"); + continue; + } + + if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + close(sockfd); + perror("listener: bind"); + continue; + } + + break; + } + + if (p == NULL) { + fprintf(stderr, "listener: failed to bind socket\n"); + return 2; + } + + freeaddrinfo(servinfo); + + printf("listener: waiting to recvfrom...\n"); + + addr_len = sizeof their_addr; + + struct fce_packet packet; + while (1) { + if ((numbytes = recvfrom(sockfd, + buf, + MAXBUFLEN - 1, + 0, + (struct sockaddr *)&their_addr, + &addr_len)) == -1) { + perror("recvfrom"); + exit(1); + } + + unpack_fce_packet((unsigned char *)buf, &packet); + + if (memcmp(packet.fcep_magic, FCE_PACKET_MAGIC, sizeof(packet.fcep_magic)) == 0) { + + switch (packet.fcep_event) { + case FCE_CONN_START: + printf("FCE Start\n"); + break; + + case FCE_CONN_BROKEN: + printf("Broken FCE connection\n"); + break; + + default: + printf("ID: %" PRIu32 ", Event: %s", packet.fcep_event_id, fce_ev_names[packet.fcep_event]); + if (packet.fcep_options & FCE_EV_INFO_PID) + printf(", pid: %" PRId64, packet.fcep_pid); + if (packet.fcep_options & FCE_EV_INFO_USER) + printf(", user: %s", packet.fcep_user); + + if (packet.fcep_options & FCE_EV_INFO_SRCPATH) + printf(", source: %s", packet.fcep_path2); + + printf(", Path: %s\n", packet.fcep_path1); + break; + } + } + } + + close(sockfd); + return 0; +} diff --git a/bin/misc/logger_test.c b/bin/misc/logger_test.c new file mode 100644 index 0000000..cf93211 --- /dev/null +++ b/bin/misc/logger_test.c @@ -0,0 +1,112 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + set_processname("logger_Test"); +#if 0 + LOG(log_severe, logtype_logger, "Logging Test starting: this should only log to syslog"); + + /* syslog testing */ + LOG(log_severe, logtype_logger, "Disabling syslog logging."); + unsetuplog("Default"); + LOG(log_error, logtype_default, "This shouldn't log to syslog: LOG(log_error, logtype_default)."); + LOG(log_error, logtype_logger, "This shouldn't log to syslog: LOG(log_error, logtype_logger)."); + setuplog("Default LOG_INFO"); + LOG(log_info, logtype_logger, "Set syslog logging to 'log_info', so this should log again. LOG(log_info, logtype_logger)."); + LOG(log_error, logtype_logger, "This should log to syslog: LOG(log_error, logtype_logger)."); + LOG(log_error, logtype_default, "This should log to syslog. LOG(log_error, logtype_default)."); + LOG(log_debug, logtype_logger, "This shouldn't log to syslog. LOG(log_debug, logtype_logger)."); + LOG(log_debug, logtype_default, "This shouldn't log to syslog. LOG(log_debug, logtype_default)."); + LOG(log_severe, logtype_logger, "Disabling syslog logging."); + unsetuplog("Default"); +#endif + /* filelog testing */ + + setuplog("DSI:maxdebug", "test.log"); + LOG(log_info, logtype_dsi, "This should log."); + LOG(log_error, logtype_default, "This should not log."); + + setuplog("Default:debug", "test.log"); + LOG(log_debug, logtype_default, "This should log."); + LOG(log_maxdebug, logtype_default, "This should not log."); + + LOG(log_maxdebug, logtype_dsi, "This should still log."); + + /* flooding prevention check */ + LOG(log_debug, logtype_default, "Flooding 3x"); + for (int i = 0; i < 3; i++) { + LOG(log_debug, logtype_default, "Flooding..."); + } + /* wipe the array */ + LOG(log_debug, logtype_default, "1"); LOG(log_debug, logtype_default, "2"); LOG(log_debug, logtype_default, "3"); + + LOG(log_debug, logtype_default, "-============"); + LOG(log_debug, logtype_default, "Flooding 5x"); + for (int i = 0; i < 5; i++) { + LOG(log_debug, logtype_default, "Flooding..."); + } + LOG(log_debug, logtype_default, "1"); LOG(log_debug, logtype_default, "2"); LOG(log_debug, logtype_default, "3"); + + LOG(log_debug, logtype_default, "o============"); + LOG(log_debug, logtype_default, "Flooding 2005x"); + for (int i = 0; i < 2005; i++) { + LOG(log_debug, logtype_default, "Flooding..."); + } + LOG(log_debug, logtype_default, "1"); LOG(log_debug, logtype_default, "2"); LOG(log_debug, logtype_default, "3"); + + LOG(log_debug, logtype_default, "0============"); + LOG(log_debug, logtype_default, "Flooding 11x1"); + for (int i = 0; i < 11; i++) { + LOG(log_error, logtype_default, "flooding 11x1 1"); + } + + LOG(log_debug, logtype_default, "1============"); + LOG(log_debug, logtype_default, "Flooding 11x2"); + for (int i = 0; i < 11; i++) { + LOG(log_error, logtype_default, "flooding 11x2 1"); + LOG(log_error, logtype_default, "flooding 11x2 2"); + } + + LOG(log_debug, logtype_default, "2============"); + LOG(log_debug, logtype_default, "Flooding 11x3"); + for (int i = 0; i < 11; i++) { + LOG(log_error, logtype_default, "flooding 11x3 1"); + LOG(log_error, logtype_default, "flooding 11x3 2"); + LOG(log_error, logtype_default, "flooding 11x3 3"); + } + + LOG(log_debug, logtype_default, "3============"); + LOG(log_debug, logtype_default, "Flooding 11x4"); + for (int i = 0; i < 11; i++) { + LOG(log_error, logtype_default, "flooding 11x4 1"); + LOG(log_error, logtype_default, "flooding 11x4 2"); + LOG(log_error, logtype_default, "flooding 11x4 3"); + LOG(log_error, logtype_default, "flooding 11x4 4"); + } + + + return 0; +} + + diff --git a/bin/misc/netacnv.c b/bin/misc/netacnv.c new file mode 100644 index 0000000..70c822d --- /dev/null +++ b/bin/misc/netacnv.c @@ -0,0 +1,105 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include + +#define MACCHARSET "MAC_ROMAN" + +#define flag(x) {x, #x} + +struct flag_map { + int flag; + const char *flagname; +}; + +struct flag_map flag_map[] = { + flag(CONV_ESCAPEHEX), + flag(CONV_UNESCAPEHEX), + flag(CONV_ESCAPEDOTS), + flag(CONV_IGNORE), + flag(CONV_FORCE), + flag(CONV__EILSEQ), + flag(CONV_TOUPPER), + flag(CONV_TOLOWER), + flag(CONV_PRECOMPOSE), + flag(CONV_DECOMPOSE) +}; + +char buffer[MAXPATHLEN +2]; + +int main(int argc, char **argv) +{ + int opt; + uint16_t flags = 0; + char *string, *macName = MACCHARSET; + char *f = NULL, *t = NULL; + charset_t from, to, mac; + + while ((opt = getopt(argc, argv, "m:o:f:t:")) != -1) { + switch(opt) { + case 'm': + macName = strdup(optarg); + break; + case 'o': + for (int i = 0; i < sizeof(flag_map)/sizeof(struct flag_map) - 1; i++) + if ((strcmp(flag_map[i].flagname, optarg)) == 0) + flags |= flag_map[i].flag; + break; + case 'f': + f = strdup(optarg); + break; + case 't': + t = strdup(optarg); + break; + } + } + + if ((optind + 1) != argc) { + printf("Usage: test [-o [...]] [-f ] [-t ] [-m legacy Mac charset] \n"); + printf("Defaults: -f: UTF8-MAC, -t: UTF8, -m MAC_ROMAN\n"); + printf("Available conversion options:\n"); + for (int i = 0; i < (sizeof(flag_map)/sizeof(struct flag_map) - 1); i++) { + printf("%s\n", flag_map[i].flagname); + } + return 1; + } + string = argv[optind]; + + set_charset_name(CH_UNIX, "UTF8"); + set_charset_name(CH_MAC, macName); + + if ( (charset_t) -1 == (from = add_charset(f ? f : "UTF8-MAC")) ) { + fprintf( stderr, "Setting codepage %s as from codepage failed\n", f ? f : "UTF8-MAC"); + return (-1); + } + + if ( (charset_t) -1 == (to = add_charset(t ? t : "UTF8")) ) { + fprintf( stderr, "Setting codepage %s as to codepage failed\n", t ? t : "UTF8"); + return (-1); + } + + if ( (charset_t) -1 == (mac = add_charset(macName)) ) { + fprintf( stderr, "Setting codepage %s as Mac codepage failed\n", MACCHARSET); + return (-1); + } + + + if ((size_t)-1 == (convert_charset(from, to, mac, + string, strlen(string), + buffer, MAXPATHLEN, + &flags)) ) { + perror("Conversion error"); + return 1; + } + + printf("from: %s\nto: %s\n", string, buffer); + + return 0; +} diff --git a/bin/misc/uuidtest.c b/bin/misc/uuidtest.c new file mode 100644 index 0000000..d254892 --- /dev/null +++ b/bin/misc/uuidtest.c @@ -0,0 +1,155 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_LDAP +#define LDAP_DEPRECATED 1 +#include +#endif + +#include +#include +#include +#include + +#define STRNCMP(a, R, b, l) (strncmp(a,b,l) R 0) + +static void usage() +{ + printf("Usage: afpldaptest -u | -g | -i \n"); +} + +static void parse_ldapconf() +{ + static int inited = 0; + dictionary *iniconfig; + + if (! inited) { +#ifdef HAVE_LDAP + /* Parse afp.conf */ + printf("Start parsing afp.conf\n"); + iniconfig = atalk_iniparser_load(_PATH_CONFDIR "afp.conf"); + acl_ldap_readconfig(iniconfig); + printf("Finished parsing afp.conf\n"); + if (ldap_config_valid) { + if (ldap_auth_method == LDAP_AUTH_NONE) + printf("afp.conf is ok. Using anonymous bind.\n"); + else if (ldap_auth_method == LDAP_AUTH_SIMPLE) + printf("afp.conf is ok. Using simple bind.\n"); + else { + ldap_config_valid = 0; + printf("afp.conf wants SASL which is not yet supported.\n"); + exit(EXIT_FAILURE); + } + } else { + printf("afp.conf is not ok, not using LDAP. Only local UUID testing available.\n"); + } +#else + printf("Built without LDAP support, only local UUID testing available.\n"); +#endif + inited = 1; + } +} + +int main( int argc, char **argv) +{ + int ret, c; + int verbose = 0; + atalk_uuid_t uuid; + int logsetup = 0; + uuidtype_t type; + char *name = NULL; + + while ((c = getopt(argc, argv, ":vu:g:i:")) != -1) { + switch(c) { + + case 'v': + if (! verbose) { + verbose = 1; + setuplog("default:maxdebug", "/dev/tty"); + logsetup = 1; + } + break; + + case 'u': + if (! logsetup) + setuplog("default:info", "/dev/tty"); + parse_ldapconf(); + printf("Searching user: %s\n", optarg); + ret = getuuidfromname( optarg, UUID_USER, uuid); + if (ret == 0) { + printf("User: %s ==> UUID: %s\n", optarg, uuid_bin2string(uuid)); + } else { + printf("User %s not found.\n", optarg); + } + break; + + case 'g': + if (! logsetup) + setuplog("default:info", "/dev/tty"); + parse_ldapconf(); + printf("Searching group: %s\n", optarg); + ret = getuuidfromname( optarg, UUID_GROUP, uuid); + if (ret == 0) { + printf("Group: %s ==> UUID: %s\n", optarg, uuid_bin2string(uuid)); + } else { + printf("Group %s not found.\n", optarg); + } + break; + + case 'i': + if (! logsetup) + setuplog("default:info", "/dev/tty"); + parse_ldapconf(); + printf("Searching uuid: %s\n", optarg); + uuid_string2bin(optarg, uuid); + ret = getnamefromuuid( uuid, &name, &type); + if (ret == 0) { + switch (type) { + case UUID_USER: + printf("UUID: %s ==> User: %s\n", optarg, name); + break; + case UUID_GROUP: + printf("UUID: %s ==> Group: %s\n", optarg, name); + break; + default: + printf("???: %s\n", optarg); + break; + } + free(name); + } else { + printf("UUID: %s not found.\n", optarg); + } + break; + + case ':': + case '?': + case 'h': + usage(); + exit(EXIT_FAILURE); + } + } + + return 0; +} + diff --git a/compile b/compile new file mode 100755 index 0000000..718dc6d --- /dev/null +++ b/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..872b96a --- /dev/null +++ b/config.guess @@ -0,0 +1,1537 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-09-25' + +# This file 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, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..d83fca6 --- /dev/null +++ b/config.h.in @@ -0,0 +1,761 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define if the admin group should be enabled */ +#undef ADMIN_GRP + +/* Define if AFS should be used */ +#undef AFS + +/* Does extattr API work */ +#undef BROKEN_EXTATTR + +/* BSD compatiblity macro */ +#undef BSD4_4 + +/* Define if CNID Concurrent BDB backend should be compiled. */ +#undef CNID_BACKEND_CDB + +/* Define if CNID Database Daemon backend should be compiled. */ +#undef CNID_BACKEND_DBD + +/* Define if CNID LAST scheme backend should be compiled. */ +#undef CNID_BACKEND_LAST + +/* whether the MySQL CNID module is available */ +#undef CNID_BACKEND_MYSQL + +/* Define if CNID TDB scheme backend should be compiled. */ +#undef CNID_BACKEND_TDB + +/* Path to dbus-daemon */ +#undef DBUS_DAEMON_PATH + +/* Required BDB version, major */ +#undef DB_MAJOR_REQ + +/* Required BDB version, minor */ +#undef DB_MINOR_REQ + +/* Required BDB version, patch */ +#undef DB_PATCH_REQ + +/* Define if verbose debugging information should be included */ +#undef DEBUG + +/* Define if you want to disable SIGALRM timers and DSI tickles */ +#undef DEBUGGING + +/* Default CNID scheme to be used */ +#undef DEFAULT_CNID_SCHEME + +/* Define if shell check should be disabled */ +#undef DISABLE_SHELLCHECK + +/* BSD compatibility macro */ +#undef DLSYM_PREPEND_UNDERSCORE + +/* Available Extended Attributes modules */ +#undef EA_MODULES + +/* Define if you want compatibily with the FHS */ +#undef FHS_COMPATIBILITY + +/* Define if OS is FreeBSD */ +#undef FREEBSD + +/* Whether ACLs support is available */ +#undef HAVE_ACLS + +/* Whether acl_from_mode() is available */ +#undef HAVE_ACL_FROM_MODE + +/* Whether acl_get_perm_np() is available */ +#undef HAVE_ACL_GET_PERM_NP + +/* Define to 1 if you have the header file. */ +#undef HAVE_ACL_LIBACL_H + +/* Define to 1 if you have the `add_proplist_entry' function. */ +#undef HAVE_ADD_PROPLIST_ENTRY + +/* Define to 1 if you have the `asprintf' function. */ +#undef HAVE_ASPRINTF + +/* whether at funcs are available */ +#undef HAVE_ATFUNCS + +/* Define to 1 if you have the `attropen' function. */ +#undef HAVE_ATTROPEN + +/* Define to 1 if you have the `attr_get' function. */ +#undef HAVE_ATTR_GET + +/* Define to 1 if you have the `attr_getf' function. */ +#undef HAVE_ATTR_GETF + +/* Define to 1 if you have the `attr_list' function. */ +#undef HAVE_ATTR_LIST + +/* Define to 1 if you have the `attr_listf' function. */ +#undef HAVE_ATTR_LISTF + +/* Define to 1 if you have the `attr_remove' function. */ +#undef HAVE_ATTR_REMOVE + +/* Define to 1 if you have the `attr_removef' function. */ +#undef HAVE_ATTR_REMOVEF + +/* Define to 1 if you have the `attr_set' function. */ +#undef HAVE_ATTR_SET + +/* Define to 1 if you have the `attr_setf' function. */ +#undef HAVE_ATTR_SETF + +/* Define to 1 if you have the header file. */ +#undef HAVE_ATTR_XATTR_H + +/* Use Avahi/DNS-SD registration */ +#undef HAVE_AVAHI + +/* Uses Avahis threaded poll implementation */ +#undef HAVE_AVAHI_THREADED_POLL + +/* Define to 1 if you have the `backtrace_symbols' function. */ +#undef HAVE_BACKTRACE_SYMBOLS + +/* Define if dbtob is broken */ +#undef HAVE_BROKEN_DBTOB + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRYPT_H + +/* Define if support for dbus-glib was found */ +#undef HAVE_DBUS_GLIB + +/* Define to 1 if you have the declaration of `cygwin_conv_path', and to 0 if + you don't. */ +#undef HAVE_DECL_CYGWIN_CONV_PATH + +/* Define to 1 if you have the `delproplist' function. */ +#undef HAVE_DELPROPLIST + +/* Define to 1 if you have the `dirfd' function. */ +#undef HAVE_DIRFD + +/* Define to 1 if you have the `dlclose' function. */ +#undef HAVE_DLCLOSE + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define to 1 if you have the `dlerror' function. */ +#undef HAVE_DLERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `dlopen' function. */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the `dlsym' function. */ +#undef HAVE_DLSYM + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* extattr API has full fledged fds for EAs */ +#undef HAVE_EAFD + +/* Define to 1 if you have the `extattr_delete_fd' function. */ +#undef HAVE_EXTATTR_DELETE_FD + +/* Define to 1 if you have the `extattr_delete_file' function. */ +#undef HAVE_EXTATTR_DELETE_FILE + +/* Define to 1 if you have the `extattr_delete_link' function. */ +#undef HAVE_EXTATTR_DELETE_LINK + +/* Define to 1 if you have the `extattr_get_fd' function. */ +#undef HAVE_EXTATTR_GET_FD + +/* Define to 1 if you have the `extattr_get_file' function. */ +#undef HAVE_EXTATTR_GET_FILE + +/* Define to 1 if you have the `extattr_get_link' function. */ +#undef HAVE_EXTATTR_GET_LINK + +/* Define to 1 if you have the `extattr_list_fd' function. */ +#undef HAVE_EXTATTR_LIST_FD + +/* Define to 1 if you have the `extattr_list_file' function. */ +#undef HAVE_EXTATTR_LIST_FILE + +/* Define to 1 if you have the `extattr_list_link' function. */ +#undef HAVE_EXTATTR_LIST_LINK + +/* Define to 1 if you have the `extattr_set_fd' function. */ +#undef HAVE_EXTATTR_SET_FD + +/* Define to 1 if you have the `extattr_set_file' function. */ +#undef HAVE_EXTATTR_SET_FILE + +/* Define to 1 if you have the `extattr_set_link' function. */ +#undef HAVE_EXTATTR_SET_LINK + +/* Define to 1 if you have the `fdelproplist' function. */ +#undef HAVE_FDELPROPLIST + +/* Define to 1 if you have the `fgetea' function. */ +#undef HAVE_FGETEA + +/* Define to 1 if you have the `fgetproplist' function. */ +#undef HAVE_FGETPROPLIST + +/* Define to 1 if you have the `fgetxattr' function. */ +#undef HAVE_FGETXATTR + +/* Define to 1 if you have the `flistea' function. */ +#undef HAVE_FLISTEA + +/* Define to 1 if you have the `flistxattr' function. */ +#undef HAVE_FLISTXATTR + +/* Whether FreeBSD ZFS ACLs with libsunacl are available */ +#undef HAVE_FREEBSD_SUNACL + +/* Define to 1 if you have the `fremoveea' function. */ +#undef HAVE_FREMOVEEA + +/* Define to 1 if you have the `fremovexattr' function. */ +#undef HAVE_FREMOVEXATTR + +/* Define to 1 if you have the `fsetea' function. */ +#undef HAVE_FSETEA + +/* Define to 1 if you have the `fsetproplist' function. */ +#undef HAVE_FSETPROPLIST + +/* Define to 1 if you have the `fsetxattr' function. */ +#undef HAVE_FSETXATTR + +/* Define to 1 if the system has the type `fshare_t'. */ +#undef HAVE_FSHARE_T + +/* Define to 1 if you have the `fstatat' function. */ +#undef HAVE_FSTATAT + +/* Define to 1 if you have the `getea' function. */ +#undef HAVE_GETEA + +/* Define to 1 if you have the `getifaddrs' function. */ +#undef HAVE_GETIFADDRS + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define to 1 if you have the `getproplist' function. */ +#undef HAVE_GETPROPLIST + +/* Define to 1 if you have the `getusershell' function. */ +#undef HAVE_GETUSERSHELL + +/* Define to 1 if you have the `getxattr' function. */ +#undef HAVE_GETXATTR + +/* Define to 1 if you have the `get_proplist_entry' function. */ +#undef HAVE_GET_PROPLIST_ENTRY + +/* Whether to enable GSSAPI support */ +#undef HAVE_GSSAPI + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_GENERIC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_KRB5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_H + +/* Wheter GSS_C_NT_HOSTBASED_SERVICE is in gssapi.h */ +#undef HAVE_GSS_C_NT_HOSTBASED_SERVICE + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if Kerberos 5 is available */ +#undef HAVE_KERBEROS + +/* Define to 1 if you have the `krb5_free_error_message' function. */ +#undef HAVE_KRB5_FREE_ERROR_MESSAGE + +/* Define to 1 if you have the `krb5_free_keytab_entry_contents' function. */ +#undef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS + +/* Define to 1 if you have the `krb5_free_unparsed_name' function. */ +#undef HAVE_KRB5_FREE_UNPARSED_NAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_KRB5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_KRB5_KRB5_H + +/* Define to 1 if you have the `krb5_kt_free_entry' function. */ +#undef HAVE_KRB5_KT_FREE_ENTRY + +/* Define to 1 if you have the header file. */ +#undef HAVE_LANGINFO_H + +/* LARGEFILE support */ +#undef HAVE_LARGEFILE_SUPPORT + +/* Whether LDAP is available */ +#undef HAVE_LDAP + +/* Define to 1 if you have the `lgetea' function. */ +#undef HAVE_LGETEA + +/* Define to 1 if you have the `lgetxattr' function. */ +#undef HAVE_LGETXATTR + +/* Define to 1 if you have the `crypt' library (-lcrypt). */ +#undef HAVE_LIBCRYPT + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define to 1 if you have the `des' library (-ldes). */ +#undef HAVE_LIBDES + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define if libdlloader will be built on this platform */ +#undef HAVE_LIBDLLOADER + +/* Define if the DHX2 modules should be built with libgcrypt */ +#undef HAVE_LIBGCRYPT + +/* define if you have libquota */ +#undef HAVE_LIBQUOTA + +/* Define to 1 if you have the `sunacl' library (-lsunacl). */ +#undef HAVE_LIBSUNACL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_DQBLK_XFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_XFS_FS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_XQM_H + +/* Define to 1 if you have the `listea' function. */ +#undef HAVE_LISTEA + +/* Define to 1 if you have the `listxattr' function. */ +#undef HAVE_LISTXATTR + +/* Define to 1 if you have the `llistea' function. */ +#undef HAVE_LLISTEA + +/* Define to 1 if you have the `llistxattr' function. */ +#undef HAVE_LLISTXATTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have the `lremoveea' function. */ +#undef HAVE_LREMOVEEA + +/* Define to 1 if you have the `lremovexattr' function. */ +#undef HAVE_LREMOVEXATTR + +/* Define to 1 if you have the `lsetea' function. */ +#undef HAVE_LSETEA + +/* Define to 1 if you have the `lsetxattr' function. */ +#undef HAVE_LSETXATTR + +/* Use mDNSRespnder/DNS-SD registration */ +#undef HAVE_MDNS + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mempcpy' function. */ +#undef HAVE_MEMPCPY + +/* Define to 1 if you have the `mmap' function. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the header file. */ +#undef HAVE_MNTENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Whether NFSv4 ACLs are available */ +#undef HAVE_NFSV4_ACLS + +/* Define to 1 if you have the `openat' function. */ +#undef HAVE_OPENAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_PAM_PAM_APPL_H + +/* Whether POSIX ACLs are available */ +#undef HAVE_POSIX_ACLS + +/* Define to 1 if you have the `pread' function. */ +#undef HAVE_PREAD + +/* Define to 1 if you have the `pselect' function. */ +#undef HAVE_PSELECT + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + +/* Define to 1 if you have the `pwrite' function. */ +#undef HAVE_PWRITE + +/* Define to 1 if you have the `removeea' function. */ +#undef HAVE_REMOVEEA + +/* Define to 1 if you have the `removexattr' function. */ +#undef HAVE_REMOVEXATTR + +/* Define to 1 if you have the `renameat' function. */ +#undef HAVE_RENAMEAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_RPCSVC_RQUOTA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_RPC_PMAP_PROT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_RPC_RPC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SECURITY_PAM_APPL_H + +/* Define to 1 if you have the `sendfilev' function. */ +#undef HAVE_SENDFILEV + +/* Define to 1 if you have the `setea' function. */ +#undef HAVE_SETEA + +/* Define to 1 if you have the `setlinebuf' function. */ +#undef HAVE_SETLINEBUF + +/* Define to 1 if you have the `setproplist' function. */ +#undef HAVE_SETPROPLIST + +/* Define to 1 if you have the `setxattr' function. */ +#undef HAVE_SETXATTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_SGTTY_H + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the `sizeof_proplist_entry' function. */ +#undef HAVE_SIZEOF_PROPLIST_ENTRY + +/* Whether Solaris ACLs are available */ +#undef HAVE_SOLARIS_ACLS + +/* Define to 1 if you have the `splice' function. */ +#undef HAVE_SPLICE + +/* Define to 1 if you have the header file. */ +#undef HAVE_STATFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcat' function. */ +#undef HAVE_STRLCAT + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strnlen' function. */ +#undef HAVE_STRNLEN + +/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ +#undef HAVE_STRUCT_TM_TM_GMTOFF + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ATTRIBUTES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EXTATTR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MNTTAB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATVFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TERMIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_VFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_XATTR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if Tracker is available */ +#undef HAVE_TRACKER + +/* Whether UCS-2-INTERNAL is supported */ +#undef HAVE_UCS2INTERNAL + +/* Define to 1 if you have the header file. */ +#undef HAVE_UFS_QUOTA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `unlinkat' function. */ +#undef HAVE_UNLINKAT + +/* Whether to use native iconv */ +#undef HAVE_USABLE_ICONV + +/* Define to 1 if you have the `utime' function. */ +#undef HAVE_UTIME + +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_XFS_LIBXFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_XFS_XFS_FS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_XFS_XQM_H + +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* OS is Linux */ +#undef LINUX + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Disable assertions */ +#undef NDEBUG + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define if OS is NetBSD */ +#undef NETBSD + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Define if quota support should not compiled */ +#undef NO_QUOTA_SUPPORT + +/* Define if the gmtoff member of struct tm is not available */ +#undef NO_STRUCT_TM_GMTOFF + +/* Define if the OpenSSL DHX modules should be built */ +#undef OPENSSL_DHX + +/* errno returned by open with O_NOFOLLOW */ +#undef OPEN_NOFOLLOW_ERRNO + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* netatalk lockfile path */ +#undef PATH_NETATALK_LOCK + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Whether the realpath function allows NULL */ +#undef REALPATH_TAKES_NULL + +/* Define if the sendfile() function uses BSD semantics */ +#undef SENDFILE_FLAVOR_BSD + +/* Whether linux sendfile() API is available */ +#undef SENDFILE_FLAVOR_LINUX + +/* Solaris sendfile() */ +#undef SENDFILE_FLAVOR_SOLARIS + +/* Define if shadow passwords should be used */ +#undef SHADOWPW + +/* Solaris compatibility macro */ +#undef SOLARIS + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if TCP wrappers should be used */ +#undef TCPWRAP + +/* Path to Tracker */ +#undef TRACKER_PREFIX + +/* Define if the DHX UAM modules should be compiled */ +#undef UAM_DHX + +/* Define if the DHX2 UAM modules should be compiled */ +#undef UAM_DHX2 + +/* Define if the PGP UAM module should be compiled */ +#undef UAM_PGP + +/* Use internal tbd */ +#undef USE_BUILTIN_TDB + +/* Define if cracklib should be used */ +#undef USE_CRACKLIB + +/* Define to enable PAM support */ +#undef USE_PAM + +/* Define to enable Zeroconf support */ +#undef USE_ZEROCONF + +/* Version number of package */ +#undef VERSION + +/* dtrace probes */ +#undef WITH_DTRACE + +/* Whether recvfile should be used */ +#undef WITH_RECVFILE + +/* Whether sendfile() should be used */ +#undef WITH_SENDFILE + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* xattr functions have additional options */ +#undef XATTR_ADD_OPT + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* AT file source */ +#undef _ATFILE_SOURCE + +/* _FILE_OFFSET_BITS (for LARGEFILE support) */ +#undef _FILE_OFFSET_BITS + +/* Whether to use GNU libc extensions */ +#undef _GNU_SOURCE + +/* Compatibility macro */ +#undef _ISOC9X_SOURCE + +/* _LARGE_FILES (for LARGEFILE support) */ +#undef _LARGE_FILES + +/* path to cracklib dictionary */ +#undef _PATH_CRACKLIB + +/* Solaris compilation environment */ +#undef _XOPEN_SOURCE + +/* Solaris compilation environment */ +#undef __EXTENSIONS__ + +/* Solaris compatibility macro */ +#undef __svr4__ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..89b1286 --- /dev/null +++ b/config.sub @@ -0,0 +1,1789 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-10-10' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config/Makefile.am b/config/Makefile.am new file mode 100644 index 0000000..c98a2ab --- /dev/null +++ b/config/Makefile.am @@ -0,0 +1,73 @@ +## Makefile.am for config/ + +SUBDIRS = pam +SUFFIXES = .tmpl . + +TMPLFILES = afp.conf.tmpl dbus-session.conf.tmpl +GENFILES = afp.conf dbus-session.conf +CLEANFILES = $(GENFILES) +EXTRA_DIST = $(TMPLFILES) extmap.conf netatalk-dbus.conf + +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ + +CONFFILES = extmap.conf + +pkgconfdir = @PKGCONFDIR@ + +if HAVE_DBUS_GLIB +dbusservicedir = $(DBUS_SYS_DIR) +dbusservice_DATA = netatalk-dbus.conf +endif + +# +# rule to parse template files +# + +.tmpl: + sed -e s@:UAMS_PATH:@${UAMS_PATH}@ \ + -e s@:ETCDIR:@${pkgconfdir}@ \ + -e s@:COMPILED_BACKENDS:@"$(compiled_backends)"@ \ + -e s@:DEFAULT_CNID_SCHEME:@$(DEFAULT_CNID_SCHEME)@ \ + -e s@:LOCALSTATEDIR:@"$(localstatedir)"@ \ + <$< >$@ + +# +# install configuration files +# + +install-data-local: install-config-files + mkdir -pm 0755 $(DESTDIR)$(localstatedir)/netatalk/ + mkdir -pm 0755 $(DESTDIR)$(localstatedir)/netatalk/CNID/ + $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(localstatedir)/netatalk/ + $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(localstatedir)/netatalk/CNID/ + +uninstall-local: + @for f in $(CONFFILES) $(GENFILES); do \ + echo rm -f $(DESTDIR)$(pkgconfdir)/$$f; \ + rm -f $(DESTDIR)$(pkgconfdir)/$$f; \ + done + rm -f $(DESTDIR)$(pkgconfdir)/dbus-session.conf + rm -f $(DESTDIR)$(localstatedir)/netatalk/README + rm -f $(DESTDIR)$(localstatedir)/netatalk/CNID/README +if USE_DEBIAN_SYSV + rm -f $(DESTDIR)/etc/default/netatalk +endif + +install-config-files: $(CONFFILES) $(GENFILES) + $(mkinstalldirs) $(DESTDIR)$(pkgconfdir) + @for f in $(CONFFILES) ; do \ + if test "x$(OVERWRITE_CONFIG)" = "xyes" -o ! -f $(DESTDIR)$(pkgconfdir)/$$f; then \ + echo "$(INSTALL_DATA) $$f $(DESTDIR)$(pkgconfdir)"; \ + $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(pkgconfdir); \ + else \ + echo "not overwriting $$f"; \ + fi; \ + done + @for f in $(GENFILES); do \ + if test "x$(OVERWRITE_CONFIG)" = "xyes" -o ! -f $(DESTDIR)$(pkgconfdir)/$$f; then \ + echo "$(INSTALL_DATA) $$f $(DESTDIR)$(pkgconfdir)"; \ + $(INSTALL_DATA) $$f $(DESTDIR)$(pkgconfdir); \ + else \ + echo "not overwriting $$f"; \ + fi; \ + done diff --git a/config/Makefile.in b/config/Makefile.in new file mode 100644 index 0000000..7dcf76a --- /dev/null +++ b/config/Makefile.in @@ -0,0 +1,822 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = config +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(dbusservicedir)" +DATA = $(dbusservice_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = pam +SUFFIXES = .tmpl . +TMPLFILES = afp.conf.tmpl dbus-session.conf.tmpl +GENFILES = afp.conf dbus-session.conf +CLEANFILES = $(GENFILES) +EXTRA_DIST = $(TMPLFILES) extmap.conf netatalk-dbus.conf +CONFFILES = extmap.conf +pkgconfdir = @PKGCONFDIR@ +@HAVE_DBUS_GLIB_TRUE@dbusservicedir = $(DBUS_SYS_DIR) +@HAVE_DBUS_GLIB_TRUE@dbusservice_DATA = netatalk-dbus.conf +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .tmpl . +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign config/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign config/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dbusserviceDATA: $(dbusservice_DATA) + @$(NORMAL_INSTALL) + @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(dbusservicedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dbusservicedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbusservicedir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(dbusservicedir)" || exit $$?; \ + done + +uninstall-dbusserviceDATA: + @$(NORMAL_UNINSTALL) + @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(dbusservicedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(dbusservicedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-data-local install-dbusserviceDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dbusserviceDATA uninstall-local + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-local \ + install-dbusserviceDATA install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-dbusserviceDATA uninstall-local + + +# +# rule to parse template files +# + +.tmpl: + sed -e s@:UAMS_PATH:@${UAMS_PATH}@ \ + -e s@:ETCDIR:@${pkgconfdir}@ \ + -e s@:COMPILED_BACKENDS:@"$(compiled_backends)"@ \ + -e s@:DEFAULT_CNID_SCHEME:@$(DEFAULT_CNID_SCHEME)@ \ + -e s@:LOCALSTATEDIR:@"$(localstatedir)"@ \ + <$< >$@ + +# +# install configuration files +# + +install-data-local: install-config-files + mkdir -pm 0755 $(DESTDIR)$(localstatedir)/netatalk/ + mkdir -pm 0755 $(DESTDIR)$(localstatedir)/netatalk/CNID/ + $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(localstatedir)/netatalk/ + $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(localstatedir)/netatalk/CNID/ + +uninstall-local: + @for f in $(CONFFILES) $(GENFILES); do \ + echo rm -f $(DESTDIR)$(pkgconfdir)/$$f; \ + rm -f $(DESTDIR)$(pkgconfdir)/$$f; \ + done + rm -f $(DESTDIR)$(pkgconfdir)/dbus-session.conf + rm -f $(DESTDIR)$(localstatedir)/netatalk/README + rm -f $(DESTDIR)$(localstatedir)/netatalk/CNID/README +@USE_DEBIAN_SYSV_TRUE@ rm -f $(DESTDIR)/etc/default/netatalk + +install-config-files: $(CONFFILES) $(GENFILES) + $(mkinstalldirs) $(DESTDIR)$(pkgconfdir) + @for f in $(CONFFILES) ; do \ + if test "x$(OVERWRITE_CONFIG)" = "xyes" -o ! -f $(DESTDIR)$(pkgconfdir)/$$f; then \ + echo "$(INSTALL_DATA) $$f $(DESTDIR)$(pkgconfdir)"; \ + $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(pkgconfdir); \ + else \ + echo "not overwriting $$f"; \ + fi; \ + done + @for f in $(GENFILES); do \ + if test "x$(OVERWRITE_CONFIG)" = "xyes" -o ! -f $(DESTDIR)$(pkgconfdir)/$$f; then \ + echo "$(INSTALL_DATA) $$f $(DESTDIR)$(pkgconfdir)"; \ + $(INSTALL_DATA) $$f $(DESTDIR)$(pkgconfdir); \ + else \ + echo "not overwriting $$f"; \ + fi; \ + done + +# 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/config/README b/config/README new file mode 100644 index 0000000..f0f9ab7 --- /dev/null +++ b/config/README @@ -0,0 +1 @@ +This directory contains modifiable Netatalk configuration files and the CNID databases. \ No newline at end of file diff --git a/config/afp.conf.tmpl b/config/afp.conf.tmpl new file mode 100644 index 0000000..b2ee186 --- /dev/null +++ b/config/afp.conf.tmpl @@ -0,0 +1,12 @@ +; +; Netatalk 3.x configuration file +; + +[Global] +; Global server settings + +; [Homes] +; basedir regex = /xxxx + +; [My AFP Volume] +; path = /path/to/volume diff --git a/config/dbus-session.conf.tmpl b/config/dbus-session.conf.tmpl new file mode 100644 index 0000000..f84b923 --- /dev/null +++ b/config/dbus-session.conf.tmpl @@ -0,0 +1,45 @@ + + + + session + + + + + unix:path=:LOCALSTATEDIR:/netatalk/spotlight.ipc + + + + + + + + + + + + + + + 1000000000 + 1000000000 + 1000000000 + 120000 + 240000 + 100000 + 10000 + 100000 + 10000 + 50000 + 50000 + 50000 + + diff --git a/config/extmap.conf b/config/extmap.conf new file mode 100644 index 0000000..44ccec5 --- /dev/null +++ b/config/extmap.conf @@ -0,0 +1,308 @@ +# Netatalk file extension -> OS X type/creator mapping configuration file +# +# Delete a '#' character at the head of line to uncomment and enable a mapping +# +### Default translation: +#. "????" "????" Unix Binary Unix application/octet-stream +#. "BINA" "UNIX" Unix Binary Unix application/octet-stream +#. "TEXT" "ttxt" ASCII Text SimpleText text/plain + +#.1st "TEXT" "ttxt" Text Readme SimpleText application/text +#.669 "6669" "SNPL" 669 MOD Music PlayerPro +#.8med "STrk" "SCPL" Amiga OctaMed music SoundApp +#.8svx "8SVX" "SCPL" Amiga 8-bit sound SoundApp +#.a "TEXT" "ttxt" Assembly Source SimpleText +#.aif "AIFF" "SCPL" AIFF Sound SoundApp audio/x-aiff +#.aifc "AIFC" "SCPL" AIFF Sound Compressed SoundApp audio/x-aiff +#.aiff "AIFF" "SCPL" AIFF Sound SoundApp audio/x-aiff +#.al "ALAW" "SCPL" ALAW Sound SoundApp +#.ani "ANIi" "GKON" Animated NeoChrome GraphicConverter +#.apd "TEXT" "ALD3" Aldus Printer Description Aldus PageMaker +#.arc "mArc" "SITx" PC ARChive StuffIt Expander +#.arj "BINA" "DArj" ARJ Archive DeArj +#.arr "ARR " "GKON" Amber ARR image GraphicConverter +#.art "ART " "GKON" First Publisher GraphicConverter +#.asc "TEXT" "ttxt" ASCII Text SimpleText text/plain +#.ascii "TEXT" "ttxt" ASCII Text SimpleText text/plain +#.asf "ASF_" "Ms01" Netshow Player Netshow Server video/x-ms-asf +#.asm "TEXT" "ttxt" Assembly Source SimpleText +#.asx "ASX_" "Ms01" Netshow Player Netshow Server video/x-ms-asf +#.au "ULAW" "TVOD" Sun Sound QuickTime Player audio/basic +#.avi "VfW " "TVOD" AVI Movie QuickTime Player video/avi +#.bar "BARF" "S691" Unix BAR Archive SunTar +#.bas "TEXT" "ttxt" BASIC Source SimpleText +#.bat "TEXT" "ttxt" MS-DOS Batch File SimpleText +#.bga "BMPp" "ogle" OS/2 Bitmap PictureViewer +#.bib "TEXT" "ttxt" BibTex Bibliography SimpleText +#.bin "SIT!" "SITx" MacBinary StuffIt Expander application/macbinary +#.binary "BINA" "hDmp" Untyped Binary Data HexEdit application/octet-stream +#.bmp "BMPp" "ogle" Windows Bitmap PictureViewer +#.boo "TEXT" "ttxt" BOO encoded SimpleText +#.bst "TEXT" "ttxt" BibTex Style SimpleText +#.bw "SGI " "GKON" SGI Image GraphicConverter +#.c "TEXT" "CWIE" C Source CodeWarrior +#.cgm "CGMm" "GKON" Computer Graphics Meta GraphicConverter +#.class "Clss" "CWIE" Java Class File CodeWarrior +#.clp "CLPp" "GKON" Windows Clipboard GraphicConverter +#.cmd "TEXT" "ttxt" OS/2 Batch File SimpleText +#.com "PCFA" "SWIN" MS-DOS Executable SoftWindows +#.cp "TEXT" "CWIE" C++ Source CodeWarrior +#.cpp "TEXT" "CWIE" C++ Source CodeWarrior +#.cpt "PACT" "SITx" Compact Pro Archive StuffIt Expander +#.csv "TEXT" "XCEL" Comma Separated Vars Excel +#.ct "..CT" "GKON" Scitex-CT GraphicConverter +#.cut "Halo" "GKON" Dr Halo Image GraphicConverter +#.cvs "drw2" "DAD2" Canvas Drawing Canvas +#.dbf "COMP" "FOX+" DBase Document FoxBase+ +#.dcx "DCXx" "GKON" Some PCX Images GraphicConverter +#.dif "TEXT" "XCEL" Data Interchange Format Excel +#.diz "TEXT" "R*Ch" BBS Descriptive Text BBEdit +#.dl "DL " "AnVw" DL Animation MacAnim Viewer +#.dll "PCFL" "SWIN" Windows DLL SoftWindows +#.doc "WDBN" "MSWD" Word Document Microsoft Word application/msword +#.dot "sDBN" "MSWD" Word for Windows Template Microsoft Word +#.dvi "ODVI" "xdvi" TeX DVI Document xdvi application/x-dvi +#.dwt "TEXT" "DmWr" Dreamweaver Template Dreamweaver +#.dxf "TEXT" "SWVL" AutoCAD 3D Data Swivel Pro +#.eps "EPSF" "vgrd" Postscript LaserWriter 8 application/postscript +#.epsf "EPSF" "vgrd" Postscript LaserWriter 8 application/postscript +#.etx "TEXT" "ezVu" SEText Easy View text/x-setext +#.evy "EVYD" "ENVY" Envoy Document Envoy +#.exe "PCFA" "SWIN" MS-DOS Executable SoftWindows +#.faq "TEXT" "ttxt" ASCII Text SimpleText text/x-usenet-faq +#.fit "FITS" "GKON" Flexible Image Transport GraphicConverter image/x-fits +#.fla "SPA " "MFL2" Flash source Macromedia Flash +#.flc "FLI " "TVOD" FLIC Animation QuickTime Player +#.fli "FLI " "TVOD" FLI Animation QuickTime Player +#.fm "FMPR" "FMPR" FileMaker Pro Database FileMaker Pro +#.for "TEXT" "MPS " Fortran Source MPW Shell +#.fts "FITS" "GKON" Flexible Image Transport GraphicConverter +#.gem "GEM-" "GKON" GEM Metafile GraphicConverter +#.gif "GIFf" "ogle" GIF Picture PictureViewer image/gif +#.gl "GL " "AnVw" GL Animation MacAnim Viewer +#.grp "GRPp" "GKON" GRP Image GraphicConverter +#.gz "SIT!" "SITx" Gnu ZIP Archive StuffIt Expander application/x-gzip +#.h "TEXT" "CWIE" C Include File CodeWarrior +#.hcom "FSSD" "SCPL" SoundEdit Sound ex SOX SoundApp +#.hp "TEXT" "CWIE" C Include File CodeWarrior +#.hpgl "HPGL" "GKON" HP GL/2 GraphicConverter +#.hpp "TEXT" "CWIE" C Include File CodeWarrior +#.hqx "TEXT" "SITx" BinHex StuffIt Expander application/mac-binhex40 +#.htm "TEXT" "MOSS" HyperText Netscape Communicator text/html +#.html "TEXT" "MOSS" HyperText Netscape Communicator text/html +#.i3 "TEXT" "R*ch" Modula 3 Interface BBEdit +#.ic1 "IMAG" "GKON" Atari Image GraphicConverter +#.ic2 "IMAG" "GKON" Atari Image GraphicConverter +#.ic3 "IMAG" "GKON" Atari Image GraphicConverter +#.icn "ICO " "GKON" Windows Icon GraphicConverter +#.ico "ICO " "GKON" Windows Icon GraphicConverter +#.ief "IEF " "GKON" IEF image GraphicConverter image/ief +#.iff "ILBM" "GKON" Amiga IFF Image GraphicConverter +#.ilbm "ILBM" "GKON" Amiga ILBM Image GraphicConverter +#.image "dImg" "ddsk" Apple DiskCopy Image Disk Copy +#.img "IMGg" "GKON" GEM bit image/XIMG GraphicConverter +#.ini "TEXT" "ttxt" Windows INI File SimpleText +#.java "TEXT" "CWIE" Java Source File CodeWarrior +#.jfif "JPEG" "ogle" JFIF Image PictureViewer +#.jpe "JPEG" "ogle" JPEG Picture PictureViewer image/jpeg +#.jpeg "JPEG" "ogle" JPEG Picture PictureViewer image/jpeg +#.jpg "JPEG" "ogle" JPEG Picture PictureViewer image/jpeg +#.latex "TEXT" "OTEX" Latex OzTex application/x-latex +#.lbm "ILBM" "GKON" Amiga IFF Image GraphicConverter +#.lha "LHA " "SITx" LHArc Archive StuffIt Expander +#.lzh "LHA " "SITx" LHArc Archive StuffIt Expander +#.m1a "MPEG" "TVOD" MPEG-1 audiostream MoviePlayer audio/x-mpeg +#.m1s "MPEG" "TVOD" MPEG-1 systemstream MoviePlayer +#.m1v "M1V " "TVOD" MPEG-1 IPB videostream MoviePlayer video/mpeg +#.m2 "TEXT" "R*ch" Modula 2 Source BBEdit +#.m2v "MPG2" "MPG2" MPEG-2 IPB videostream MPEG2decoder +#.m3 "TEXT" "R*ch" Modula 3 Source BBEdit +#.mac "PICT" "ogle" PICT Picture PictureViewer image/x-pict +#.mak "TEXT" "R*ch" Makefile BBEdit +#.mcw "WDBN" "MSWD" Mac Word Document Microsoft Word +#.me "TEXT" "ttxt" Text Readme SimpleText +#.med "STrk" "SCPL" Amiga MED Sound SoundApp +#.mf "TEXT" "*MF*" Metafont Metafont +#.mid "Midi" "TVOD" MIDI Music MoviePlayer +#.midi "Midi" "TVOD" MIDI Music MoviePlayer +#.mif "TEXT" "Fram" FrameMaker MIF FrameMaker application/x-framemaker +#.mime "TEXT" "SITx" MIME Message StuffIt Expander message/rfc822 +#.ml "TEXT" "R*ch" ML Source BBEdit +#.mod "STrk" "SCPL" MOD Music SoundApp +#.mol "TEXT" "RSML" MDL Molfile RasMac +#.moov "MooV" "TVOD" QuickTime Movie MoviePlayer video/quicktime +#.mov "MooV" "TVOD" QuickTime Movie MoviePlayer video/quicktime +#.mp2 "MPEG" "TVOD" MPEG-1 audiostream MoviePlayer audio/x-mpeg +#.mp3 "MPG3" "TVOD" MPEG-3 audiostream MoviePlayer audio/x-mpeg +#.mpa "MPEG" "TVOD" MPEG-1 audiostream MoviePlayer audio/x-mpeg +#.mpe "MPEG" "TVOD" MPEG Movie of some sort MoviePlayer video/mpeg +#.mpeg "MPEG" "TVOD" MPEG Movie of some sort MoviePlayer video/mpeg +#.mpg "MPEG" "TVOD" MPEG Movie of some sort MoviePlayer video/mpeg +#.msp "MSPp" "GKON" Microsoft Paint GraphicConverter +#.mtm "MTM " "SNPL" MultiMOD Music PlayerPro +#.mw "MW2D" "MWII" MacWrite Document MacWrite II application/macwriteii +#.mwii "MW2D" "MWII" MacWrite Document MacWrite II application/macwriteii +#.neo "NeoC" "GKON" Atari NeoChrome GraphicConverter +#.nfo "TEXT" "ttxt" Info Text SimpleText application/text +#.nst "STrk" "SCPL" MOD Music SoundApp +#.obj "PCFL" "SWIN" Object (DOS/Windows) SoftWindows +#.oda "ODIF" "ODA " ODA Document MacODA XTND Translator application/oda +#.okt "OKTA" "SCPL" Oktalyser MOD Music SoundApp +#.out "BINA" "hDmp" Output File HexEdit +#.ovl "PCFL" "SWIN" Overlay (DOS/Windows) SoftWindows +#.p "TEXT" "CWIE" Pascal Source CodeWarrior +#.pac "STAD" "GKON" Atari STAD Image GraphicConverter +#.pas "TEXT" "CWIE" Pascal Source CodeWarrior +#.pbm "PPGM" "GKON" Portable Bitmap GraphicConverter image/x-portable-bitmap +#.pc1 "Dega" "GKON" Atari Degas Image GraphicConverter +#.pc2 "Dega" "GKON" Atari Degas Image GraphicConverter +#.pc3 "Dega" "GKON" Atari Degas Image GraphicConverter +#.pcs "PICS" "GKON" Animated PICTs GraphicConverter +#.pct "PICT" "ogle" PICT Picture PictureViewer image/x-pict +#.pcx "PCXx" "GKON" PC PaintBrush GraphicConverter +#.pdb "TEXT" "RSML" Brookhaven PDB file RasMac +#.pdf "PDF " "CARO" Portable Document Format Acrobat Reader application/pdf +#.pdx "TEXT" "ALD5" Printer Description PageMaker +#.pf "CSIT" "SITx" Private File StuffIt Expander +#.pgm "PPGM" "GKON" Portable Graymap GraphicConverter image/x-portable-graymap +#.pi1 "Dega" "GKON" Atari Degas Image GraphicConverter +#.pi2 "Dega" "GKON" Atari Degas Image GraphicConverter +#.pi3 "Dega" "GKON" Atari Degas Image GraphicConverter +#.pic "PICT" "ogle" PICT Picture PictureViewer image/x-pict +#.pict "PICT" "ogle" PICT Picture PictureViewer image/x-macpict +#.pit "PIT " "SITx" PackIt Archive StuffIt Expander +#.pkg "HBSF" "SITx" AppleLink Package StuffIt Expander +#.pl "TEXT" "McPL" Perl Source MacPerl +#.plt "HPGL" "GKON" HP GL/2 GraphicConverter +#.pm "PMpm" "GKON" Bitmap from xv GraphicConverter +#.pm3 "ALB3" "ALD3" PageMaker 3 Document PageMaker +#.pm4 "ALB4" "ALD4" PageMaker 4 Document PageMaker +#.pm5 "ALB5" "ALD5" PageMaker 5 Document PageMaker +#.png "PNG " "ogle" Portable Network Graphic PictureViewer +#.pntg "PNTG" "ogle" Macintosh Painting PictureViewer +#.ppd "TEXT" "ALD5" Printer Description PageMaker +#.ppm "PPGM" "GKON" Portable Pixmap GraphicConverter image/x-portable-pixmap +#.prn "TEXT" "R*ch" Printer Output File BBEdit +#.ps "TEXT" "vgrd" PostScript LaserWriter 8 application/postscript +#.psd "8BPS" "8BIM" PhotoShop Document Photoshop +#.pt4 "ALT4" "ALD4" PageMaker 4 Template PageMaker +#.pt5 "ALT5" "ALD5" PageMaker 5 Template PageMaker +#.pxr "PXR " "8BIM" Pixar Image Photoshop +#.qdv "QDVf" "GKON" QDV image GraphicConverter +#.qt "MooV" "TVOD" QuickTime Movie MoviePlayer video/quicktime +#.qxd "XDOC" "XPR3" QuarkXpress Document QuarkXpress +#.qxt "XTMP" "XPR3" QuarkXpress Template QuarkXpress +#.raw "BINA" "GKON" Raw Image GraphicConverter +#.readme "TEXT" "ttxt" Text Readme SimpleText application/text +#.rgb "SGI " "GKON" SGI Image GraphicConverter image/x-rgb +#.rgba "SGI " "GKON" SGI Image GraphicConverter image/x-rgb +#.rib "TEXT" "RINI" Renderman 3D Data Renderman +#.rif "RIFF" "GKON" RIFF Graphic GraphicConverter +#.rle "RLE " "GKON" RLE image GraphicConverter +#.rme "TEXT" "ttxt" Text Readme SimpleText +#.rpl "FRL!" "REP!" Replica Document Replica +#.rsc "rsrc" "RSED" Resource File ResEdit +#.rsrc "rsrc" "RSED" Resource File ResEdit +#.rtf "TEXT" "MSWD" Rich Text Format Microsoft Word application/rtf +#.rtx "TEXT" "R*ch" Rich Text BBEdit text/richtext +#.s3m "S3M " "SNPL" ScreamTracker 3 MOD PlayerPro +#.scc "MSX " "GKON" MSX pitcure GraphicConverter +#.scg "RIX3" "GKON" ColoRIX GraphicConverter +#.sci "RIX3" "GKON" ColoRIX GraphicConverter +#.scp "RIX3" "GKON" ColoRIX GraphicConverter +#.scr "RIX3" "GKON" ColoRIX GraphicConverter +#.scu "RIX3" "GKON" ColoRIX GraphicConverter +#.sea "APPL" "????" Self-Extracting Archive Self Extracting Archive +#.sf "IRCM" "SDHK" IRCAM Sound SoundHack +#.sgi ".SGI" "ogle" SGI Image PictureViewer +#.sha "TEXT" "UnSh" Unix Shell Archive UnShar application/x-shar +#.shar "TEXT" "UnSh" Unix Shell Archive UnShar application/x-shar +#.shp "SHPp" "GKON" Printmaster Icon Library GraphicConverter +#.sit "SIT!" "SITx" StuffIt 1.5.1 Archive StuffIt Expander application/x-stuffit +#.sithqx "TEXT" "SITx" BinHexed StuffIt Archive StuffIt Expander application/mac-binhex40 +#.six "SIXE" "GKON" SIXEL image GraphicConverter +#.slk "TEXT" "XCEL" SYLK Spreadsheet Excel +#.snd "BINA" "SCPL" Sound of various types SoundApp +#.spc "Spec" "GKON" Atari Spectrum 512 GraphicConverter +#.sr "SUNn" "GKON" Sun Raster Image GraphicConverter +#.sty "TEXT" "*TEX" TeX Style Textures +#.sun "SUNn" "GKON" Sun Raster Image GraphicConverter +#.sup "SCRN" "GKON" StartupScreen GraphicConverter +#.svx "8SVX" "SCPL" Amiga IFF Sound SoundApp +#.syk "TEXT" "XCEL" SYLK Spreadsheet Excel +#.sylk "TEXT" "XCEL" SYLK Spreadsheet Excel +#.tar "TARF" "SITx" Unix Tape ARchive StuffIt Expander application/x-tar +#.targa "TPIC" "GKON" Truevision Image GraphicConverter +#.taz "ZIVU" "SITx" Compressed Tape ARchive StuffIt Expander application/x-compress +#.tex "TEXT" "OTEX" TeX Document OzTeX application/x-tex +#.texi "TEXT" "OTEX" TeX Document OzTeX +#.texinfo "TEXT" "OTEX" TeX Document OzTeX application/x-texinfo +#.text "TEXT" "ttxt" ASCII Text SimpleText text/plain +#.tga "TPIC" "GKON" Truevision Image GraphicConverter +#.tgz "Gzip" "SITx" Gnu ZIPed Tape ARchive StuffIt Expander application/x-gzip +#.tif "TIFF" "ogle" TIFF Picture PictureViewer image/tiff +#.tiff "TIFF" "ogle" TIFF Picture PictureViewer image/tiff +#.tny "TINY" "GKON" Atari TINY Bitmap GraphicConverter +#.tsv "TEXT" "XCEL" Tab Separated Values Excel text/tab-separated-values +#.tx8 "TEXT" "ttxt" 8-bit ASCII Text SimpleText +#.txt "TEXT" "ttxt" ASCII Text SimpleText text/plain +#.ul "ULAW" "TVOD" Mu-Law Sound MoviePlayer audio/basic +#.url "AURL" "Arch" URL Bookmark Anarchie message/external-body +#.uu "TEXT" "SITx" UUEncode StuffIt Expander +#.uue "TEXT" "SITx" UUEncode StuffIt Expander +#.vff "VFFf" "GKON" DESR VFF Greyscale Image GraphicConverter +#.vga "BMPp" "ogle" OS/2 Bitmap PictureViewer +#.voc "VOC " "SCPL" VOC Sound SoundApp +#.w51 ".WP5" "WPC2" WordPerfect PC 5.1 Doc WordPerfect application/wordperfect5.1 +#.wav "WAVE" "TVOD" Windows WAV Sound MoviePlayer audio/x-wav +#.wk1 "XLBN" "XCEL" Lotus Spreadsheet r2.1 Excel +#.wks "XLBN" "XCEL" Lotus Spreadsheet r1.x Excel +#.wmf "WMF " "GKON" Windows Metafile GraphicConverter +#.wp ".WP5" "WPC2" WordPerfect PC 5.1 Doc WordPerfect application/wordperfect5.1 +#.wp4 ".WP4" "WPC2" WordPerfect PC 4.2 Doc WordPerfect +#.wp5 ".WP5" "WPC2" WordPerfect PC 5.x Doc WordPerfect application/wordperfect5.1 +#.wp6 ".WP6" "WPC2" WordPerfect PC 6.x Doc WordPerfect +#.wpg "WPGf" "GKON" WordPerfect Graphic GraphicConverter +#.wpm "WPD1" "WPC2" WordPerfect Mac WordPerfect +#.wri "WDBN" "MSWD" MS Write/Windows Microsoft Word +#.wve "BINA" "SCPL" PSION sound SoundApp +#.x10 "XWDd" "GKON" X-Windows Dump GraphicConverter image/x-xwd +#.x11 "XWDd" "GKON" X-Windows Dump GraphicConverter image/x-xwd +#.xbm "XBM " "GKON" X-Windows Bitmap GraphicConverter image/x-xbm +#.xl "XLS " "XCEL" Excel Spreadsheet Excel +#.xlc "XLC " "XCEL" Excel Chart Excel +#.xlm "XLM " "XCEL" Excel Macro Excel +#.xls "XLS " "XCEL" Excel Spreadsheet Excel +#.xlw "XLW " "XCEL" Excel Workspace Excel +#.xm "XM " "SNPL" FastTracker MOD Music PlayerPro +#.xpm "XPM " "GKON" X-Windows Pixmap GraphicConverter image/x-xpm +#.xwd "XWDd" "GKON" X-Windows Dump GraphicConverter image/x-xwd +#.Z "ZIVU" "SITx" Unix Compress Archive StuffIt Expander application/x-compress +#.zip "ZIP " "SITx" PC ZIP Archive StuffIt Expander application/zip +#.zoo "Zoo " "Booz" Zoo Archive MacBooz + +# I'd like to dedicate this as follows code to Miss.Tamaki Imazu +# +# Kazuhiko Okudaira the Nursery Teacher +# kokudaira@hotmail.com + +#.bld "BLD " "GKON" BLD GraphicConverter +#.bum ".bMp" "GKON" QuickTime Importer(QuickDraw) GraphicConverter +#.cel "CEL " "GKON" KISS CEL GraphicConverter +#.cur "CUR " "GKON" Windows Cursor GraphicConverter +#.cwj "CWSS" "cwkj" ClarisWorks Document ClarisWorks 4.0 +#.dat "TCLl" "GKON" TCL image GraphicConverter +#.hr "TR80" "GKON" TSR-80 HR GraphicConverter +#.iss "ISS " "GKON" ISS GraphicConverter +#.jif "JIFf" "GKON" JIF99a GraphicConverter +#.lwf "lwfF" "GKON" LuraWave(LWF) GraphicConverter +#.mbm "MBM " "GKON" PSION 5(MBM) GraphicConverter +#.ngg "NGGC" "GKON" Mobile Phone(Nokia)Format GraphicConverter +#.nol "NOL " "GKON" Mobile Phone(Nokia)Format GraphicConverter +#.pal "8BCT" "8BIM" Color Table GraphicConverter +#.pgc "PGCF" "GKON" PGC/PGF Atari Portfolio PCG GraphicConverter +#.pics "PICS" "GKON" PICS-PICT Sequence GraphicConverter +#.swf "SWFL" "SWF2" Flash Macromedia Flash +#.vpb "VPB " "GKON" VPB QUANTEL GraphicConverter +#.wbmp "WBMP" "GKON" WBMP GraphicConverter +#.x-face "TEXT" "GKON" X-Face GraphicConverter diff --git a/config/netatalk-dbus.conf b/config/netatalk-dbus.conf new file mode 100644 index 0000000..1646efd --- /dev/null +++ b/config/netatalk-dbus.conf @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/config/pam/Makefile.am b/config/pam/Makefile.am new file mode 100644 index 0000000..62affbd --- /dev/null +++ b/config/pam/Makefile.am @@ -0,0 +1,19 @@ +## Makefile for distrib/pam/ + +SUFFIXES = .tmpl . +EXTRA_DIST = netatalk.tmpl +noinst_SCRIPTS = netatalk +CLEANFILES = netatalk + +.tmpl: + sed -e "s,[@]PAM_DIRECTIVE[@],${PAM_DIRECTIVE},g" \ + -e "s,[@]PAM_AUTH[@],${PAM_AUTH}," \ + -e "s,[@]PAM_ACCOUNT[@],${PAM_ACCOUNT}," \ + -e "s,[@]PAM_PASSWORD[@],${PAM_PASSWORD}," \ + -e "s,[@]PAM_SESSION[@],${PAM_SESSION}," \ + <$< >$@ + +if USE_PAM +pamdir = $(PAMDIR) +pam_DATA = netatalk +endif diff --git a/config/pam/Makefile.in b/config/pam/Makefile.in new file mode 100644 index 0000000..c4ebf80 --- /dev/null +++ b/config/pam/Makefile.in @@ -0,0 +1,587 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = config/pam +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SCRIPTS = $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pamdir)" +DATA = $(pam_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUFFIXES = .tmpl . +EXTRA_DIST = netatalk.tmpl +noinst_SCRIPTS = netatalk +CLEANFILES = netatalk +@USE_PAM_TRUE@pamdir = $(PAMDIR) +@USE_PAM_TRUE@pam_DATA = netatalk +all: all-am + +.SUFFIXES: +.SUFFIXES: .tmpl . +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign config/pam/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign config/pam/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pamDATA: $(pam_DATA) + @$(NORMAL_INSTALL) + @list='$(pam_DATA)'; test -n "$(pamdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pamdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pamdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pamdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pamdir)" || exit $$?; \ + done + +uninstall-pamDATA: + @$(NORMAL_UNINSTALL) + @list='$(pam_DATA)'; test -n "$(pamdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pamdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pamdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pamDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pamDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pamDATA \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-pamDATA + + +.tmpl: + sed -e "s,[@]PAM_DIRECTIVE[@],${PAM_DIRECTIVE},g" \ + -e "s,[@]PAM_AUTH[@],${PAM_AUTH}," \ + -e "s,[@]PAM_ACCOUNT[@],${PAM_ACCOUNT}," \ + -e "s,[@]PAM_PASSWORD[@],${PAM_PASSWORD}," \ + -e "s,[@]PAM_SESSION[@],${PAM_SESSION}," \ + <$< >$@ + +# 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/config/pam/netatalk.tmpl b/config/pam/netatalk.tmpl new file mode 100644 index 0000000..1eceba3 --- /dev/null +++ b/config/pam/netatalk.tmpl @@ -0,0 +1,5 @@ +#%PAM-1.0 +auth @PAM_DIRECTIVE@ @PAM_AUTH@ +account @PAM_DIRECTIVE@ @PAM_ACCOUNT@ +password @PAM_DIRECTIVE@ @PAM_PASSWORD@ +session @PAM_DIRECTIVE@ @PAM_SESSION@ diff --git a/configure b/configure new file mode 100755 index 0000000..f112a03 --- /dev/null +++ b/configure @@ -0,0 +1,22726 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="etc/afpd/main.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +enable_option_checking=no +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +USE_SHADOWPW_FALSE +USE_SHADOWPW_TRUE +HAVE_ATFUNCS_FALSE +HAVE_ATFUNCS_TRUE +USE_BDB_FALSE +USE_BDB_TRUE +DEFAULT_HOOK_FALSE +DEFAULT_HOOK_TRUE +USE_PGP_FALSE +USE_PGP_TRUE +BUILD_PAM_FALSE +BUILD_PAM_TRUE +USE_PAM_FALSE +USE_PAM_TRUE +USE_PAM_SO_FALSE +USE_PAM_SO_TRUE +USE_RANDNUM_FALSE +USE_RANDNUM_TRUE +USE_DHX2_FALSE +USE_DHX2_TRUE +USE_DHX_FALSE +USE_DHX_TRUE +HAVE_LDAP_FALSE +HAVE_LDAP_TRUE +HAVE_ACLS_FALSE +HAVE_ACLS_TRUE +HAVE_OPENSSL_FALSE +HAVE_OPENSSL_TRUE +HAVE_LIBGCRYPT_FALSE +HAVE_LIBGCRYPT_TRUE +SOLARIS_MODULE_FALSE +SOLARIS_MODULE_TRUE +UAMS_PATH +DOCBOOK_ROOT +XSLTPROC_FLAGS +HAVE_XSLTPROC_FALSE +HAVE_XSLTPROC_TRUE +XSLTPROC +PATH_NETATALK_LOCK +HAVE_DBUS_GLIB_FALSE +HAVE_DBUS_GLIB_TRUE +DBUS_SYS_DIR +DBUS_GTHREAD_LIBS +DBUS_GTHREAD_CFLAGS +DBUS_GLIB_LIBS +DBUS_GLIB_CFLAGS +DBUS_LIBS +DBUS_CFLAGS +WITH_DTRACE_FALSE +WITH_DTRACE_TRUE +DTRACE_LIBS +atalk_cv_have_dtrace +DEVELOPER_FALSE +DEVELOPER_TRUE +HAVE_TRACKER_FALSE +HAVE_TRACKER_TRUE +TRACKER_MINER_LIBS +TRACKER_MINER_CFLAGS +TRACKER_LIBS +TRACKER_CFLAGS +PKG_CONFIG_PATH +USE_BUILTIN_TDB_FALSE +USE_BUILTIN_TDB_TRUE +TDB_LIBS +TDB_CFLAGS +USE_BUILTIN_LIBEVENT_FALSE +USE_BUILTIN_LIBEVENT_TRUE +LIBEVENT_LDFLAGS +LIBEVENT_CFLAGS +subdirs +ACL_LIBS +LDAP_LIBS +LDAP_LDFLAGS +LDAP_CFLAGS +OVERWRITE_CONFIG +KRB5_LIBS +KRB5_CFLAGS +USE_GSSAPI_FALSE +USE_GSSAPI_TRUE +GSSAPI_LDFLAGS +GSSAPI_CFLAGS +GSSAPI_LIBS +KRB5_CONFIG +CRYPT_LIBS +BDB_PATH +BDB_BIN +BDB_LIBS +BDB_CFLAGS +SSL_LIBS +SSL_CFLAGS +LIBGCRYPT_LIBS +LIBGCRYPT_CFLAGS +LIBGCRYPT_CONFIG +INIT_DIR +USE_UNDEF_FALSE +USE_UNDEF_TRUE +USE_DEBIAN_SYSTEMD_FALSE +USE_DEBIAN_SYSTEMD_TRUE +USE_SYSTEMD_FALSE +USE_SYSTEMD_TRUE +USE_DEBIAN_SYSV_FALSE +USE_DEBIAN_SYSV_TRUE +USE_GENTOO_FALSE +USE_GENTOO_TRUE +USE_SOLARIS_FALSE +USE_SOLARIS_TRUE +USE_SUSE_SYSV_FALSE +USE_SUSE_SYSV_TRUE +USE_REDHAT_SYSV_FALSE +USE_REDHAT_SYSV_TRUE +USE_NETBSD_FALSE +USE_NETBSD_TRUE +PAM_SESSION +PAM_PASSWORD +PAM_ACCOUNT +PAM_AUTH +PAM_DIRECTIVE +PAM_LIBS +PAM_CFLAGS +PAMDIR +WRAP_LIBS +ZEROCONF_CFLAGS +ZEROCONF_LIBS +AVAHI_TPOLL_LIBS +AVAHI_TPOLL_CFLAGS +AVAHI_LIBS +AVAHI_CFLAGS +PKG_CONFIG +QUOTA_LIBS +compiled_backends +DEFAULT_CNID_SCHEME +USE_MYSQL_BACKEND_FALSE +USE_MYSQL_BACKEND_TRUE +MYSQL_CONFIG +MYSQL_LIBS +MYSQL_CFLAGS +USE_TDB_BACKEND_FALSE +USE_TDB_BACKEND_TRUE +USE_LAST_BACKEND_FALSE +USE_LAST_BACKEND_TRUE +USE_CDB_BACKEND_FALSE +USE_CDB_BACKEND_TRUE +BUILD_DBD_DAEMON_FALSE +BUILD_DBD_DAEMON_TRUE +ICONV_LIBS +ICONV_CFLAGS +SERVERTEXT +PKGCONFDIR +AFS_CFLAGS +AFS_LIBS +RUN_LDCONFIG_FALSE +RUN_LDCONFIG_TRUE +NETA_LDCONFIG +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CC +ax_pthread_config +sys_symbol_underscore +LIBADD_DL +LT_DLPREOPEN +LIBADD_DLD_LINK +LIBADD_SHL_LOAD +LIBADD_DLOPEN +LT_DLLOADERS +YFLAGS +YACC +LEXLIB +LEX_OUTPUT_ROOT +LEX +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +SED +LIBTOOL +LN_S +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +NETATALK_VERSION +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL +PS +PERL +GREP' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_maintainer_mode +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_largefile +enable_admin_group +enable_afs +with_pkgconfdir +with_message_dir +with_cracklib +enable_debug +enable_debugging +with_libiconv +with_cnid_dbd_backend +with_cnid_cdb_backend +with_cnid_last_backend +with_cnid_tdb_backend +with_mysql_config +with_cnid_default_backend +enable_quota +enable_zeroconf +enable_tcp_wrappers +with_pam +with_pam_confdir +with_shadow +enable_shell_check +with_init_style +with_init_dir +with_uams_path +with_libgcrypt_dir +with_ssl_dir +with_bdb +enable_pgp_uam +enable_krbV_uam +with_gssapi +with_kerberos +enable_overwrite +with_ldap +with_acls +enable_sendfile +with_libevent +with_libevent_header +with_libevent_lib +with_tdb +with_tracker_pkgconfig_version +with_tracker_prefix +enable_developer +with_dtrace +with_afpstats +with_dbus_sysconf_dir +enable_fhs +with_lockfile +with_docbook +enable_silent_rules +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +YACC +YFLAGS +MYSQL_CFLAGS +MYSQL_LIBS +PKG_CONFIG +AVAHI_CFLAGS +AVAHI_LIBS +AVAHI_TPOLL_CFLAGS +AVAHI_TPOLL_LIBS +TDB_CFLAGS +TDB_LIBS +PKG_CONFIG_PATH +TRACKER_CFLAGS +TRACKER_LIBS +DBUS_CFLAGS +DBUS_LIBS +DBUS_GLIB_CFLAGS +DBUS_GLIB_LIBS +DBUS_GTHREAD_CFLAGS +DBUS_GTHREAD_LIBS' +ac_subdirs_all='libevent' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-maintainer-mode + disable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-largefile omit support for large files + --disable-admin-group disable admin group + --enable-afs enable AFS support + --enable-debug enable verbose debug code + --enable-debugging disable SIGALRM timers and DSI tickles (eg for debugging with gdb/dbx/...) + --enable-quota Turn on quota support (default=auto) + --enable-zeroconf[=DIR] enable Zeroconf support [auto] + --disable-tcp-wrappers disable TCP wrappers support + --disable-shell-check disable checking for a valid shell + --enable-pgp-uam enable build of PGP UAM module + --enable-krbV-uam enable build of Kerberos V UAM module + --enable-overwrite overwrite configuration files during installation + --disable-sendfile disable sendfile syscall + --enable-developer whether to enable developer build (ABI checking) + --enable-fhs use Filesystem Hierarchy Standard (FHS) compatibility + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + --with-pkgconfdir=DIR package specific configuration in DIR + [$sysconfdir] + --with-message-dir=PATH path to server message files [$localstatedir/netatalk/msg/] + --with-cracklib[=DICT] enable/set location of cracklib dictionary [no] + --with-libiconv=BASEDIR Use libiconv in BASEDIR/lib and BASEDIR/include [default=auto] + --with-cnid-dbd-backend build CNID with Database Daemon Data Store [yes] + --with-cnid-cdb-backend build CNID with Concurrent BDB Data Store [no] + --with-cnid-last-backend build LAST CNID scheme [yes] + --with-cnid-tdb-backend build TDB CNID scheme [yes] + --with-mysql-config=PATH + Path to mysql-config binary (default: mysql_config) + --with-cnid-default-backend=val set default DID scheme [dbd] + --with-pam[=PATH] specify path to PAM installation [auto] + --with-pam-confdir=PATH Path to PAM config dir (default: + ${sysconfdir}/pam.d) + --with-shadow enable shadow password support [auto] + --with-init-style use OS specific init config [redhat-sysv|redhat-systemd|suse-sysv|suse-systemd|gentoo|netbsd|debian-sysv|debian-systemd|solaris|systemd] + --with-init-dir=PATH path to OS specific init directory + --with-uams-path=PATH path to UAMs [$libdir/netatalk/] + --with-libgcrypt-dir=PATH + path where LIBGCRYPT is installed (optional). Must + contain lib and include dirs. + --with-ssl-dir=PATH specify path to OpenSSL installation (must contain + lib and include dirs) + --with-bdb=PATH specify path to Berkeley DB installation[auto] + --with-gssapi[=PATH] path to GSSAPI for Kerberos V UAM [auto] + --with-kerberos Kerberos 5 support (default=auto) + --with-ldap[=PATH] LDAP support (default=auto) + --with-acls Include ACL support (default=auto) + --with-libevent whether to use the bundled libevent (default: yes) + --with-libevent-header path to libevent header files + --with-libevent-lib path to libevent library + --with-tdb whether to use the bundled tdb (default: yes) + --with-tracker-pkgconfig-version=VERSION + Version suffix of the Tracker SPARQL pkg-config + (default: 0.12) + --with-tracker-prefix=PATH + Prefix of Tracker installation (default: none) + --with-dtrace Enable dtrace probes (default: enabled if dtrace + found) + --with-afpstats Enable AFP statistics via dbus (default: enabled if + dbus found) + --with-dbus-sysconf-dir=PATH + Path to dbus system bus security configuration + directory (default: ${sysconfdir}/dbus-1/system.d/) + --with-lockfile=PATH Path of netatalk lockfile + --with-docbook Path to Docbook XSL directory + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + YACC The `Yet Another Compiler Compiler' implementation to use. + Defaults to the first program found out of: `bison -y', `byacc', + `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + MYSQL_CFLAGS + C compiler flags for MySQL, overriding checks + MYSQL_LIBS linker flags for MySQL, overriding checks + PKG_CONFIG path to pkg-config utility + AVAHI_CFLAGS + C compiler flags for AVAHI, overriding pkg-config + AVAHI_LIBS linker flags for AVAHI, overriding pkg-config + AVAHI_TPOLL_CFLAGS + C compiler flags for AVAHI_TPOLL, overriding pkg-config + AVAHI_TPOLL_LIBS + linker flags for AVAHI_TPOLL, overriding pkg-config + TDB_CFLAGS C compiler flags for TDB, overriding pkg-config + TDB_LIBS linker flags for TDB, overriding pkg-config + PKG_CONFIG_PATH + Path to additional pkg-config packages + TRACKER_CFLAGS + C compiler flags for TRACKER, overriding pkg-config + TRACKER_LIBS + linker flags for TRACKER, overriding pkg-config + DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config + DBUS_LIBS linker flags for DBUS, overriding pkg-config + DBUS_GLIB_CFLAGS + C compiler flags for DBUS_GLIB, overriding pkg-config + DBUS_GLIB_LIBS + linker flags for DBUS_GLIB, overriding pkg-config + DBUS_GTHREAD_CFLAGS + C compiler flags for DBUS_GTHREAD, overriding pkg-config + DBUS_GTHREAD_LIBS + linker flags for DBUS_GTHREAD, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +NETATALK_VERSION=`cat $srcdir/VERSION` + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +am__api_version='1.12' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + + PACKAGE=netatalk + VERSION=${NETATALK_VERSION} + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + +ac_config_headers="$ac_config_headers config.h" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +enable_dlopen=yes + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.2' +macro_revision='1.3337' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + + + +test x$GREP = x && # Extract the first word of "grep$EXEEXT", so it can be a program name with args. +set dummy grep$EXEEXT; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GREP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GREP="$GREP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GREP" && ac_cv_path_GREP="grep$EXEEXT" + ;; +esac +fi +GREP=$ac_cv_path_GREP +if test -n "$GREP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GREP" >&5 +$as_echo "$GREP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +test x$GREP = x && as_fn_error $? "no acceptable grep found in \$PATH" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + test "x$PERL" = x && # Extract the first word of "perl$EXEEXT", so it can be a program name with args. +set dummy perl$EXEEXT; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="perl$EXEEXT" + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test "x$PERL" = x && as_fn_error $? "no acceptable Perl found in \$PATH" "$LINENO" 5 + + +test x$GREP = x && # Extract the first word of "grep$EXEEXT", so it can be a program name with args. +set dummy grep$EXEEXT; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GREP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GREP="$GREP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GREP" && ac_cv_path_GREP="grep$EXEEXT" + ;; +esac +fi +GREP=$ac_cv_path_GREP +if test -n "$GREP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GREP" >&5 +$as_echo "$GREP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +test x$GREP = x && as_fn_error $? "no acceptable grep found in \$PATH" "$LINENO" 5 + + +test x$PS = x && # Extract the first word of "ps$EXEEXT", so it can be a program name with args. +set dummy ps$EXEEXT; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PS in + [\\/]* | ?:[\\/]*) + ac_cv_path_PS="$PS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PS" && ac_cv_path_PS="ps$EXEEXT" + ;; +esac +fi +PS=$ac_cv_path_PS +if test -n "$PS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PS" >&5 +$as_echo "$PS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +test x$PS = x && as_fn_error $? "no acceptable ps found in \$PATH" "$LINENO" 5 + +if test "x$CC" != xcc; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 +$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 +$as_echo_n "checking whether cc understands -c and -o together... " >&6; } +fi +set dummy $CC; ac_cc=`$as_echo "$2" | + sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' +rm -f conftest2.* +if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.$ac_ext >&5' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' + rm -f conftest2.* + if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f core conftest* + +fi +if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h + +fi + +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +for ac_prog in flex lex +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LEX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LEX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LEX=$ac_cv_prog_LEX +if test -n "$LEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 +$as_echo "$LEX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LEX" && break +done +test -n "$LEX" || LEX=":" + +if test "x$LEX" != "x:"; then + cat >conftest.l <<_ACEOF +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ + yyless ((input () != 0)); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; +#endif +int +main (void) +{ + return ! yylex () + ! yywrap (); +} +_ACEOF +{ { ac_try="$LEX conftest.l" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$LEX conftest.l") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 +$as_echo_n "checking lex output file root... " >&6; } +if ${ac_cv_prog_lex_root+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 +$as_echo "$ac_cv_prog_lex_root" >&6; } +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +if test -z "${LEXLIB+set}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 +$as_echo_n "checking lex library... " >&6; } +if ${ac_cv_lib_lex+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS=$LIBS + ac_cv_lib_lex='none needed' + for ac_lib in '' -lfl -ll; do + LIBS="$ac_lib $ac_save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lex=$ac_lib +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + test "$ac_cv_lib_lex" != 'none needed' && break + done + LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 +$as_echo "$ac_cv_lib_lex" >&6; } + test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 +$as_echo_n "checking whether yytext is a pointer... " >&6; } +if ${ac_cv_prog_lex_yytext_pointer+:} false; then : + $as_echo_n "(cached) " >&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +ac_save_LIBS=$LIBS +LIBS="$LEXLIB $ac_save_LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define YYTEXT_POINTER 1 +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_prog_lex_yytext_pointer=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 +$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } +if test $ac_cv_prog_lex_yytext_pointer = yes; then + +$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h + +fi +rm -f conftest.l $LEX_OUTPUT_ROOT.c + +fi +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_YACC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_YACC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +$as_echo "$YACC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if we can add '__attribute__((unused))' to CFLAGS" >&5 +$as_echo_n "checking to see if we can add '__attribute__((unused))' to CFLAGS... " >&6; } +if test x$GCC != x ; then + CFLAGS="-D_U_=\"__attribute__((unused))\" $CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + CFLAGS="-D_U_=\"\" $CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +for ac_header in mntent.h unistd.h termios.h ufs/quota.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in netdb.h sgtty.h statfs.h dlfcn.h langinfo.h locale.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/param.h sys/fcntl.h sys/termios.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/mount.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" "#ifdef HAVE_SYS_PARAM_H +#include +#endif + +" +if test "x$ac_cv_header_sys_mount_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_MOUNT_H 1 +_ACEOF + +fi + +done + +ac_fn_c_check_type "$LINENO" "fshare_t" "ac_cv_type_fshare_t" "#include +" +if test "x$ac_cv_type_fshare_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_FSHARE_T 1 +_ACEOF + + +fi + + +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + wx_largefile=no + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 + #include +int +main () +{ +typedef struct { + unsigned int field: sizeof(off_t) == 8; +} wxlf; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64 +else + ac_cv_sys_file_offset_bits=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } + + if test "$ac_cv_sys_file_offset_bits" != no; then + wx_largefile=yes + +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF + + fi + + if test "x$wx_largefile" != "xyes"; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 + #include +int +main () +{ +typedef struct { + unsigned int field: sizeof(off_t) == 8; +} wxlf; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1 +else + ac_cv_sys_large_files=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } + + if test "$ac_cv_sys_large_files" != no; then + wx_largefile=yes + +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF + + fi + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64 bit off_t" >&5 +$as_echo_n "checking for 64 bit off_t... " >&6; } +if ${netatalk_cv_SIZEOF_OFF_T+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + netatalk_cv_SIZEOF_OFF_T=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +main() { exit((sizeof(off_t) == 8) ? 0 : 1); } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + netatalk_cv_SIZEOF_OFF_T=yes +else + netatalk_cv_SIZEOF_OFF_T=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_SIZEOF_OFF_T" >&5 +$as_echo "$netatalk_cv_SIZEOF_OFF_T" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if large file support is available" >&5 +$as_echo_n "checking if large file support is available... " >&6; } + if test "x$netatalk_cv_SIZEOF_OFF_T" != "xno"; then + +$as_echo "#define HAVE_LARGEFILE_SUPPORT /**/" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "AFP 3.x support requires Large File Support." "$LINENO" 5 + fi +fi + + + +LT_DLLOADERS= + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +LIBADD_DLOPEN= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +$as_echo "#define HAVE_LIBDL 1" >>confdefs.h + + if test "$ac_cv_search_dlopen" != "none required" ; then + LIBADD_DLOPEN="-ldl" + fi + libltdl_cv_lib_dl_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if HAVE_DLFCN_H +# include +#endif + +int +main () +{ +dlopen(0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +$as_echo "#define HAVE_LIBDL 1" >>confdefs.h + + libltdl_cv_func_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + +$as_echo "#define HAVE_LIBDL 1" >>confdefs.h + + LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes" + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la" +fi + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DLOPEN" + for ac_func in dlerror +do : + ac_fn_c_check_func "$LINENO" "dlerror" "ac_cv_func_dlerror" +if test "x$ac_cv_func_dlerror" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLERROR 1 +_ACEOF + +fi +done + + LIBS="$lt_save_LIBS" +fi + + +LIBADD_SHL_LOAD= +ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + +$as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h + + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + +$as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h + + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la" + LIBADD_SHL_LOAD="-ldld" +fi + +fi + + + +case $host_os in +darwin[1567].*) +# We only want this for pre-Mac OS X 10.4. + ac_fn_c_check_func "$LINENO" "_dyld_func_lookup" "ac_cv_func__dyld_func_lookup" +if test "x$ac_cv_func__dyld_func_lookup" = xyes; then : + +$as_echo "#define HAVE_DYLD 1" >>confdefs.h + + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dyld.la" +fi + + ;; +beos*) + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}load_add_on.la" + ;; +cygwin* | mingw* | os2* | pw32*) + ac_fn_c_check_decl "$LINENO" "cygwin_conv_path" "ac_cv_have_decl_cygwin_conv_path" "#include +" +if test "x$ac_cv_have_decl_cygwin_conv_path" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_CYGWIN_CONV_PATH $ac_have_decl +_ACEOF + + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}loadlibrary.la" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + +$as_echo "#define HAVE_DLD 1" >>confdefs.h + + LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dld_link.la" +fi + + + + +LT_DLPREOPEN= +if test -n "$LT_DLLOADERS" +then + for lt_loader in $LT_DLLOADERS; do + LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen $lt_loader " + done + +$as_echo "#define HAVE_LIBDLLOADER 1" >>confdefs.h + +fi + + +LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD" + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +for ac_func in dlopen dlsym dlclose +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ prefix in compiled symbols" >&5 +$as_echo_n "checking for _ prefix in compiled symbols... " >&6; } +if ${lt_cv_sys_symbol_underscore+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext <<_LT_EOF +void nm_test_func(){} +int main(){nm_test_func;return 0;} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + lt_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&5 + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -rf conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_symbol_underscore" >&5 +$as_echo "$lt_cv_sys_symbol_underscore" >&6; } + sys_symbol_underscore=$lt_cv_sys_symbol_underscore + + +if test x"$lt_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have to add an underscore for dlsym" >&5 +$as_echo_n "checking whether we have to add an underscore for dlsym... " >&6; } +if ${libltdl_cv_need_uscore+:} false; then : + $as_echo_n "(cached) " >&6 +else + libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DLOPEN" + if test "$cross_compiling" = yes; then : + libltdl_cv_need_uscore=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; + x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; + x$lt_dlunknown|x*) ;; + esac + else : + # compilation failed + + fi +fi +rm -fr conftest* + + LIBS="$save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_need_uscore" >&5 +$as_echo "$libltdl_cv_need_uscore" >&6; } + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + +$as_echo "#define NEED_USCORE 1" >>confdefs.h + +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + +$as_echo "#define DLSYM_PREPEND_UNDERSCORE 1" >>confdefs.h + +fi + +ac_neta_haveatfuncs=yes +for ac_func in openat renameat fstatat unlinkat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + ac_neta_haveatfuncs=no +fi +done + +if test x"$ac_neta_haveatfuncs" = x"yes" ; then + +$as_echo "#define _ATFILE_SOURCE 1" >>confdefs.h + + +$as_echo "#define HAVE_ATFUNCS 1" >>confdefs.h + +fi +ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "#include +" +if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TM_TM_GMTOFF 1 +_ACEOF + + +fi + + +for ac_func in backtrace_symbols dirfd getusershell pread pwrite pselect +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in setlinebuf strlcat strlcpy strnlen mempcpy vasprintf asprintf +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in mmap utime getpagesize +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 +$as_echo_n "checking for library containing gethostbyname... " >&6; } +if ${ac_cv_search_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_gethostbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gethostbyname+:} false; then : + break +fi +done +if ${ac_cv_search_gethostbyname+:} false; then : + +else + ac_cv_search_gethostbyname=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 +$as_echo "$ac_cv_search_gethostbyname" >&6; } +ac_res=$ac_cv_search_gethostbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing connect" >&5 +$as_echo_n "checking for library containing connect... " >&6; } +if ${ac_cv_search_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_connect=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_connect+:} false; then : + break +fi +done +if ${ac_cv_search_connect+:} false; then : + +else + ac_cv_search_connect=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_connect" >&5 +$as_echo "$ac_cv_search_connect" >&6; } +ac_res=$ac_cv_search_connect +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +for ac_func in getifaddrs +do : + ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs" +if test "x$ac_cv_func_getifaddrs" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETIFADDRS 1 +_ACEOF + +fi +done + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 +$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test x"$ax_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case ${host_os} in + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" + ;; + + darwin*) + ax_pthread_flags="-pthread $ax_pthread_flags" + ;; +esac + +if test x"$ax_pthread_ok" = xno; then +for flag in $ax_pthread_flags; do + + case $flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 +$as_echo_n "checking whether pthreads work with $flag... " >&6; } + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ax_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x"$ax_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 +$as_echo_n "checking for the pthreads library -l$flag... " >&6; } + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; } +int +main () +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr = $attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + attr_name=$attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 +$as_echo "$attr_name" >&6; } + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $attr_name +_ACEOF + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 +$as_echo_n "checking if more special flags are required for pthreads... " >&6; } + flag=no + case ${host_os} in + aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; + osf* | hpux*) flag="-D_REENTRANT";; + solaris*) + if test "$GCC" = "yes"; then + flag="-D_REENTRANT" + else + flag="-mt -D_REENTRANT" + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 +$as_echo "${flag}" >&6; } + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include +int +main () +{ +int i = PTHREAD_PRIO_INHERIT; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else + ax_cv_PTHREAD_PRIO_INHERIT=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"; then : + +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + +fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + for ac_prog in xlc_r cc_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" + + else + PTHREAD_CC=$CC + fi +else + PTHREAD_CC="$CC" +fi + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$ax_pthread_ok" = xyes; then + +$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + + : +else + ax_pthread_ok=no + as_fn_error $? "missing pthread_sigmask" "$LINENO" 5 +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +$as_echo "#define OPEN_NOFOLLOW_ERRNO ELOOP" >>confdefs.h + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to check for 64bit libraries" >&5 +$as_echo_n "checking whether to check for 64bit libraries... " >&6; } +# Test if the compiler is in 64bit mode +echo 'int i;' > conftest.$ac_ext +atalk_cv_cc_64bit_output=no +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *"ELF 64"*) + atalk_cv_cc_64bit_output=yes + ;; + esac +fi +rm -rf conftest* + +case $host_cpu:$atalk_cv_cc_64bit_output in +powerpc64:yes | s390x:yes | sparc*:yes | x86_64:yes | i386:yes) + case $target_os in + solaris2*) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + atalk_libname="lib/64" + ;; + *bsd* | dragonfly*) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + atalk_libname="lib" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + atalk_libname="lib64" + ;; + esac + ;; +*:*) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + atalk_libname="lib" + ;; +esac + + + +case "$host_os" in + *aix*) this_os=aix ;; + *freebsd*) this_os=freebsd ;; + *hpux11*) this_os=hpux11 ;; + *irix*) this_os=irix ;; + *linux*) this_os=linux ;; + *osx*) this_os=macosx ;; + *darwin*) this_os=macosx ;; + *netbsd*) this_os=netbsd ;; + *openbsd*) this_os=openbsd ;; + *osf*) this_os=tru64 ;; + *solaris*) this_os=solaris ;; +esac + +case "$host_cpu" in + i386|i486|i586|i686|k7) this_cpu=x86 ;; + alpha) this_cpu=alpha ;; + mips) this_cpu=mips ;; + powerpc|ppc) this_cpu=ppc ;; +esac + +case "$this_os" in + linux) +$as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + ;; + kfreebsd-gnu) +$as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + ;; +esac + + +if test x"$this_os" = "xfreebsd"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: * FreeBSD specific configuration" >&5 +$as_echo " * FreeBSD specific configuration" >&6; } + +$as_echo "#define BSD4_4 1" >>confdefs.h + + +$as_echo "#define FREEBSD 1" >>confdefs.h + + +$as_echo "#define OPEN_NOFOLLOW_ERRNO EMLINK" >>confdefs.h + +fi + +if test x"$this_os" = "xkfreebsd-gnu"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: * GNU/kFreeBSD specific configuration" >&5 +$as_echo " * GNU/kFreeBSD specific configuration" >&6; } + +$as_echo "#define BSD4_4 1" >>confdefs.h + + +$as_echo "#define FREEBSD 1" >>confdefs.h + + +$as_echo "#define OPEN_NOFOLLOW_ERRNO EMLINK" >>confdefs.h + +fi + +if test x"$this_os" = "xlinux"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: * Linux specific configuration" >&5 +$as_echo " * Linux specific configuration" >&6; } + +$as_echo "#define LINUX 1" >>confdefs.h + + for ac_header in linux/dqblk_xfs.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "linux/dqblk_xfs.h" "ac_cv_header_linux_dqblk_xfs_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_dqblk_xfs_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_DQBLK_XFS_H 1 +_ACEOF + +else + for ac_header in linux/xqm.h linux/xfs_fs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_header in xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +fi + +done + + + + +$as_echo "#define HAVE_BROKEN_DBTOB 1" >>confdefs.h + + + need_dash_r=no +fi + +if test x"$this_os" = "xnetbsd"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: * NetBSD specific configuration" >&5 +$as_echo " * NetBSD specific configuration" >&6; } + +$as_echo "#define BSD4_4 1" >>confdefs.h + + +$as_echo "#define NETBSD 1" >>confdefs.h + + +$as_echo "#define OPEN_NOFOLLOW_ERRNO EFTYPE" >>confdefs.h + + + CFLAGS="-I\$(top_srcdir)/sys/netbsd $CFLAGS" + need_dash_r=yes + + +$as_echo "#define UAM_DHX 1" >>confdefs.h + +fi + +if test x"$this_os" = "xopenbsd"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: * OpenBSD specific configuration" >&5 +$as_echo " * OpenBSD specific configuration" >&6; } + +$as_echo "#define BSD4_4 1" >>confdefs.h + + +$as_echo "#define UAM_DHX 1" >>confdefs.h + +fi + +if test x"$this_os" = "xsolaris"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: * Solaris specific configuration" >&5 +$as_echo " * Solaris specific configuration" >&6; } + +$as_echo "#define __svr4__ 1" >>confdefs.h + + +$as_echo "#define _ISOC9X_SOURCE 1" >>confdefs.h + + +$as_echo "#define NO_STRUCT_TM_GMTOFF 1" >>confdefs.h + + +$as_echo "#define SOLARIS 1" >>confdefs.h + + +$as_echo "#define _XOPEN_SOURCE 600" >>confdefs.h + + +$as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + need_dash_r=yes + init_style=solaris +fi + +# Extract the first word of "ldconfig", so it can be a program name with args. +set dummy ldconfig; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_NETA_LDCONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $NETA_LDCONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_NETA_LDCONFIG="$NETA_LDCONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/usr/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_NETA_LDCONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +NETA_LDCONFIG=$ac_cv_path_NETA_LDCONFIG +if test -n "$NETA_LDCONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NETA_LDCONFIG" >&5 +$as_echo "$NETA_LDCONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +echo NETA_LDCONFIG = $NETA_LDCONFIG + if test x"$this_os" = x"linux" -a x"$NETA_LDCONFIG" != x""; then + RUN_LDCONFIG_TRUE= + RUN_LDCONFIG_FALSE='#' +else + RUN_LDCONFIG_TRUE='#' + RUN_LDCONFIG_FALSE= +fi + + + + + netatalk_cv_admin_group=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for administrative group support" >&5 +$as_echo_n "checking for administrative group support... " >&6; } + # Check whether --enable-admin-group was given. +if test "${enable_admin_group+set}" = set; then : + enableval=$enable_admin_group; + if test x"$enableval" = x"no"; then + +$as_echo "#define ADMIN_GRP 0" >>confdefs.h + + netatalk_cv_admin_group=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + +$as_echo "#define ADMIN_GRP 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi +else + + +$as_echo "#define ADMIN_GRP 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + + AFS_LIBS= + AFS_CFLAGS= + + netatalk_cv_afs=no + # Check whether --enable-afs was given. +if test "${enable_afs+set}" = set; then : + enableval=$enable_afs; + if test "x$enableval" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pioctl in -lafsauthent" >&5 +$as_echo_n "checking for pioctl in -lafsauthent... " >&6; } +if ${ac_cv_lib_afsauthent_pioctl+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lafsauthent $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pioctl (); +int +main () +{ +return pioctl (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_afsauthent_pioctl=yes +else + ac_cv_lib_afsauthent_pioctl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_afsauthent_pioctl" >&5 +$as_echo "$ac_cv_lib_afsauthent_pioctl" >&6; } +if test "x$ac_cv_lib_afsauthent_pioctl" = xyes; then : + netatalk_cv_afs=yes +else + as_fn_error $? "AFS installation not found" "$LINENO" 5 + +fi + + AFS_LIBS=-lresolv -lafsrpc -lafsauthent + +$as_echo "#define AFS 1" >>confdefs.h + + fi + + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable AFS support" >&5 +$as_echo_n "checking whether to enable AFS support... " >&6; } + if test x"$netatalk_cv_afs" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + + + + + PKGCONFDIR="${sysconfdir}" + + +# Check whether --with-pkgconfdir was given. +if test "${with_pkgconfdir+set}" = set; then : + withval=$with_pkgconfdir; + if test "x$withval" != "x"; then + PKGCONFDIR="$withval" + fi + + +fi + + + + SERVERTEXT="${localstatedir}/netatalk/msg" + + +# Check whether --with-message-dir was given. +if test "${with_message_dir+set}" = set; then : + withval=$with_message_dir; + if test x"$withval" = x"no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: message-dir is mandatory and cannot be disabled, using default" >&5 +$as_echo "$as_me: WARNING: message-dir is mandatory and cannot be disabled, using default" >&2;} + elif test "x$withval" != "x" && test x"$withval" != x"yes"; then + SERVERTEXT="$withval" + fi + + +fi + + + + + + + +netatalk_cv_with_cracklib=no + +# Check whether --with-cracklib was given. +if test "${with_cracklib+set}" = set; then : + withval=$with_cracklib; + if test "x$withval" != "xno" ; then + cracklib="$withval" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lcrack" >&5 +$as_echo_n "checking for main in -lcrack... " >&6; } +if ${ac_cv_lib_crack_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrack $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crack_main=yes +else + ac_cv_lib_crack_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crack_main" >&5 +$as_echo "$ac_cv_lib_crack_main" >&6; } +if test "x$ac_cv_lib_crack_main" = xyes; then : + + +$as_echo "#define USE_CRACKLIB 1" >>confdefs.h + + LIBS="$LIBS -lcrack" + if test "$cracklib" = "yes"; then + cracklib="/usr/$atalk_libname/cracklib_dict" + fi + +cat >>confdefs.h <<_ACEOF +#define _PATH_CRACKLIB "$cracklib" +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: setting cracklib dictionary to $cracklib" >&5 +$as_echo "setting cracklib dictionary to $cracklib" >&6; } + netatalk_cv_with_cracklib=yes + +else + + as_fn_error $? "cracklib not found!" "$LINENO" 5 + + +fi + + fi + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cracklib support" >&5 +$as_echo_n "checking for cracklib support... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_with_cracklib" >&5 +$as_echo "$netatalk_cv_with_cracklib" >&6; } + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable verbose debug code" >&5 +$as_echo_n "checking whether to enable verbose debug code... " >&6; } +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; + if test "$enableval" != "no"; then + if test "$enableval" = "yes"; then + +$as_echo "#define DEBUG 1" >>confdefs.h + + else + +cat >>confdefs.h <<_ACEOF +#define DEBUG $enableval +_ACEOF + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NDEBUG 1" >>confdefs.h + + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NDEBUG 1" >>confdefs.h + + + +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable debugging with debuggers" >&5 +$as_echo_n "checking whether to enable debugging with debuggers... " >&6; } +# Check whether --enable-debugging was given. +if test "${enable_debugging+set}" = set; then : + enableval=$enable_debugging; + if test "$enableval" != "no"; then + if test "$enableval" = "yes"; then + +$as_echo "#define DEBUGGING 1" >>confdefs.h + + else + +cat >>confdefs.h <<_ACEOF +#define DEBUGGING $enableval +_ACEOF + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +fi + + + + + + + saved_CPPFLAGS="$CPPFLAGS" + savedcflags="$CFLAGS" + savedldflags="$LDFLAGS" + ICONV_CFLAGS="" + ICONV_LIBS="" + + +# Check whether --with-libiconv was given. +if test "${with_libiconv+set}" = set; then : + withval=$with_libiconv; case "$withval" in + no) + ;; + yes) + ;; + *) + ICONV_CFLAGS="-I$withval/include" + ICONV_LIBS="-L$withval/$atalk_libname" + ;; + esac +else + withval="no" + +fi + + + CFLAGS="$ICONV_CFLAGS $CFLAGS" + LDFLAGS="$LDFLAGS $ICONV_LIBS -liconv" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libiconv" >&5 +$as_echo_n "checking for libiconv... " >&6; } +if ${netatalk_cv_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + + iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + netatalk_cv_iconv=yes +else + netatalk_cv_iconv=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_iconv" >&5 +$as_echo "$netatalk_cv_iconv" >&6; } + + if test x"$netatalk_cv_iconv" = x"yes"; then + ICONV_LIBS="$ICONV_LIBS -liconv" + else + CFLAGS="$savedcflags" + LDFLAGS="$savedldflags" + ICONV_LIBS="" + ICONV_CFLAGS="" + if test x"$withval" != x"no"; then + as_fn_error $? "libiconv not found" "$LINENO" 5 + fi + fi + + + + ac_new_flags="" + for i in $ICONV_CFLAGS; do + case $i in + -I/usr/include|-I/usr/include/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + ICONV_CFLAGS=$ac_new_flags + + + ac_new_flags="" + for i in $ICONV_LIBS; do + case $i in + -L/usr/lib|-L/usr/lib/|-L/usr|-L/usr/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + ICONV_LIBS=$ac_new_flags + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${netatalk_cv_HAVE_USABLE_ICONV+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + netatalk_cv_HAVE_USABLE_ICONV=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +\ +#include +main() { + iconv_t cd = iconv_open("ASCII", "UTF-8"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + netatalk_cv_HAVE_USABLE_ICONV=yes +else + netatalk_cv_HAVE_USABLE_ICONV=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_HAVE_USABLE_ICONV" >&5 +$as_echo "$netatalk_cv_HAVE_USABLE_ICONV" >&6; } + + if test x"$netatalk_cv_HAVE_USABLE_ICONV" = x"yes"; then + +$as_echo "#define HAVE_USABLE_ICONV 1" >>confdefs.h + + fi + + if test x"$netatalk_cv_HAVE_USABLE_ICONV" = x"yes"; then + if ${am_cv_proto_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +\ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_cv_proto_iconv_arg1="" +else + am_cv_proto_iconv_arg1="const" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" +fi + + +cat >>confdefs.h <<_ACEOF +#define ICONV_CONST $am_cv_proto_iconv_arg1 +_ACEOF + + fi + + if test x"$netatalk_cv_HAVE_USABLE_ICONV" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether iconv supports UCS-2-INTERNAL" >&5 +$as_echo_n "checking whether iconv supports UCS-2-INTERNAL... " >&6; } +if ${netatalk_cv_HAVE_UCS2INTERNAL+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + netatalk_cv_HAVEUCS2INTERNAL=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +\ +#include +int main() { + iconv_t cd = iconv_open("ASCII", "UCS-2-INTERNAL"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + netatalk_cv_HAVE_UCS2INTERNAL=yes +else + netatalk_cv_HAVE_UCS2INTERNAL=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_HAVE_UCS2INTERNAL" >&5 +$as_echo "$netatalk_cv_HAVE_UCS2INTERNAL" >&6; } + + if test x"$netatalk_cv_HAVE_UCS2INTERNAL" = x"yes"; then + +$as_echo "#define HAVE_UCS2INTERNAL 1" >>confdefs.h + + fi + fi + + CFLAGS="$savedcflags" + LDFLAGS="$savedldflags" + CPPFLAGS="$saved_CPPFLAGS" + + + + + bdb_required=no + compiled_backends="" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether or not to use Database Daemon CNID backend" >&5 +$as_echo_n "checking whether or not to use Database Daemon CNID backend... " >&6; } + +# Check whether --with-cnid-dbd-backend was given. +if test "${with_cnid_dbd_backend+set}" = set; then : + withval=$with_cnid_dbd_backend; if test x"$withval" = x"no"; then + use_dbd_backend=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + use_dbd_backend=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + +else + + use_dbd_backend=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + if test $use_dbd_backend = yes; then + compiled_backends="$compiled_backends dbd" + +$as_echo "#define CNID_BACKEND_DBD 1" >>confdefs.h + + if test x"$DEFAULT_CNID_SCHEME" = x; then + DEFAULT_CNID_SCHEME=dbd + fi + bdb_required=yes + fi + if test x"$use_dbd_backend" = x"yes"; then + BUILD_DBD_DAEMON_TRUE= + BUILD_DBD_DAEMON_FALSE='#' +else + BUILD_DBD_DAEMON_TRUE='#' + BUILD_DBD_DAEMON_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether or not to use BDB Concurrent Data Store" >&5 +$as_echo_n "checking whether or not to use BDB Concurrent Data Store... " >&6; } + +# Check whether --with-cnid-cdb-backend was given. +if test "${with_cnid_cdb_backend+set}" = set; then : + withval=$with_cnid_cdb_backend; + if test x"$withval" = x"no"; then + use_cdb_backend=no + else + use_cdb_backend=yes + fi + +else + + use_cdb_backend=no + +fi + + + + if test $use_cdb_backend = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define CNID_BACKEND_CDB 1" >>confdefs.h + + if test x"$DEFAULT_CNID_SCHEME" = x; then + DEFAULT_CNID_SCHEME=cdb + fi + bdb_required=yes + compiled_backends="$compiled_backends cdb" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + if test x"$use_cdb_backend" = x"yes"; then + USE_CDB_BACKEND_TRUE= + USE_CDB_BACKEND_FALSE='#' +else + USE_CDB_BACKEND_TRUE='#' + USE_CDB_BACKEND_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether or not to use LAST DID scheme" >&5 +$as_echo_n "checking whether or not to use LAST DID scheme... " >&6; } + +# Check whether --with-cnid-last-backend was given. +if test "${with_cnid_last_backend+set}" = set; then : + withval=$with_cnid_last_backend; + if test x"$withval" = x"no"; then + use_last_backend=no + else + use_last_backend=yes + fi + +else + + use_last_backend=yes + +fi + + + if test $use_last_backend = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define CNID_BACKEND_LAST 1" >>confdefs.h + + if test x"$DEFAULT_CNID_SCHEME" = x; then + DEFAULT_CNID_SCHEME=last + fi + compiled_backends="$compiled_backends last" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + if test x"$use_last_backend" = x"yes"; then + USE_LAST_BACKEND_TRUE= + USE_LAST_BACKEND_FALSE='#' +else + USE_LAST_BACKEND_TRUE='#' + USE_LAST_BACKEND_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether or not to use TDB DID scheme" >&5 +$as_echo_n "checking whether or not to use TDB DID scheme... " >&6; } + +# Check whether --with-cnid-tdb-backend was given. +if test "${with_cnid_tdb_backend+set}" = set; then : + withval=$with_cnid_tdb_backend; + if test x"$withval" = x"no"; then + use_tdb_backend=no + else + use_tdb_backend=yes + fi + +else + + use_tdb_backend=yes + +fi + + + if test $use_tdb_backend = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define CNID_BACKEND_TDB 1" >>confdefs.h + + if test x"$DEFAULT_CNID_SCHEME" = x; then + DEFAULT_CNID_SCHEME=tdb + fi + compiled_backends="$compiled_backends tdb" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + if test x"$use_tdb_backend" = x"yes"; then + USE_TDB_BACKEND_TRUE= + USE_TDB_BACKEND_FALSE='#' +else + USE_TDB_BACKEND_TRUE='#' + USE_TDB_BACKEND_FALSE= +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking MySQL library and headers" >&5 +$as_echo_n "checking MySQL library and headers... " >&6; } + +# Check whether --with-mysql-config was given. +if test "${with_mysql_config+set}" = set; then : + withval=$with_mysql_config; MYSQL_CONFIG=$withval + +fi + + + if test -z "$MYSQL_CONFIG" -a -z "$MYSQL_CFLAGS" -a -z "$MYSQL_LIBS" ; then + # Extract the first word of "mysql_config", so it can be a program name with args. +set dummy mysql_config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MYSQL_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MYSQL_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_MYSQL_CONFIG="$MYSQL_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MYSQL_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MYSQL_CONFIG=$ac_cv_path_MYSQL_CONFIG +if test -n "$MYSQL_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CONFIG" >&5 +$as_echo "$MYSQL_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi + + if test -x "$MYSQL_CONFIG" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CONFIG" >&5 +$as_echo "$MYSQL_CONFIG" >&6; } + MYSQL_CFLAGS="`$MYSQL_CONFIG --cflags`" + MYSQL_LIBS="`$MYSQL_CONFIG --libs`" + ac_cv_with_cnid_mysql="yes" + elif test -n "$MYSQL_CFLAGS" -a -n "$MYSQL_LIBS" ; then + ac_cv_with_cnid_mysql="yes" + fi + + if test x"$ac_cv_with_cnid_mysql" = x"yes" ; then + compiled_backends="$compiled_backends mysql" + +$as_echo "#define CNID_BACKEND_MYSQL 1" >>confdefs.h + + fi + + + + if test x"$ac_cv_with_cnid_mysql" = x"yes"; then + USE_MYSQL_BACKEND_TRUE= + USE_MYSQL_BACKEND_FALSE='#' +else + USE_MYSQL_BACKEND_TRUE='#' + USE_MYSQL_BACKEND_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking default DID scheme" >&5 +$as_echo_n "checking default DID scheme... " >&6; } + +# Check whether --with-cnid-default-backend was given. +if test "${with_cnid_default_backend+set}" = set; then : + withval=$with_cnid_default_backend; + if test x"$withval" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ignored" >&5 +$as_echo "ignored" >&6; } + else + DEFAULT_CNID_SCHEME=$withval + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEFAULT_CNID_SCHEME" >&5 +$as_echo "$DEFAULT_CNID_SCHEME" >&6; } + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEFAULT_CNID_SCHEME" >&5 +$as_echo "$DEFAULT_CNID_SCHEME" >&6; } + +fi + + + if test x"$DEFAULT_CNID_SCHEME" = x; then + as_fn_error $? "No DID schemes compiled in " "$LINENO" 5 + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether default CNID scheme has been activated" >&5 +$as_echo_n "checking whether default CNID scheme has been activated... " >&6; } + found_scheme=no + for scheme in $compiled_backends ; do + if test x"$scheme" = x"$DEFAULT_CNID_SCHEME"; then + found_scheme=yes + fi + done + if test x"$found_scheme" = x"no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Specified default CNID scheme $DEFAULT_CNID_SCHEME was not selected for compilation" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_CNID_SCHEME "$DEFAULT_CNID_SCHEME" +_ACEOF + + + + + if test "x$bdb_required" = "xyes"; then + bdb_required=yes + else + bdb_required=no + fi + + + + # Check whether --enable-quota was given. +if test "${enable_quota+set}" = set; then : + enableval=$enable_quota; +fi + + + if test x$enable_quota != xno; then + QUOTA_LIBS="" + netatalk_cv_quotasupport="yes" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrpcsvc" >&5 +$as_echo_n "checking for main in -lrpcsvc... " >&6; } +if ${ac_cv_lib_rpcsvc_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrpcsvc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rpcsvc_main=yes +else + ac_cv_lib_rpcsvc_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rpcsvc_main" >&5 +$as_echo "$ac_cv_lib_rpcsvc_main" >&6; } +if test "x$ac_cv_lib_rpcsvc_main" = xyes; then : + QUOTA_LIBS="-lrpcsvc" +fi + + for ac_header in rpc/rpc.h rpc/pmap_prot.h rpcsvc/rquota.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + + QUOTA_LIBS="" + netatalk_cv_quotasupport="no" + +$as_echo "#define NO_QUOTA_SUPPORT 1" >>confdefs.h + + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getfsquota in -lquota" >&5 +$as_echo_n "checking for getfsquota in -lquota... " >&6; } +if ${ac_cv_lib_quota_getfsquota+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lquota -lprop -lrpcsvc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getfsquota (); +int +main () +{ +return getfsquota (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_quota_getfsquota=yes +else + ac_cv_lib_quota_getfsquota=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_quota_getfsquota" >&5 +$as_echo "$ac_cv_lib_quota_getfsquota" >&6; } +if test "x$ac_cv_lib_quota_getfsquota" = xyes; then : + QUOTA_LIBS="-lquota -lprop -lrpcsvc" + +$as_echo "#define HAVE_LIBQUOTA 1" >>confdefs.h + +fi + + else + netatalk_cv_quotasupport="no" + +$as_echo "#define NO_QUOTA_SUPPORT 1" >>confdefs.h + + fi + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi + +fi + + ZEROCONF_LIBS="" + ZEROCONF_CFLAGS="" + found_zeroconf=no + zeroconf_dir="" + + # Check whether --enable-zeroconf was given. +if test "${enable_zeroconf+set}" = set; then : + enableval=$enable_zeroconf; zeroconf=$enableval +else + zeroconf=try + +fi + + + [ -n "$atalk_libname" ] || as_fn_error $? "internal error, atalk_libname undefined" "$LINENO" 5 + + if test "x$zeroconf" != "xno"; then + savedcppflags="$CPPFLAGS" + savedldflags="$LDFLAGS" + + if test "x$zeroconf" = "xyes" -o "x$zeroconf" = "xtry"; then + zeroconf_dir="/usr" + else + zeroconf_dir="$zeroconf" + fi + + # mDNS support using mDNSResponder + ac_fn_c_check_header_mongrel "$LINENO" "dns_sd.h" "ac_cv_header_dns_sd_h" "$ac_includes_default" +if test "x$ac_cv_header_dns_sd_h" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DNSServiceRegister in -ldns_sd" >&5 +$as_echo_n "checking for DNSServiceRegister in -ldns_sd... " >&6; } +if ${ac_cv_lib_dns_sd_DNSServiceRegister+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldns_sd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char DNSServiceRegister (); +int +main () +{ +return DNSServiceRegister (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dns_sd_DNSServiceRegister=yes +else + ac_cv_lib_dns_sd_DNSServiceRegister=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dns_sd_DNSServiceRegister" >&5 +$as_echo "$ac_cv_lib_dns_sd_DNSServiceRegister" >&6; } +if test "x$ac_cv_lib_dns_sd_DNSServiceRegister" = xyes; then : + +$as_echo "#define USE_ZEROCONF 1" >>confdefs.h + +fi + + +fi + + + + if test "$ac_cv_lib_dns_sd_DNSServiceRegister" = yes; then + ZEROCONF_LIBS="-ldns_sd" + +$as_echo "#define HAVE_MDNS 1" >>confdefs.h + + found_zeroconf=yes + fi + + # mDNS support using Avahi + if test x"$found_zeroconf" != x"yes" ; then + ac_fn_c_check_header_mongrel "$LINENO" "avahi-client/client.h" "ac_cv_header_avahi_client_client_h" "$ac_includes_default" +if test "x$ac_cv_header_avahi_client_client_h" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avahi_client_new in -lavahi-client" >&5 +$as_echo_n "checking for avahi_client_new in -lavahi-client... " >&6; } +if ${ac_cv_lib_avahi_client_avahi_client_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lavahi-client $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char avahi_client_new (); +int +main () +{ +return avahi_client_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_avahi_client_avahi_client_new=yes +else + ac_cv_lib_avahi_client_avahi_client_new=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avahi_client_avahi_client_new" >&5 +$as_echo "$ac_cv_lib_avahi_client_avahi_client_new" >&6; } +if test "x$ac_cv_lib_avahi_client_avahi_client_new" = xyes; then : + +$as_echo "#define USE_ZEROCONF 1" >>confdefs.h + +fi + + +fi + + + + case "$ac_cv_lib_avahi_client_avahi_client_new" in + yes) + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVAHI" >&5 +$as_echo_n "checking for AVAHI... " >&6; } + +if test -n "$AVAHI_CFLAGS"; then + pkg_cv_AVAHI_CFLAGS="$AVAHI_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" avahi-client >= 0.6 \""; } >&5 + ($PKG_CONFIG --exists --print-errors " avahi-client >= 0.6 ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_AVAHI_CFLAGS=`$PKG_CONFIG --cflags " avahi-client >= 0.6 " 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$AVAHI_LIBS"; then + pkg_cv_AVAHI_LIBS="$AVAHI_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" avahi-client >= 0.6 \""; } >&5 + ($PKG_CONFIG --exists --print-errors " avahi-client >= 0.6 ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_AVAHI_LIBS=`$PKG_CONFIG --libs " avahi-client >= 0.6 " 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +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 + AVAHI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors " avahi-client >= 0.6 " 2>&1` + else + AVAHI_PKG_ERRORS=`$PKG_CONFIG --print-errors " avahi-client >= 0.6 " 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$AVAHI_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ( avahi-client >= 0.6 ) were not met: + +$AVAHI_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 AVAHI_CFLAGS +and AVAHI_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}: 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 AVAHI_CFLAGS +and AVAHI_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + AVAHI_CFLAGS=$pkg_cv_AVAHI_CFLAGS + AVAHI_LIBS=$pkg_cv_AVAHI_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVAHI_TPOLL" >&5 +$as_echo_n "checking for AVAHI_TPOLL... " >&6; } + +if test -n "$AVAHI_TPOLL_CFLAGS"; then + pkg_cv_AVAHI_TPOLL_CFLAGS="$AVAHI_TPOLL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" avahi-client >= 0.6.4 \""; } >&5 + ($PKG_CONFIG --exists --print-errors " avahi-client >= 0.6.4 ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_AVAHI_TPOLL_CFLAGS=`$PKG_CONFIG --cflags " avahi-client >= 0.6.4 " 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$AVAHI_TPOLL_LIBS"; then + pkg_cv_AVAHI_TPOLL_LIBS="$AVAHI_TPOLL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" avahi-client >= 0.6.4 \""; } >&5 + ($PKG_CONFIG --exists --print-errors " avahi-client >= 0.6.4 ") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_AVAHI_TPOLL_LIBS=`$PKG_CONFIG --libs " avahi-client >= 0.6.4 " 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +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 + AVAHI_TPOLL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors " avahi-client >= 0.6.4 " 2>&1` + else + AVAHI_TPOLL_PKG_ERRORS=`$PKG_CONFIG --print-errors " avahi-client >= 0.6.4 " 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$AVAHI_TPOLL_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want." >&5 +$as_echo "$as_me: WARNING: This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want." >&2;} +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want." >&5 +$as_echo "$as_me: WARNING: This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want." >&2;} +else + AVAHI_TPOLL_CFLAGS=$pkg_cv_AVAHI_TPOLL_CFLAGS + AVAHI_TPOLL_LIBS=$pkg_cv_AVAHI_TPOLL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_AVAHI_THREADED_POLL 1" >>confdefs.h + +fi + ZEROCONF_LIBS="$AVAHI_LIBS" + ZEROCONF_CFLAGS="$AVAHI_CFLAGS" + +$as_echo "#define HAVE_AVAHI 1" >>confdefs.h + + found_zeroconf=yes + ;; + esac + CPPFLAGS="$savedcppflags" + LDFLAGS="$savedldflags" + fi + fi + + netatalk_cv_zeroconf=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Zerconf support" >&5 +$as_echo_n "checking whether to enable Zerconf support... " >&6; } + if test "x$found_zeroconf" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define USE_ZEROCONF 1" >>confdefs.h + + netatalk_cv_zeroconf=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "x$zeroconf" != "xno" -a "x$zeroconf" != "xtry"; then + as_fn_error $? "Zeroconf installation not found" "$LINENO" 5 + fi + fi + + + ac_new_flags="" + for i in $ZEROCONF_LIBS; do + case $i in + -L/usr/lib|-L/usr/lib/|-L/usr|-L/usr/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + ZEROCONF_LIBS=$ac_new_flags + + + ac_new_flags="" + for i in $ZEROCONF_CFLAGS; do + case $i in + -I/usr/include|-I/usr/include/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + ZEROCONF_CFLAGS=$ac_new_flags + + + + + + + check=maybe + # Check whether --enable-tcp-wrappers was given. +if test "${enable_tcp_wrappers+set}" = set; then : + enableval=$enable_tcp_wrappers; + if test "x$enableval" = "xno"; then + wrapcheck=no + else + wrapcheck=yes + fi + + +fi + + + enable=no + netatalk_cv_tcpwrap=no + if test "x$wrapcheck" != "xno"; then + saved_LIBS=$LIBS + W_LIBS="-lwrap" + LIBS="$LIBS $W_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + int allow_severity = 0; int deny_severity = 0; + +int +main () +{ +hosts_access(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + netatalk_cv_tcpwrap=yes +else + + LIBS=$saved_LIBS + W_LIBS="-lwrap -lnsl" + LIBS="$LIBS $W_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + int allow_severity = 0; int deny_severity = 0; + +int +main () +{ +hosts_access(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + netatalk_cv_tcpwrap=yes +else + netatalk_cv_tcpwrap=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + LIBS=$saved_LIBS + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable the TCP wrappers" >&5 +$as_echo_n "checking whether to enable the TCP wrappers... " >&6; } + if test "x$netatalk_cv_tcpwrap" = "xyes"; then + +$as_echo "#define TCPWRAP 1" >>confdefs.h + + WRAP_LIBS=$W_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + if test "x$wrapcheck" = "xyes"; then + as_fn_error $? "libwrap not found" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + + + + + + netatalk_cv_use_pam=no + +# Check whether --with-pam was given. +if test "${with_pam+set}" = set; then : + withval=$with_pam; + require_pam="yes" + if test "x$withval" = "xno"; then + PAMDIR="NONE" + require_pam="never" + elif test "x$withval" = "xyes"; then + PAMDIR="NONE" + else + PAMDIR="$withval" + fi + +else + PAMDIR="NONE";require_pam="no" + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PAM installation directory" >&5 +$as_echo_n "checking for PAM installation directory... " >&6; } + if test "$host_os" != "solaris"; then + if test "x$PAMDIR" = "xNONE" -a "x$require_pam" != "xnever"; then + pam_paths="/ /usr/ /usr/local/" + for path in $pam_paths; do + if test -d "${path}etc/pam.d"; then + PAMDIR="$path" + break + fi + done + fi + + if test "x$PAMDIR" != "xNONE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (path: ${PAMDIR}etc/pam.d)" >&5 +$as_echo "yes (path: ${PAMDIR}etc/pam.d)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: /etc/pam.conf (solaris)" >&5 +$as_echo "/etc/pam.conf (solaris)" >&6; } + fi + + pam_found="no" + if test "x$require_pam" != "xnever"; then + + savedCFLAGS="$CFLAGS" + savedLDFLAGS="$LDFLAGS" + savedLIBS="$LIBS" + + if test "x$PAMDIR" != "xNONE" -a "x$PAMDIR" != "x/"; then + PAM_CFLAGS="-I${PAMDIR}include" + PAM_LDFLAGS="-L${PAMDIR}lib" + LDFLAGS="$LDFLAGS $PAM_LDFLAGS" + CFLAGS="$CFLAGS $PAM_CFLAGS" + fi + + for ac_header in security/pam_appl.h pam/pam_appl.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + if test x"$ac_cv_header_security_pam_appl_h" = x"no" -a x"$ac_cv_header_pam_pam_appl_h" = x"no"; then + pam_found=no + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_set_item in -lpam" >&5 +$as_echo_n "checking for pam_set_item in -lpam... " >&6; } +if ${ac_cv_lib_pam_pam_set_item+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpam $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pam_set_item (); +int +main () +{ +return pam_set_item (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pam_pam_set_item=yes +else + ac_cv_lib_pam_pam_set_item=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_set_item" >&5 +$as_echo "$ac_cv_lib_pam_pam_set_item" >&6; } +if test "x$ac_cv_lib_pam_pam_set_item" = xyes; then : + + PAM_LIBS="$PAM_LDFLAGS -lpam" + pam_found="yes" + +fi + + fi + CFLAGS="$savedCFLAGS" + LDFLAGS="$savedLDFLAGS" + LIBS="$savedLIBS" + fi + + netatalk_cv_install_pam=yes + if test x"$pam_found" = "xyes" -a "x$PAMDIR" = "xNONE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: PAM support can be compiled, but the install location for the netatalk.pamd file could not be determined. Either install this file by hand or specify the install path." >&5 +$as_echo "$as_me: WARNING: PAM support can be compiled, but the install location for the netatalk.pamd file could not be determined. Either install this file by hand or specify the install path." >&2;} + netatalk_cv_install_pam=no + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for includable common PAM config" >&5 +$as_echo_n "checking for includable common PAM config... " >&6; } + pampath="${PAMDIR}etc/pam.d" + if test -f "$pampath/common-auth" ; then + PAM_DIRECTIVE=include + PAM_AUTH=common-auth + PAM_ACCOUNT=common-account + PAM_PASSWORD=common-password + PAM_SESSION=common-session + elif test -f "$pampath/system-auth" ; then + PAM_DIRECTIVE=include + PAM_AUTH=system-auth + PAM_ACCOUNT=system-auth + PAM_PASSWORD=system-auth + PAM_SESSION=system-auth + elif test -f "$pampath/system" ; then + PAM_DIRECTIVE=include + PAM_AUTH=system + PAM_ACCOUNT=system + PAM_PASSWORD=system + PAM_SESSION=system + elif test -f "$pampath/other" ; then + PAM_DIRECTIVE=include + PAM_AUTH=${PAMDIR}etc/pam.d/other + PAM_ACCOUNT=${PAMDIR}etc/pam.d/other + PAM_PASSWORD=${PAMDIR}etc/pam.d/other + PAM_SESSION=${PAMDIR}etc/pam.d/other + else + PAM_DIRECTIVE=required + PAM_AUTH=pam_unix.so + PAM_ACCOUNT=pam_unix.so + PAM_PASSWORD="pam_unix.so use_authtok" + PAM_SESSION=pam_unix.so + fi + + if test "x$PAM_DIRECTIVE" != "xrequired" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($PAM_DIRECTIVE $PAM_AUTH)" >&5 +$as_echo "yes ($PAM_DIRECTIVE $PAM_AUTH)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (using defaut pam_unix.so)" >&5 +$as_echo "no (using defaut pam_unix.so)" >&6; } + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable PAM support" >&5 +$as_echo_n "checking whether to enable PAM support... " >&6; } + if test "x$pam_found" = "xno"; then + netatalk_cv_install_pam=no + if test "x$require_pam" = "xyes"; then + as_fn_error $? "PAM support missing" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + : + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : + use_pam_so=yes + compile_pam=yes + netatalk_cv_use_pam=yes + +$as_echo "#define USE_PAM 1" >>confdefs.h + + fi + + +# Check whether --with-pam-confdir was given. +if test "${with_pam_confdir+set}" = set; then : + withval=$with_pam_confdir; ac_cv_pamdir=$withval +else + ac_cv_pamdir='${sysconfdir}/pam.d' + +fi + + + PAMDIR="$ac_cv_pamdir" + + + ac_new_flags="" + for i in $PAM_LIBS; do + case $i in + -L/usr/lib|-L/usr/lib/|-L/usr|-L/usr/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + PAM_LIBS=$ac_new_flags + + + ac_new_flags="" + for i in $PAM_CFLAGS; do + case $i in + -I/usr/include|-I/usr/include/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + PAM_CFLAGS=$ac_new_flags + + + + + + + + + + + + +netatalk_cv_use_shadowpw=no + +# Check whether --with-shadow was given. +if test "${with_shadow+set}" = set; then : + withval=$with_shadow; netatalk_cv_use_shadowpw="$withval" +else + netatalk_cv_use_shadowpw=auto + +fi + + +if test "x$netatalk_cv_use_shadowpw" != "xno"; then + ac_fn_c_check_header_mongrel "$LINENO" "shadow.h" "ac_cv_header_shadow_h" "$ac_includes_default" +if test "x$ac_cv_header_shadow_h" = xyes; then : + +fi + + + if test x"$ac_cv_header_shadow_h" = x"yes"; then + netatalk_cv_use_shadowpw=yes + +$as_echo "#define SHADOWPW 1" >>confdefs.h + + else + if test "x$shadowpw" = "xyes"; then + as_fn_error $? "shadow support not available" "$LINENO" 5 + else + netatalk_cv_use_shadowpw=no + fi + fi +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether shadow support should be enabled" >&5 +$as_echo_n "checking whether shadow support should be enabled... " >&6; } +if test "x$netatalk_cv_use_shadowpw" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +netatalk_cv_use_shellcheck=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether checking for a valid shell should be enabled" >&5 +$as_echo_n "checking whether checking for a valid shell should be enabled... " >&6; } +# Check whether --enable-shell-check was given. +if test "${enable_shell_check+set}" = set; then : + enableval=$enable_shell_check; + if test "$enableval" = "no"; then + +$as_echo "#define DISABLE_SHELLCHECK 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + netatalk_cv_use_shellcheck=no + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +fi + + + + + +# Check whether --with-init-style was given. +if test "${with_init_style+set}" = set; then : + withval=$with_init_style; init_style="$withval" +else + init_style=none + +fi + + case "$init_style" in + "redhat") + as_fn_error $? "--with-init-style=redhat is obsoleted. Use redhat-sysv or redhat-systemd." "$LINENO" 5 + ;; + "redhat-sysv") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling redhat-style sysv initscript support" >&5 +$as_echo "enabling redhat-style sysv initscript support" >&6; } + ac_cv_init_dir="/etc/rc.d/init.d" + ;; + "redhat-systemd") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling redhat-style systemd support" >&5 +$as_echo "enabling redhat-style systemd support" >&6; } + ac_cv_init_dir="/usr/lib/systemd/system" + ;; + "suse") + as_fn_error $? "--with-init-style=suse is obsoleted. Use suse-sysv or suse-systemd." "$LINENO" 5 + ;; + "suse-sysv") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling suse-style sysv initscript support" >&5 +$as_echo "enabling suse-style sysv initscript support" >&6; } + ac_cv_init_dir="/etc/init.d" + ;; + "suse-systemd") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling suse-style systemd support (>=openSUSE12.1)" >&5 +$as_echo "enabling suse-style systemd support (>=openSUSE12.1)" >&6; } + ac_cv_init_dir="/usr/lib/systemd/system" + ;; + "gentoo") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling gentoo-style initscript support" >&5 +$as_echo "enabling gentoo-style initscript support" >&6; } + ac_cv_init_dir="/etc/init.d" + ;; + "netbsd") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling netbsd-style initscript support" >&5 +$as_echo "enabling netbsd-style initscript support" >&6; } + ac_cv_init_dir="/etc/rc.d" + ;; + "debian") + as_fn_error $? "--with-init-style=debian is obsoleted. Use debian-sysv or debian-systemd." "$LINENO" 5 + ;; + "debian-sysv") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling debian-style sysv initscript support" >&5 +$as_echo "enabling debian-style sysv initscript support" >&6; } + ac_cv_init_dir="/etc/init.d" + ;; + "debian-systemd") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling debian-style systemd support" >&5 +$as_echo "enabling debian-style systemd support" >&6; } + ac_cv_init_dir="/lib/systemd/system" + ;; + "solaris") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling solaris-style SMF support" >&5 +$as_echo "enabling solaris-style SMF support" >&6; } + ac_cv_init_dir="/lib/svc/manifest/network/" + ;; + "systemd") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling general systemd support" >&5 +$as_echo "enabling general systemd support" >&6; } + ac_cv_init_dir="/usr/lib/systemd/system" + ;; + "none") + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabling init-style support" >&5 +$as_echo "disabling init-style support" >&6; } + ac_cv_init_dir="none" + ;; + *) + as_fn_error $? "illegal init-style" "$LINENO" 5 + ;; + esac + if test x$init_style = xnetbsd; then + USE_NETBSD_TRUE= + USE_NETBSD_FALSE='#' +else + USE_NETBSD_TRUE='#' + USE_NETBSD_FALSE= +fi + + if test x$init_style = xredhat-sysv; then + USE_REDHAT_SYSV_TRUE= + USE_REDHAT_SYSV_FALSE='#' +else + USE_REDHAT_SYSV_TRUE='#' + USE_REDHAT_SYSV_FALSE= +fi + + if test x$init_style = xsuse-sysv; then + USE_SUSE_SYSV_TRUE= + USE_SUSE_SYSV_FALSE='#' +else + USE_SUSE_SYSV_TRUE='#' + USE_SUSE_SYSV_FALSE= +fi + + if test x$init_style = xsolaris; then + USE_SOLARIS_TRUE= + USE_SOLARIS_FALSE='#' +else + USE_SOLARIS_TRUE='#' + USE_SOLARIS_FALSE= +fi + + if test x$init_style = xgentoo; then + USE_GENTOO_TRUE= + USE_GENTOO_FALSE='#' +else + USE_GENTOO_TRUE='#' + USE_GENTOO_FALSE= +fi + + if test x$init_style = xdebian-sysv; then + USE_DEBIAN_SYSV_TRUE= + USE_DEBIAN_SYSV_FALSE='#' +else + USE_DEBIAN_SYSV_TRUE='#' + USE_DEBIAN_SYSV_FALSE= +fi + + if test x$init_style = xsystemd || test x$init_style = xredhat-systemd || test x$init_style = xsuse-systemd; then + USE_SYSTEMD_TRUE= + USE_SYSTEMD_FALSE='#' +else + USE_SYSTEMD_TRUE='#' + USE_SYSTEMD_FALSE= +fi + + if test x$init_style = xdebian-systemd; then + USE_DEBIAN_SYSTEMD_TRUE= + USE_DEBIAN_SYSTEMD_FALSE='#' +else + USE_DEBIAN_SYSTEMD_TRUE='#' + USE_DEBIAN_SYSTEMD_FALSE= +fi + + if test x$init_style = xnone; then + USE_UNDEF_TRUE= + USE_UNDEF_FALSE='#' +else + USE_UNDEF_TRUE='#' + USE_UNDEF_FALSE= +fi + + + +# Check whether --with-init-dir was given. +if test "${with_init_dir+set}" = set; then : + withval=$with_init_dir; ac_cv_init_dir="$withval" +else + ac_cv_init_dir="$ac_cv_init_dir" + +fi + + INIT_DIR="$ac_cv_init_dir" + INIT_DIR="$ac_cv_init_dir" + + + + +# Check whether --with-uams-path was given. +if test "${with_uams_path+set}" = set; then : + withval=$with_uams_path; uams_path="$withval/" +else + uams_path="$libdir/netatalk/" +fi + + + +# Check whether --with-libgcrypt-dir was given. +if test "${with_libgcrypt_dir+set}" = set; then : + withval=$with_libgcrypt_dir; libgcrypt_config_prefix="$withval" +else + libgcrypt_config_prefix="" +fi + + if test x$libgcrypt_config_prefix != x ; then + if test x${LIBGCRYPT_CONFIG+set} != xset ; then + LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config + fi + fi + + ok=no + +if test x$libgcrypt_config_prefix != xno ; then + + # Extract the first word of "libgcrypt-config", so it can be a program name with args. +set dummy libgcrypt-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $LIBGCRYPT_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_LIBGCRYPT_CONFIG" && ac_cv_path_LIBGCRYPT_CONFIG="no" + ;; +esac +fi +LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG +if test -n "$LIBGCRYPT_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5 +$as_echo "$LIBGCRYPT_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + tmp=1:1.2.3 + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libgcrypt_api=0 + min_libgcrypt_version="$tmp" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5 +$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; } + if test "$LIBGCRYPT_CONFIG" != "no" ; then + req_major=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` + req_minor=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` + req_micro=`echo $min_libgcrypt_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` + major=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` + minor=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` + micro=`echo $libgcrypt_config_version | \ + sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5 +$as_echo "yes ($libgcrypt_config_version)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi +fi + + if test $ok = yes; then + # If we have a recent libgcrypt, we should also check that the + # API is compatible + if test "$req_libgcrypt_api" -gt 0 ; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking libgcrypt API version" >&5 +$as_echo_n "checking libgcrypt API version... " >&6; } + if test "$req_libgcrypt_api" -eq "$tmp" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5 +$as_echo "okay" >&6; } + else + ok=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5 +$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; } + fi + fi + fi + fi + if test $ok = yes; then + # Opensolaris 11/08 provided libgcrypt doesn't have CAST5, + # so we better check the general case + { $as_echo "$as_me:${as_lineno-$LINENO}: checking libgcrypt hast CAST5 API" >&5 +$as_echo_n "checking libgcrypt hast CAST5 API... " >&6; } + cast=`$LIBGCRYPT_CONFIG --algorithms 2>/dev/null | grep cast5 | sed 's/\(.*\)\(cast5\)\(.*\)/\2/'` + if test x$cast = xcast5 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + echo "*** Detected libgcryt without CAST5 ***" + echo "*** Please install/build another one and point to it with ***" + echo "*** --with-libgcrypt-dir= ***" + ok=no + fi + fi + + if test $ok = yes; then + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` + neta_cv_compile_dhx2=yes + neta_cv_have_libgcrypt=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling DHX2 UAM" >&5 +$as_echo "$as_me: Enabling DHX2 UAM" >&6;} + +$as_echo "#define HAVE_LIBGCRYPT 1" >>confdefs.h + + +$as_echo "#define UAM_DHX2 1" >>confdefs.h + + : + else + LIBGCRYPT_CFLAGS="" + LIBGCRYPT_LIBS="" + : + fi + + + + + + +# Check whether --with-ssl-dir was given. +if test "${with_ssl_dir+set}" = set; then : + withval=$with_ssl_dir; + if test "x$withval" = "xno"; then + tryssl=no + elif test "x$withval" = "xyes"; then + tryssl=yes + tryssldir= + else + tryssl=yes + tryssldir="$withval" + fi + +else + tryssl=yes + +fi + + + SSL_CFLAGS="" + SSL_LIBS="" + saved_LIBS=$LIBS + saved_CFLAGS=$CFLAGS + neta_cv_have_openssl=no + + [ -n "$atalk_libname" ] || as_fn_error $? "internal error, atalk_libname undefined" "$LINENO" 5 + + if test "$tryssl" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5 +$as_echo_n "checking for SSL... " >&6; } + for ssldir in "" $tryssldir /usr /usr/local/openssl /usr/$atalk_libname/openssl /usr/local/ssl /usr/$atalk_libname/ssl /usr/local /usr/pkg /opt /opt/openssl /usr/local/ssl ; do + if test -f "$ssldir/include/openssl/cast.h" ; then + SSL_CFLAGS="$SSL_CFLAGS -I$ssldir/include -I$ssldir/include/openssl" + SSL_LIBS="$SSL_LIBS -L$ssldir/$atalk_libname -L$ssldir -lcrypto" + if test "x$need_dash_r" = "xyes"; then + SSL_LIBS="$SSL_LIBS -R$ssldir/$atalk_libname -R$ssldir" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssldir (enabling RANDNUM and DHX support)" >&5 +$as_echo "$ssldir (enabling RANDNUM and DHX support)" >&6; } + CFLAGS="$CFLAGS $SSL_CFLAGS" + LIBS="$LIBS $SSL_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lcrypto" >&5 +$as_echo_n "checking for main in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypto_main=yes +else + ac_cv_lib_crypto_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_main" >&5 +$as_echo "$ac_cv_lib_crypto_main" >&6; } +if test "x$ac_cv_lib_crypto_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCRYPTO 1 +_ACEOF + + LIBS="-lcrypto $LIBS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldes" >&5 +$as_echo_n "checking for main in -ldes... " >&6; } +if ${ac_cv_lib_des_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldes $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_des_main=yes +else + ac_cv_lib_des_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_des_main" >&5 +$as_echo "$ac_cv_lib_des_main" >&6; } +if test "x$ac_cv_lib_des_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDES 1 +_ACEOF + + LIBS="-ldes $LIBS" + +fi + + + +$as_echo "#define OPENSSL_DHX 1" >>confdefs.h + + +$as_echo "#define UAM_DHX 1" >>confdefs.h + + neta_cv_have_openssl=yes + neta_cv_compile_dhx=yes + CFLAGS=$saved_CFLAGS + LIBS=$saved_LIBS + break + fi + done + if test "x$neta_cv_have_openssl" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + + ac_new_flags="" + for i in $SSL_CFLAGS; do + case $i in + -I/usr/include|-I/usr/include/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + SSL_CFLAGS=$ac_new_flags + + + ac_new_flags="" + for i in $SSL_LIBS; do + case $i in + -L/usr/lib|-L/usr/lib/|-L/usr|-L/usr/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + SSL_LIBS=$ac_new_flags + + + + LIBS=$saved_LIBS + + + +if test "x$bdb_required" = "xyes"; then + trybdbdir="" + dobdbsearch=yes + bdb_search_dirs="/usr/local /usr" + search_subdirs="/ /db5 /db5.1 /db51 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4" + + bdbfound=no + savedcflags="$CFLAGS" + savedldflags="$LDFLAGS" + savedcppflags="$CPPFLAGS" + savedlibs="$LIBS" + saved_shlibpath_var=$shlibpath_var + + DB_MAJOR_REQ=4 + DB_MINOR_REQ=6 + DB_PATCH_REQ=0 + + [ -n "$atalk_libname" ] || as_fn_error $? "internal error, atalk_libname undefined" "$LINENO" 5 + saved_atalk_libname=$atalk_libname + + +cat >>confdefs.h <<_ACEOF +#define DB_MAJOR_REQ ${DB_MAJOR_REQ} +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define DB_MINOR_REQ ${DB_MINOR_REQ} +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define DB_PATCH_REQ ${DB_PATCH_REQ} +_ACEOF + + + +# Check whether --with-bdb was given. +if test "${with_bdb+set}" = set; then : + withval=$with_bdb; if test "x$withval" = "xno"; then + dobdbsearch=no + elif test "x$withval" = "xyes"; then + dobdbsearch=yes + else + bdb_search_dirs="$withval" + fi + +fi + + + if test "x$dobdbsearch" = "xyes"; then + for bdbdir in $bdb_search_dirs; do + if test $bdbfound = "yes"; then + break; + fi + for subdir in ${search_subdirs}; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB headers in ${bdbdir}/include${subdir}" >&5 +$as_echo_n "checking for Berkeley DB headers in ${bdbdir}/include${subdir}... " >&6; } + if test -f "${bdbdir}/include${subdir}/db.h" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking ${bdbdir}/include${subdir}/db.h version >= ${DB_MAJOR_REQ}.${DB_MINOR_REQ}.${DB_PATCH_REQ}" >&5 +$as_echo_n "checking ${bdbdir}/include${subdir}/db.h version >= ${DB_MAJOR_REQ}.${DB_MINOR_REQ}.${DB_PATCH_REQ}... " >&6; } + + atalk_cv_bdb_MAJOR=`grep DB_VERSION_MAJOR "${bdbdir}/include${subdir}/db.h" | cut -f 3` + atalk_cv_bdb_MINOR=`grep DB_VERSION_MINOR "${bdbdir}/include${subdir}/db.h" | cut -f 3` + + if test $atalk_cv_bdb_MAJOR -gt $DB_MAJOR_REQ ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + atalk_cv_bdbheader=yes + elif test $DB_MAJOR_REQ -gt $atalk_cv_bdb_MAJOR ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + atalk_cv_bdbheader=no + elif test $DB_MINOR_REQ -gt $atalk_cv_bdb_MINOR ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + atalk_cv_bdbheader=no + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + atalk_cv_bdbheader=yes + fi + + + if test ${atalk_cv_bdbheader} != "no"; then + bdblibdir="${bdbdir}/${atalk_libname}" + bdbbindir="${bdbdir}/bin" + + CPPFLAGS="-I${bdbdir}/include${subdir} $CPPFLAGS" + LDFLAGS="-L$bdblibdir $LDFLAGS" + + eval export $shlibpath_var=$bdblibdir + + atalk_cv_bdb_version=no + maj=$atalk_cv_bdb_MAJOR + min=$atalk_cv_bdb_MINOR + atalk_cv_bdb_try_libs="db$maj$min db$maj.$min db-$maj$min db-$maj.$min db$maj-$maj.$min db" + + for lib in $atalk_cv_bdb_try_libs ; do + LIBS="-l$lib $savedlibs" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Berkeley DB library (-l$lib)" >&5 +$as_echo_n "checking Berkeley DB library (-l$lib)... " >&6; } + if test "$cross_compiling" = yes; then : + + bdblibs=`ls $bdblibdir/lib$lib.* 2>/dev/null` + for bdblib in $bdblibs ; do + echo "Testing for lib file $bdblib" >&5 + if test -f "$bdblib" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (cross-compiling)" >&5 +$as_echo "yes (cross-compiling)" >&6; } + atalk_cv_bdb_version="yes" + atalk_cv_lib_db="-l$lib" + break + fi + done + if test "x$atalk_cv_bdb_version" = "xyes" ; then + break + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (cross-compiling)" >&5 +$as_echo "no (cross-compiling)" >&6; } + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + int main(void) { + int major, minor, patch; + char *version_str; + version_str = db_version(&major, &minor, &patch); + if ((major*100 + minor*10 + patch) < (DB_MAJOR_REQ*100 + DB_MINOR_REQ*10 + DB_PATCH_REQ)) { + printf("linking wrong library version (%d.%d.%d), ",major, minor, patch); + return (2); + } + if ( major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR || patch != DB_VERSION_PATCH) { + printf("header/library version mismatch (%d.%d.%d/%d.%d.%d), ", + DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch); + return (3); + } + printf("%d.%d.%d ... ",major, minor, patch); + return (0); + } + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + atalk_cv_bdb_version="yes" + atalk_cv_lib_db="-l$lib" + break + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + done + LIBS="$savedlibs" + + eval export $shlibpath_var=$saved_shlibpath_var + + if test x"${atalk_cv_bdb_version}" = x"yes"; then + BDB_CFLAGS="-I${bdbdir}/include${subdir}" + BDB_LIBS="-L${bdblibdir} ${atalk_cv_lib_db}" + if test x"$need_dash_r" = x"yes"; then + BDB_LIBS="$BDB_LIBS -R${bdblibdir}" + fi + BDB_BIN="$bdbbindir" + BDB_PATH="$bdbdir" + bdbfound=yes + break; + fi + + if test x"$atalk_libname" != x"lib" ; then + bdblibdir="${bdbdir}/lib" + bdbbindir="${bdbdir}/bin" + + CPPFLAGS="-I${bdbdir}/include${subdir} $CPPFLAGS" + LDFLAGS="-L$bdblibdir $LDFLAGS" + + eval export $shlibpath_var=$bdblibdir + + atalk_cv_bdb_version=no + maj=$atalk_cv_bdb_MAJOR + min=$atalk_cv_bdb_MINOR + atalk_cv_bdb_try_libs="db$maj$min db$maj.$min db-$maj$min db-$maj.$min db$maj-$maj.$min db" + + for lib in $atalk_cv_bdb_try_libs ; do + LIBS="-l$lib $savedlibs" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Berkeley DB library (-l$lib)" >&5 +$as_echo_n "checking Berkeley DB library (-l$lib)... " >&6; } + if test "$cross_compiling" = yes; then : + + bdblibs=`ls $bdblibdir/lib$lib.* 2>/dev/null` + for bdblib in $bdblibs ; do + echo "Testing for lib file $bdblib" >&5 + if test -f "$bdblib" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (cross-compiling)" >&5 +$as_echo "yes (cross-compiling)" >&6; } + atalk_cv_bdb_version="yes" + atalk_cv_lib_db="-l$lib" + break + fi + done + if test "x$atalk_cv_bdb_version" = "xyes" ; then + break + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (cross-compiling)" >&5 +$as_echo "no (cross-compiling)" >&6; } + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + int main(void) { + int major, minor, patch; + char *version_str; + version_str = db_version(&major, &minor, &patch); + if ((major*100 + minor*10 + patch) < (DB_MAJOR_REQ*100 + DB_MINOR_REQ*10 + DB_PATCH_REQ)) { + printf("linking wrong library version (%d.%d.%d), ",major, minor, patch); + return (2); + } + if ( major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR || patch != DB_VERSION_PATCH) { + printf("header/library version mismatch (%d.%d.%d/%d.%d.%d), ", + DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch); + return (3); + } + printf("%d.%d.%d ... ",major, minor, patch); + return (0); + } + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + atalk_cv_bdb_version="yes" + atalk_cv_lib_db="-l$lib" + break + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + done + LIBS="$savedlibs" + + eval export $shlibpath_var=$saved_shlibpath_var + + if test x"${atalk_cv_bdb_version}" = x"yes"; then + BDB_CFLAGS="-I${bdbdir}/include${subdir}" + BDB_LIBS="-L${bdblibdir} ${atalk_cv_lib_db}" + if test x"$need_dash_r" = x"yes"; then + BDB_LIBS="$BDB_LIBS -R${bdblibdir}" + fi + BDB_BIN="$bdbbindir" + BDB_PATH="$bdbdir" + bdbfound=yes + break; + fi + fi + fi + CFLAGS="$savedcflags" + LDFLAGS="$savedldflags" + CPPFLAGS="$savedcppflags" + LIBS="$savedlibs" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + done + done + fi + + CFLAGS="$savedcflags" + LDFLAGS="$savedldflags" + CPPFLAGS="$savedcppflags" + LIBS="$savedlibs" + atalk_libname=$saved_atalk_libname + + if test "x$bdbfound" = "xyes"; then + : + else + : + as_fn_error $? "Berkeley DB library required but not found!" "$LINENO" 5 + fi + + + ac_new_flags="" + for i in $BDB_CFLAGS; do + case $i in + -I/usr/include|-I/usr/include/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + BDB_CFLAGS=$ac_new_flags + + + ac_new_flags="" + for i in $BDB_LIBS; do + case $i in + -L/usr/lib|-L/usr/lib/|-L/usr|-L/usr/) ;; + *) ac_new_flags="$ac_new_flags $i" ;; + esac + done + BDB_LIBS=$ac_new_flags + + + + + +fi + + + + + saveLIBS=$LIBS + LIBS="" + CRYPT_LIBS="" + + for ac_header in crypt.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "crypt.h" "ac_cv_header_crypt_h" "$ac_includes_default" +if test "x$ac_cv_header_crypt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CRYPT_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lcrypt" >&5 +$as_echo_n "checking for main in -lcrypt... " >&6; } +if ${ac_cv_lib_crypt_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypt_main=yes +else + ac_cv_lib_crypt_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_main" >&5 +$as_echo "$ac_cv_lib_crypt_main" >&6; } +if test "x$ac_cv_lib_crypt_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCRYPT 1 +_ACEOF + + LIBS="-lcrypt $LIBS" + +fi + + + CRYPT_LIBS=$LIBS + LIBS=$saveLIBS + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PGP UAM should be build" >&5 +$as_echo_n "checking whether the PGP UAM should be build... " >&6; } +# Check whether --enable-pgp-uam was given. +if test "${enable_pgp_uam+set}" = set; then : + enableval=$enable_pgp_uam; + if test "$enableval" = "yes"; then + if test "x$neta_cv_have_openssl" = "xyes"; then + +$as_echo "#define UAM_PGP 1" >>confdefs.h + + compile_pgp=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +fi + + + + +netatalk_cv_build_krb5_uam=no +# Check whether --enable-krbV-uam was given. +if test "${enable_krbV_uam+set}" = set; then : + enableval=$enable_krbV_uam; + if test x"$enableval" = x"yes"; then + + FOUND_GSSAPI=no + GSSAPI_LIBS="" + GSSAPI_CFLAGS="" + GSSAPI_LDFLAGS="" + save_CFLAGS="$CFLAGS" + save_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" + + +# Check whether --with-gssapi was given. +if test "${with_gssapi+set}" = set; then : + withval=$with_gssapi; compilegssapi=$withval +else + compilegssapi=auto + +fi + + + if test x"$compilegssapi" != x"no" ; then + if test "x$compilegssapi" != "xyes" -a "x$compilegssapi" != "xauto" ; then + export CFLAGS="-I$withval/include" + export LDFLAGS="-L$withval/${atalk_libname}" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GSSAPI support in $compilegssapi" >&5 +$as_echo "$as_me: checking for GSSAPI support in $compilegssapi" >&6;} + fi + + if test x"$compilegssapi" = x"yes" -o x"$compilegssapi" = x"auto" ; then + # check for krb5-config from recent MIT and Heimdal kerberos 5 + # Extract the first word of "krb5-config", so it can be a program name with args. +set dummy krb5-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_KRB5_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $KRB5_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_KRB5_CONFIG="$KRB5_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_KRB5_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +KRB5_CONFIG=$ac_cv_path_KRB5_CONFIG +if test -n "$KRB5_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KRB5_CONFIG" >&5 +$as_echo "$KRB5_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working krb5-config that takes --libs gssapi" >&5 +$as_echo_n "checking for working krb5-config that takes --libs gssapi... " >&6; } + + if test -x "$KRB5_CONFIG" ; then + TEMP="`$KRB5_CONFIG --libs gssapi`" + if test $? -eq 0 ; then + GSSAPI_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`" + GSSAPI_LIBS="$TEMP" + FOUND_GSSAPI=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no. Fallback to previous krb5 detection strategy" >&5 +$as_echo "no. Fallback to previous krb5 detection strategy" >&6; } + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no. Fallback to previous krb5 detection strategy" >&5 +$as_echo "no. Fallback to previous krb5 detection strategy" >&6; } + fi + fi + fi + + if test x"$compilegssapi" != x"no" -a x"$FOUND_GSSAPI" = x"no" ; then + # check for gssapi headers + gss_headers_found=no + for ac_header in gssapi.h gssapi/gssapi_generic.h gssapi/gssapi.h gssapi/gssapi_krb5.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + gss_headers_found=yes +fi + +done + + if test x"$gss_headers_found" = x"no" ; then + as_fn_error $? "GSSAPI installation not found, headers missing" "$LINENO" 5 + fi + # check for libs + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gss_display_status" >&5 +$as_echo_n "checking for library containing gss_display_status... " >&6; } +if ${ac_cv_search_gss_display_status+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gss_display_status (); +int +main () +{ +return gss_display_status (); + ; + return 0; +} +_ACEOF +for ac_lib in '' gss gssapi gssapi_krb5; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_gss_display_status=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gss_display_status+:} false; then : + break +fi +done +if ${ac_cv_search_gss_display_status+:} false; then : + +else + ac_cv_search_gss_display_status=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gss_display_status" >&5 +$as_echo "$ac_cv_search_gss_display_status" >&6; } +ac_res=$ac_cv_search_gss_display_status +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + if test x"$ac_cv_search_gss_display_status" = x"no" ; then + as_fn_error $? "GSSAPI installation not found, library missing" "$LINENO" 5 + fi + GSSAPI_CFLAGS="$CFLAGS" + GSSAPI_LIBS="$LIBS" + FOUND_GSSAPI=yes + fi + + if test x"$FOUND_GSSAPI" = x"yes" ; then + # check for functions + export CFLAGS="$GSSAPI_CFLAGS" + export LIBS="$GSSAPI_LIBS" + ac_fn_c_check_func "$LINENO" "gss_acquire_cred" "ac_cv_func_gss_acquire_cred" +if test "x$ac_cv_func_gss_acquire_cred" = xyes; then : + +else + as_fn_error $? "GSSAPI: required function gss_acquire_cred missing" "$LINENO" 5 +fi + + + # Heimdal/MIT compatibility fix + if test "$ac_cv_header_gssapi_h" = "yes" ; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "GSS_C_NT_HOSTBASED_SERVICE" >/dev/null 2>&1; then : + +$as_echo "#define HAVE_GSS_C_NT_HOSTBASED_SERVICE 1" >>confdefs.h + + +fi +rm -f conftest* + + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "GSS_C_NT_HOSTBASED_SERVICE" >/dev/null 2>&1; then : + +$as_echo "#define HAVE_GSS_C_NT_HOSTBASED_SERVICE 1" >>confdefs.h + + +fi +rm -f conftest* + + fi + + +$as_echo "#define HAVE_GSSAPI 1" >>confdefs.h + + if test x"$ac_cv_func_gss_acquire_cred" = x"yes" ; then + + netatalk_cv_build_krb5_uam=yes + + else + + as_fn_error $? "need GSSAPI to build Kerberos V UAM" "$LINENO" 5 + + fi + fi + + + + + + export LIBS="$save_LIBS" + export CFLAGS="$save_CFLAGS" + export LDFLAGS="$save_LDFLAGS" + + fi + + + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Kerberos V UAM should be build" >&5 +$as_echo_n "checking whether Kerberos V UAM should be build... " >&6; } +if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then + USE_GSSAPI_TRUE= + USE_GSSAPI_FALSE='#' +else + USE_GSSAPI_TRUE='#' + USE_GSSAPI_FALSE= +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Kerberos 5 (necessary for GetSrvrInfo:DirectoryNames support)" >&5 +$as_echo_n "checking for Kerberos 5 (necessary for GetSrvrInfo:DirectoryNames support)... " >&6; } + +# Check whether --with-kerberos was given. +if test "${with_kerberos+set}" = set; then : + withval=$with_kerberos; +else + with_kerberos=auto +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_kerberos" >&5 +$as_echo "$with_kerberos" >&6; } + +if test x"$with_kerberos" != x"no"; then + have_krb5_header="no" + for ac_header in krb5/krb5.h krb5.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + have_krb5_header="yes"; break +fi + +done + + if test x"$have_krb5_header" = x"no" && test x"$with_kerberos" != x"auto"; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "--with-kerberos was given, but no headers found +See \`config.log' for more details" "$LINENO" 5; } + fi + + # Extract the first word of "krb5-config", so it can be a program name with args. +set dummy krb5-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_KRB5_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $KRB5_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_KRB5_CONFIG="$KRB5_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_KRB5_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +KRB5_CONFIG=$ac_cv_path_KRB5_CONFIG +if test -n "$KRB5_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KRB5_CONFIG" >&5 +$as_echo "$KRB5_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for krb5-config" >&5 +$as_echo_n "checking for krb5-config... " >&6; } + if test -x "$KRB5_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KRB5_CONFIG" >&5 +$as_echo "$KRB5_CONFIG" >&6; } + KRB5_CFLAGS="`$KRB5_CONFIG --cflags krb5`" + KRB5_LIBS="`$KRB5_CONFIG --libs krb5`" + + + with_kerberos="yes" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + if test x"$with_kerberos" != x"auto"; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "--with-kerberos was given, but krb5-config could not be found +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi + +if test x"$with_kerberos" = x"yes"; then + +$as_echo "#define HAVE_KERBEROS 1" >>confdefs.h + +fi + +save_CFLAGS="$CFLAGS" +save_LIBS="$LIBS" +CFLAGS="$KRB5_CFLAGS" +LIBS="$KRB5_LIBS" +for ac_func in krb5_free_unparsed_name krb5_free_error_message krb5_free_keytab_entry_contents krb5_kt_free_entry +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +CFLAGS="$save_CFLAGS" +LIBS="$save_LIBS" + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether configuration files should be overwritten" >&5 +$as_echo_n "checking whether configuration files should be overwritten... " >&6; } +# Check whether --enable-overwrite was given. +if test "${enable_overwrite+set}" = set; then : + enableval=$enable_overwrite; OVERWRITE_CONFIG="${enable_overwrite}" +else + OVERWRITE_CONFIG="no" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OVERWRITE_CONFIG" >&5 +$as_echo "$OVERWRITE_CONFIG" >&6; } + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LDAP (necessary for client-side ACL visibility)" >&5 +$as_echo_n "checking for LDAP (necessary for client-side ACL visibility)... " >&6; } + +# Check whether --with-ldap was given. +if test "${with_ldap+set}" = set; then : + withval=$with_ldap; netatalk_cv_ldap=$withval +else + netatalk_cv_ldap=auto + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_ldap" >&5 +$as_echo "$netatalk_cv_ldap" >&6; } + +save_CFLAGS="$CFLAGS" +save_LDFLAGS="$LDFLAGS" +save_LIBS="$LIBS" +CFLAGS="" +LDFLAGS="" +LIBS="" +LDAP_CFLAGS="" +LDAP_LDFLAGS="" +LDAP_LIBS="" + +if test x"$netatalk_cv_ldap" != x"no" ; then + if test x"$netatalk_cv_ldap" != x"yes" -a x"$netatalk_cv_ldap" != x"auto"; then + CFLAGS="-I$netatalk_cv_ldap/include" + LDFLAGS="-L$netatalk_cv_ldap/lib" + fi + ac_fn_c_check_header_mongrel "$LINENO" "ldap.h" "ac_cv_header_ldap_h" "$ac_includes_default" +if test "x$ac_cv_header_ldap_h" = xyes; then : + netatalk_cv_ldap=yes +else + if test x"$netatalk_cv_ldap" = x"yes" ; then + as_fn_error $? "Missing LDAP headers" "$LINENO" 5 + fi + netatalk_cv_ldap=no + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_init in -lldap" >&5 +$as_echo_n "checking for ldap_init in -lldap... " >&6; } +if ${ac_cv_lib_ldap_ldap_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_init (); +int +main () +{ +return ldap_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldap_ldap_init=yes +else + ac_cv_lib_ldap_ldap_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_init" >&5 +$as_echo "$ac_cv_lib_ldap_ldap_init" >&6; } +if test "x$ac_cv_lib_ldap_ldap_init" = xyes; then : + netatalk_cv_ldap=yes +else + if test x"$netatalk_cv_ldap" = x"yes" ; then + as_fn_error $? "Missing LDAP library" "$LINENO" 5 + fi + netatalk_cv_ldap=no + +fi + +fi + +if test x"$netatalk_cv_ldap" = x"yes"; then + LDAP_CFLAGS="$CFLAGS" + LDAP_LDFLAGS="$LDFLAGS" + LDAP_LIBS="-lldap" + +$as_echo "#define HAVE_LDAP 1" >>confdefs.h + +fi + + + + +CFLAGS="$save_CFLAGS" +LDFLAGS="$save_LDFLAGS" +LIBS="$save_LIBS" + + + +ac_cv_have_acls=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support ACLs" >&5 +$as_echo_n "checking whether to support ACLs... " >&6; } + +# Check whether --with-acls was given. +if test "${with_acls+set}" = set; then : + withval=$with_acls; case "$withval" in + yes|no) + with_acl_support="$withval" + ;; + *) + with_acl_support=auto + ;; + esac +else + with_acl_support=auto +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_acl_support" >&5 +$as_echo "$with_acl_support" >&6; } + +if test x"$with_acl_support" = x"no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling ACL support" >&5 +$as_echo "Disabling ACL support" >&6; } +fi + +# Platform specific checks +if test x"$with_acl_support" != x"no" ; then + case "$host_os" in + *solaris*) + { $as_echo "$as_me:${as_lineno-$LINENO}: Using solaris ACLs" >&5 +$as_echo "$as_me: Using solaris ACLs" >&6;} + +$as_echo "#define HAVE_SOLARIS_ACLS 1" >>confdefs.h + + +$as_echo "#define HAVE_NFSV4_ACLS 1" >>confdefs.h + + ACL_LIBS="$ACL_LIBS -lsec" + ac_cv_have_acls=yes + ;; + *freebsd*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libsunacl is available" >&5 +$as_echo "$as_me: checking whether libsunacl is available" >&6;} + sunacl_include_path="/usr/local/include" + sunacl_lib_path="/usr/local/lib" + + save_CPPFLAGS=$CPPFLAGS + save_LDFLAGS=$LDFLAGS + save_LIBS=$LIBS + + CPPFLAGS="-I$sunacl_include_path $CPPFLAGS" + ac_fn_c_check_header_mongrel "$LINENO" "sunacl.h" "ac_cv_header_sunacl_h" "$ac_includes_default" +if test "x$ac_cv_header_sunacl_h" = xyes; then : + +fi + + + + LDFLAGS="-L$sunacl_lib_path $LDFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl in -lsunacl" >&5 +$as_echo_n "checking for acl in -lsunacl... " >&6; } +if ${ac_cv_lib_sunacl_acl+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsunacl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char acl (); +int +main () +{ +return acl (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_sunacl_acl=yes +else + ac_cv_lib_sunacl_acl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sunacl_acl" >&5 +$as_echo "$ac_cv_lib_sunacl_acl" >&6; } +if test "x$ac_cv_lib_sunacl_acl" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSUNACL 1 +_ACEOF + + LIBS="-lsunacl $LIBS" + +fi + + + if test x"$ac_cv_header_sunacl_h" = x"yes" -a x"$ac_cv_lib_sunacl_acl" = x"yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling support for ZFS ACLs using libsunacl" >&5 +$as_echo "$as_me: Enabling support for ZFS ACLs using libsunacl" >&6;} + ac_cv_have_acls=yes + CFLAGS="-I$sunacl_include_path $CFLAGS" + ACL_LIBS="$ACL_LIBS -L$sunacl_lib_path -lsunacl" + +$as_echo "#define HAVE_FREEBSD_SUNACL 1" >>confdefs.h + + +$as_echo "#define HAVE_NFSV4_ACLS 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: libsunacl not found, disabling ZFS ACL support" >&5 +$as_echo "$as_me: libsunacl not found, disabling ZFS ACL support" >&6;} + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac +fi + +if test x"$with_acl_support" != x"no" -a x"$ac_cv_have_acls" != x"yes" ; then + # Runtime checks for POSIX ACLs + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_get_file in -lacl" >&5 +$as_echo_n "checking for acl_get_file in -lacl... " >&6; } +if ${ac_cv_lib_acl_acl_get_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lacl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char acl_get_file (); +int +main () +{ +return acl_get_file (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_acl_acl_get_file=yes +else + ac_cv_lib_acl_acl_get_file=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_acl_acl_get_file" >&5 +$as_echo "$ac_cv_lib_acl_acl_get_file" >&6; } +if test "x$ac_cv_lib_acl_acl_get_file" = xyes; then : + ACL_LIBS="$ACL_LIBS -lacl" +fi + + case "$host_os" in + *linux*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getxattr in -lattr" >&5 +$as_echo_n "checking for getxattr in -lattr... " >&6; } +if ${ac_cv_lib_attr_getxattr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lattr $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getxattr (); +int +main () +{ +return getxattr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_attr_getxattr=yes +else + ac_cv_lib_attr_getxattr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_attr_getxattr" >&5 +$as_echo "$ac_cv_lib_attr_getxattr" >&6; } +if test "x$ac_cv_lib_attr_getxattr" = xyes; then : + ACL_LIBS="$ACL_LIBS -lattr" +fi + + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for POSIX ACL support" >&5 +$as_echo_n "checking for POSIX ACL support... " >&6; } +if ${netatalk_cv_HAVE_POSIX_ACLS+:} false; then : + $as_echo_n "(cached) " >&6 +else + + acl_LIBS=$LIBS + LIBS="$LIBS $ACL_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + acl_t acl; + int entry_id; + acl_entry_t *entry_p; + return acl_get_entry(acl, entry_id, entry_p); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + netatalk_cv_HAVE_POSIX_ACLS=yes; ac_cv_have_acls=yes +else + netatalk_cv_HAVE_POSIX_ACLS=no; ac_cv_have_acls=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$acl_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_HAVE_POSIX_ACLS" >&5 +$as_echo "$netatalk_cv_HAVE_POSIX_ACLS" >&6; } + + if test x"$netatalk_cv_HAVE_POSIX_ACLS" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Using POSIX ACLs" >&5 +$as_echo "$as_me: Using POSIX ACLs" >&6;} + +$as_echo "#define HAVE_POSIX_ACLS 1" >>confdefs.h + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_get_perm_np" >&5 +$as_echo_n "checking for acl_get_perm_np... " >&6; } +if ${netatalk_cv_HAVE_ACL_GET_PERM_NP+:} false; then : + $as_echo_n "(cached) " >&6 +else + + acl_LIBS=$LIBS + LIBS="$LIBS $ACL_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + acl_permset_t permset_d; + acl_perm_t perm; + return acl_get_perm_np(permset_d, perm); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + netatalk_cv_HAVE_ACL_GET_PERM_NP=yes +else + netatalk_cv_HAVE_ACL_GET_PERM_NP=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$acl_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_HAVE_ACL_GET_PERM_NP" >&5 +$as_echo "$netatalk_cv_HAVE_ACL_GET_PERM_NP" >&6; } + if test x"$netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then + +$as_echo "#define HAVE_ACL_GET_PERM_NP 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_from_mode" >&5 +$as_echo_n "checking for acl_from_mode... " >&6; } +if ${netatalk_cv_HAVE_ACL_FROM_MODE+:} false; then : + $as_echo_n "(cached) " >&6 +else + + acl_LIBS=$LIBS + LIBS="$LIBS $ACL_LIBS" + for ac_func in acl_from_mode +do : + ac_fn_c_check_func "$LINENO" "acl_from_mode" "ac_cv_func_acl_from_mode" +if test "x$ac_cv_func_acl_from_mode" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ACL_FROM_MODE 1 +_ACEOF + netatalk_cv_HAVE_ACL_FROM_MODE=yes +else + netatalk_cv_HAVE_ACL_FROM_MODE=no + +fi +done + + LIBS=$acl_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netatalk_cv_HAVE_ACL_FROM_MODE" >&5 +$as_echo "$netatalk_cv_HAVE_ACL_FROM_MODE" >&6; } + if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then + +$as_echo "#define HAVE_ACL_FROM_MODE 1" >>confdefs.h + + fi + fi +fi + +if test x"$ac_cv_have_acls" = x"no" ; then + if test x"$with_acl_support" = x"yes" ; then + as_fn_error $? "ACL support requested but not found" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: ACL support is not avaliable" >&5 +$as_echo "$as_me: ACL support is not avaliable" >&6;} + fi +else + for ac_header in acl/libacl.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "acl/libacl.h" "ac_cv_header_acl_libacl_h" "$ac_includes_default" +if test "x$ac_cv_header_acl_libacl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ACL_LIBACL_H 1 +_ACEOF + +fi + +done + + +$as_echo "#define HAVE_ACLS 1" >>confdefs.h + +fi + + + + +neta_cv_eas="ad" +neta_cv_eas_sys_found=no +neta_cv_eas_sys_not_found=no + +for ac_header in sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h sys/ea.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +case "$this_os" in + + *osf*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getproplist" >&5 +$as_echo_n "checking for library containing getproplist... " >&6; } +if ${ac_cv_search_getproplist+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getproplist (); +int +main () +{ +return getproplist (); + ; + return 0; +} +_ACEOF +for ac_lib in '' proplist; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_getproplist=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_getproplist+:} false; then : + break +fi +done +if ${ac_cv_search_getproplist+:} false; then : + +else + ac_cv_search_getproplist=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getproplist" >&5 +$as_echo "$ac_cv_search_getproplist" >&6; } +ac_res=$ac_cv_search_getproplist +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + for ac_func in getproplist fgetproplist setproplist fsetproplist +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + neta_cv_eas_sys_found=yes +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in delproplist fdelproplist add_proplist_entry get_proplist_entry +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in sizeof_proplist_entry +do : + ac_fn_c_check_func "$LINENO" "sizeof_proplist_entry" "ac_cv_func_sizeof_proplist_entry" +if test "x$ac_cv_func_sizeof_proplist_entry" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SIZEOF_PROPLIST_ENTRY 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + ;; + + *solaris*) + for ac_func in attropen +do : + ac_fn_c_check_func "$LINENO" "attropen" "ac_cv_func_attropen" +if test "x$ac_cv_func_attropen" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ATTROPEN 1 +_ACEOF + neta_cv_eas_sys_found=yes; +$as_echo "#define HAVE_EAFD 1" >>confdefs.h + +else + neta_cv_eas_sys_not_found=yes +fi +done + + ;; + + 'freebsd') + for ac_func in extattr_delete_fd extattr_delete_file extattr_delete_link +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + neta_cv_eas_sys_found=yes +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in extattr_get_fd extattr_get_file extattr_get_link +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in extattr_list_fd extattr_list_file extattr_list_link +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in extattr_set_fd extattr_set_file extattr_set_link +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + ;; + + *freebsd4* | *dragonfly* ) + +$as_echo "#define BROKEN_EXTATTR 1" >>confdefs.h + + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getxattr" >&5 +$as_echo_n "checking for library containing getxattr... " >&6; } +if ${ac_cv_search_getxattr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getxattr (); +int +main () +{ +return getxattr (); + ; + return 0; +} +_ACEOF +for ac_lib in '' attr; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_getxattr=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_getxattr+:} false; then : + break +fi +done +if ${ac_cv_search_getxattr+:} false; then : + +else + ac_cv_search_getxattr=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getxattr" >&5 +$as_echo "$ac_cv_search_getxattr" >&6; } +ac_res=$ac_cv_search_getxattr +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + + if test "x$neta_cv_eas_sys_found" != "xyes" ; then + for ac_func in getxattr lgetxattr fgetxattr listxattr llistxattr +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + neta_cv_eas_sys_found=yes +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in flistxattr removexattr lremovexattr fremovexattr +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in setxattr lsetxattr fsetxattr +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + fi + + if test "x$neta_cv_eas_sys_found" != "xyes" ; then + for ac_func in getea fgetea lgetea listea flistea llistea +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + neta_cv_eas_sys_found=yes +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in removeea fremoveea lremoveea setea fsetea lsetea +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + fi + + if test "x$neta_cv_eas_sys_found" != "xyes" ; then + for ac_func in attr_get attr_list attr_set attr_remove +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + for ac_func in attr_getf attr_listf attr_setf attr_removef +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + neta_cv_eas_sys_not_found=yes +fi +done + + fi + ;; +esac + +# Do xattr functions take additional options like on Darwin? +if test x"$ac_cv_func_getxattr" = x"yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether xattr interface takes additional options" >&5 +$as_echo_n "checking whether xattr interface takes additional options... " >&6; } +if ${smb_attr_cv_xattr_add_opt+:} false; then : + $as_echo_n "(cached) " >&6 +else + + old_LIBS=$LIBS + LIBS="$LIBS $ACL_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #if HAVE_ATTR_XATTR_H + #include + #elif HAVE_SYS_XATTR_H + #include + #endif + +int +main () +{ + + getxattr(0, 0, 0, 0, 0, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + smb_attr_cv_xattr_add_opt=yes +else + smb_attr_cv_xattr_add_opt=no;LIBS=$old_LIBS +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $smb_attr_cv_xattr_add_opt" >&5 +$as_echo "$smb_attr_cv_xattr_add_opt" >&6; } + if test x"$smb_attr_cv_xattr_add_opt" = x"yes"; then + +$as_echo "#define XATTR_ADD_OPT 1" >>confdefs.h + + fi +fi + +if test "x$neta_cv_eas_sys_found" = "xyes" ; then + if test "x$neta_cv_eas_sys_not_found" != "xyes" ; then + neta_cv_eas="$neta_cv_eas | sys" + fi +fi + +cat >>confdefs.h <<_ACEOF +#define EA_MODULES "$neta_cv_eas" +_ACEOF + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the realpath function allows a NULL argument" >&5 +$as_echo_n "checking if the realpath function allows a NULL argument... " >&6; } +if ${neta_cv_REALPATH_TAKES_NULL+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + neta_cv_REALPATH_TAKES_NULL=cross + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + #include + + void exit_on_core(int ignored) { + exit(1); + } + + main() { + char *newpath; + signal(SIGSEGV, exit_on_core); + newpath = realpath("/tmp", NULL); + exit((newpath != NULL) ? 0 : 1); + } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + neta_cv_REALPATH_TAKES_NULL=yes +else + neta_cv_REALPATH_TAKES_NULL=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $neta_cv_REALPATH_TAKES_NULL" >&5 +$as_echo "$neta_cv_REALPATH_TAKES_NULL" >&6; } + +if test x"$neta_cv_REALPATH_TAKES_NULL" = x"yes"; then + +$as_echo "#define REALPATH_TAKES_NULL 1" >>confdefs.h + +fi + + + +netatalk_cv_search_sendfile=yes +# Check whether --enable-sendfile was given. +if test "${enable_sendfile+set}" = set; then : + enableval=$enable_sendfile; if test x"$enableval" = x"no"; then + netatalk_cv_search_sendfile=no + fi + +fi + + +if test x"$netatalk_cv_search_sendfile" = x"yes"; then + case "$host_os" in + *linux*) + +$as_echo "#define SENDFILE_FLAVOR_LINUX 1" >>confdefs.h + + ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile" +if test "x$ac_cv_func_sendfile" = xyes; then : + netatalk_cv_HAVE_SENDFILE=yes +fi + + ;; + + *solaris*) + +$as_echo "#define SENDFILE_FLAVOR_SOLARIS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sendfile" >&5 +$as_echo_n "checking for library containing sendfile... " >&6; } +if ${ac_cv_search_sendfile+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sendfile (); +int +main () +{ +return sendfile (); + ; + return 0; +} +_ACEOF +for ac_lib in '' sendfile; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_sendfile=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_sendfile+:} false; then : + break +fi +done +if ${ac_cv_search_sendfile+:} false; then : + +else + ac_cv_search_sendfile=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sendfile" >&5 +$as_echo "$ac_cv_search_sendfile" >&6; } +ac_res=$ac_cv_search_sendfile +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile" +if test "x$ac_cv_func_sendfile" = xyes; then : + netatalk_cv_HAVE_SENDFILE=yes +fi + + for ac_func in sendfilev +do : + ac_fn_c_check_func "$LINENO" "sendfilev" "ac_cv_func_sendfilev" +if test "x$ac_cv_func_sendfilev" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SENDFILEV 1 +_ACEOF + +fi +done + + ;; + + *freebsd*) + +$as_echo "#define SENDFILE_FLAVOR_BSD 1" >>confdefs.h + + ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile" +if test "x$ac_cv_func_sendfile" = xyes; then : + netatalk_cv_HAVE_SENDFILE=yes +fi + + ;; + + *) + ;; + + esac + + if test x"$netatalk_cv_HAVE_SENDFILE" = x"yes"; then + +$as_echo "#define WITH_SENDFILE 1" >>confdefs.h + + fi +fi + + +case "$host_os" in +*linux*) + for ac_func in splice +do : + ac_fn_c_check_func "$LINENO" "splice" "ac_cv_func_splice" +if test "x$ac_cv_func_splice" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SPLICE 1 +_ACEOF + atalk_cv_use_recvfile=yes +fi +done + + ;; + +*) + ;; + +esac + +if test x"$atalk_cv_use_recvfile" = x"yes"; then + +$as_echo "#define WITH_RECVFILE 1" >>confdefs.h + +fi + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use bundled libevent" >&5 +$as_echo_n "checking whether to use bundled libevent... " >&6; } + +# Check whether --with-libevent was given. +if test "${with_libevent+set}" = set; then : + withval=$with_libevent; use_bundled_libevent=$withval +else + use_bundled_libevent=yes + +fi + + +# Check whether --with-libevent-header was given. +if test "${with_libevent_header+set}" = set; then : + withval=$with_libevent_header; use_bundled_libevent=no; LIBEVENT_CFLAGS=-I$withval + +fi + + +# Check whether --with-libevent-lib was given. +if test "${with_libevent_lib+set}" = set; then : + withval=$with_libevent_lib; use_bundled_libevent=no; LIBEVENT_LDFLAGS=-L$withval + +fi + + if test x"$LIBEVENT_CFLAGS" = x"-Iyes" -o x"$LIBEVENT_LDFLAGS" = x"-Lyes" ; then + as_fn_error $? "--with-libevent requires a path" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_bundled_libevent" >&5 +$as_echo "$use_bundled_libevent" >&6; } + if test x"$use_bundled_libevent" = x"yes" ; then + subdirs="$subdirs libevent" + + fi + + + if test x"$use_bundled_libevent" = x"yes"; then + USE_BUILTIN_LIBEVENT_TRUE= + USE_BUILTIN_LIBEVENT_FALSE='#' +else + USE_BUILTIN_LIBEVENT_TRUE='#' + USE_BUILTIN_LIBEVENT_FALSE= +fi + + + + + +# Check whether --with-tdb was given. +if test "${with_tdb+set}" = set; then : + withval=$with_tdb; use_bundled_tdb=$withval +else + use_bundled_tdb=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use bundled tdb" >&5 +$as_echo_n "checking whether to use bundled tdb... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_bundled_tdb" >&5 +$as_echo "$use_bundled_tdb" >&6; } + + if test x"$use_bundled_tdb" = x"yes" ; then + +$as_echo "#define USE_BUILTIN_TDB 1" >>confdefs.h + + else + if test -z "$TDB_LIBS" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TDB" >&5 +$as_echo_n "checking for TDB... " >&6; } + +if test -n "$TDB_CFLAGS"; then + pkg_cv_TDB_CFLAGS="$TDB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tdb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "tdb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_TDB_CFLAGS=`$PKG_CONFIG --cflags "tdb" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$TDB_LIBS"; then + pkg_cv_TDB_LIBS="$TDB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tdb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "tdb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_TDB_LIBS=`$PKG_CONFIG --libs "tdb" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +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 + TDB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "tdb" 2>&1` + else + TDB_PKG_ERRORS=`$PKG_CONFIG --print-errors "tdb" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$TDB_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "couldn't find tdb with pkg-config" "$LINENO" 5 +elif test $pkg_failed = untried; then + as_fn_error $? "couldn't find tdb with pkg-config" "$LINENO" 5 +else + TDB_CFLAGS=$pkg_cv_TDB_CFLAGS + TDB_LIBS=$pkg_cv_TDB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + fi + use_bundled_tdb=no + fi + + + + if test x"$use_bundled_tdb" = x"yes"; then + USE_BUILTIN_TDB_TRUE= + USE_BUILTIN_TDB_FALSE='#' +else + USE_BUILTIN_TDB_TRUE='#' + USE_BUILTIN_TDB_FALSE= +fi + + + + + ac_cv_have_tracker=no + ac_cv_tracker_pkg_version_default=0.12 + ac_cv_tracker_pkg_version_min=0.12 + + +# Check whether --with-tracker-pkgconfig-version was given. +if test "${with_tracker_pkgconfig_version+set}" = set; then : + withval=$with_tracker_pkgconfig_version; ac_cv_tracker_pkg_version=$withval +else + ac_cv_tracker_pkg_version=$ac_cv_tracker_pkg_version_default + +fi + + + +# Check whether --with-tracker-prefix was given. +if test "${with_tracker_prefix+set}" = set; then : + withval=$with_tracker_prefix; ac_cv_tracker_prefix=$withval +else + ac_cv_tracker_prefix="`pkg-config --variable=prefix tracker-sparql-$ac_cv_tracker_pkg_version`" + +fi + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TRACKER" >&5 +$as_echo_n "checking for TRACKER... " >&6; } + +if test -n "$TRACKER_CFLAGS"; then + pkg_cv_TRACKER_CFLAGS="$TRACKER_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tracker-sparql-\$ac_cv_tracker_pkg_version >= \$ac_cv_tracker_pkg_version_min\""; } >&5 + ($PKG_CONFIG --exists --print-errors "tracker-sparql-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_TRACKER_CFLAGS=`$PKG_CONFIG --cflags "tracker-sparql-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$TRACKER_LIBS"; then + pkg_cv_TRACKER_LIBS="$TRACKER_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tracker-sparql-\$ac_cv_tracker_pkg_version >= \$ac_cv_tracker_pkg_version_min\""; } >&5 + ($PKG_CONFIG --exists --print-errors "tracker-sparql-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_TRACKER_LIBS=`$PKG_CONFIG --libs "tracker-sparql-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +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 + TRACKER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "tracker-sparql-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min" 2>&1` + else + TRACKER_PKG_ERRORS=`$PKG_CONFIG --print-errors "tracker-sparql-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$TRACKER_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ac_cv_have_tracker_sparql=no +elif test $pkg_failed = untried; then + ac_cv_have_tracker_sparql=no +else + TRACKER_CFLAGS=$pkg_cv_TRACKER_CFLAGS + TRACKER_LIBS=$pkg_cv_TRACKER_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_cv_have_tracker_sparql=yes +fi + + if test x"$ac_cv_have_tracker_sparql" = x"no" ; then + if test x"$need_tracker_sparql" = x"yes" ; then + as_fn_error $? "$ac_cv_tracker_pkg not found" "$LINENO" 5 + fi + else + ac_cv_have_tracker=yes + +$as_echo "#define HAVE_TRACKER 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define TRACKER_PREFIX "$ac_cv_tracker_prefix" +_ACEOF + + +$as_echo "#define DBUS_DAEMON_PATH \"/bin/dbus-daemon\"" >>confdefs.h + + fi + + + + + + if test x"$ac_cv_have_tracker" = x"yes"; then + HAVE_TRACKER_TRUE= + HAVE_TRACKER_FALSE='#' +else + HAVE_TRACKER_TRUE='#' + HAVE_TRACKER_FALSE= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable developer build" >&5 +$as_echo_n "checking whether to enable developer build... " >&6; } + # Check whether --enable-developer was given. +if test "${enable_developer+set}" = set; then : + enableval=$enable_developer; enable_dev=$enableval +else + enable_dev=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_dev" >&5 +$as_echo "$enable_dev" >&6; } + if test x"$enable_dev" = x"yes"; then + DEVELOPER_TRUE= + DEVELOPER_FALSE='#' +else + DEVELOPER_TRUE='#' + DEVELOPER_FALSE= +fi + + + + + +# Check whether --with-dtrace was given. +if test "${with_dtrace+set}" = set; then : + withval=$with_dtrace; WDTRACE=$withval +else + WDTRACE=auto + +fi + + if test "x$WDTRACE" = "xyes" -o "x$WDTRACE" = "xauto" ; then + # Extract the first word of "dtrace", so it can be a program name with args. +set dummy dtrace; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_atalk_cv_have_dtrace+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$atalk_cv_have_dtrace"; then + ac_cv_prog_atalk_cv_have_dtrace="$atalk_cv_have_dtrace" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_atalk_cv_have_dtrace="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_atalk_cv_have_dtrace" && ac_cv_prog_atalk_cv_have_dtrace="no" +fi +fi +atalk_cv_have_dtrace=$ac_cv_prog_atalk_cv_have_dtrace +if test -n "$atalk_cv_have_dtrace"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $atalk_cv_have_dtrace" >&5 +$as_echo "$atalk_cv_have_dtrace" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$atalk_cv_have_dtrace" = "xno" ; then + if test "x$WDTRACE" = "xyes" ; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "dtrace requested but not found +See \`config.log' for more details" "$LINENO" 5; } + fi + WDTRACE="no" + else + WDTRACE="yes" + fi + fi + + if test x"$WDTRACE" = x"yes" ; then + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + + DTRACE_LIBS="" + if test x"$this_os" = x"freebsd" ; then + DTRACE_LIBS="-lelf" + fi + + fi + if test "x$WDTRACE" = "xyes"; then + WITH_DTRACE_TRUE= + WITH_DTRACE_FALSE='#' +else + WITH_DTRACE_TRUE='#' + WITH_DTRACE_FALSE= +fi + + + + + atalk_cv_with_dbus=no + + +# Check whether --with-afpstats was given. +if test "${with_afpstats+set}" = set; then : + withval=$with_afpstats; +else + withval=auto + +fi + + + if test x"$withval" != x"no" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBUS" >&5 +$as_echo_n "checking for DBUS... " >&6; } + +if test -n "$DBUS_CFLAGS"; then + pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1 >= 1.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1 >= 1.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1 >= 1.1" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$DBUS_LIBS"; then + pkg_cv_DBUS_LIBS="$DBUS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1 >= 1.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1 >= 1.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1 >= 1.1" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +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 + DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "dbus-1 >= 1.1" 2>&1` + else + DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors "dbus-1 >= 1.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$DBUS_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_dbus=no +elif test $pkg_failed = untried; then + have_dbus=no +else + DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS + DBUS_LIBS=$pkg_cv_DBUS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_dbus=yes +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBUS_GLIB" >&5 +$as_echo_n "checking for DBUS_GLIB... " >&6; } + +if test -n "$DBUS_GLIB_CFLAGS"; then + pkg_cv_DBUS_GLIB_CFLAGS="$DBUS_GLIB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-glib-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-glib-1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_GLIB_CFLAGS=`$PKG_CONFIG --cflags "dbus-glib-1" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$DBUS_GLIB_LIBS"; then + pkg_cv_DBUS_GLIB_LIBS="$DBUS_GLIB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-glib-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-glib-1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_GLIB_LIBS=`$PKG_CONFIG --libs "dbus-glib-1" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +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 + DBUS_GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "dbus-glib-1" 2>&1` + else + DBUS_GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors "dbus-glib-1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$DBUS_GLIB_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_dbus_glib=no +elif test $pkg_failed = untried; then + have_dbus_glib=no +else + DBUS_GLIB_CFLAGS=$pkg_cv_DBUS_GLIB_CFLAGS + DBUS_GLIB_LIBS=$pkg_cv_DBUS_GLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_dbus_glib=yes +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBUS_GTHREAD" >&5 +$as_echo_n "checking for DBUS_GTHREAD... " >&6; } + +if test -n "$DBUS_GTHREAD_CFLAGS"; then + pkg_cv_DBUS_GTHREAD_CFLAGS="$DBUS_GTHREAD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gthread-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_GTHREAD_CFLAGS=`$PKG_CONFIG --cflags "gthread-2.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$DBUS_GTHREAD_LIBS"; then + pkg_cv_DBUS_GTHREAD_LIBS="$DBUS_GTHREAD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gthread-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_GTHREAD_LIBS=`$PKG_CONFIG --libs "gthread-2.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +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 + DBUS_GTHREAD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gthread-2.0" 2>&1` + else + DBUS_GTHREAD_PKG_ERRORS=`$PKG_CONFIG --print-errors "gthread-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$DBUS_GTHREAD_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_dbus_gthread=no +elif test $pkg_failed = untried; then + have_dbus_gthread=no +else + DBUS_GTHREAD_CFLAGS=$pkg_cv_DBUS_GTHREAD_CFLAGS + DBUS_GTHREAD_LIBS=$pkg_cv_DBUS_GTHREAD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_dbus_gthread=yes +fi + if test x$have_dbus_glib = xyes -a x$have_dbus = xyes -a x$have_dbus_gthread = xyes ; then + saved_CFLAGS=$CFLAGS + saved_LIBS=$LIBS + CFLAGS="$CFLAGS $DBUS_GLIB_CFLAGS" + LIBS="$LIBS $DBUS_GLIB_LIBS" + ac_fn_c_check_func "$LINENO" "dbus_g_bus_get_private" "ac_cv_func_dbus_g_bus_get_private" +if test "x$ac_cv_func_dbus_g_bus_get_private" = xyes; then : + atalk_cv_with_dbus=yes +else + atalk_cv_with_dbus=no +fi + + CFLAGS="$saved_CFLAGS" + LIBS="$saved_LIBS" + fi + fi + + if test x"$withval" = x"yes" -a x"$atalk_cv_with_dbus" = x"no"; then + as_fn_error $? "afpstats requested but dbus-glib not found" "$LINENO" 5 + fi + + +# Check whether --with-dbus-sysconf-dir was given. +if test "${with_dbus_sysconf_dir+set}" = set; then : + withval=$with_dbus_sysconf_dir; ac_cv_dbus_sysdir=$withval +else + ac_cv_dbus_sysdir='${sysconfdir}/dbus-1/system.d' + +fi + + DBUS_SYS_DIR="" + if test x$atalk_cv_with_dbus = xyes ; then + +$as_echo "#define HAVE_DBUS_GLIB 1" >>confdefs.h + + DBUS_SYS_DIR="$ac_cv_dbus_sysdir" + fi + + + + + + + + + if test x$atalk_cv_with_dbus = xyes; then + HAVE_DBUS_GLIB_TRUE= + HAVE_DBUS_GLIB_FALSE='#' +else + HAVE_DBUS_GLIB_TRUE='#' + HAVE_DBUS_GLIB_FALSE= +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use Filesystem Hierarchy Standard (FHS) compatibility" >&5 +$as_echo_n "checking whether to use Filesystem Hierarchy Standard (FHS) compatibility... " >&6; } +# Check whether --enable-fhs was given. +if test "${enable_fhs+set}" = set; then : + enableval=$enable_fhs; + if test "$enableval" = "yes"; then + bindir="/bin" + sbindir="/sbin" + sysconfdir="/etc" + libdir="/lib" + localstatedir="/var" + mandir="/usr/share/man" + uams_path="${libdir}/netatalk" + PKGCONFDIR="${sysconfdir}" + SERVERTEXT="${localstatedir}/netatalk/msg" + use_pam_so=yes + +$as_echo "#define FHS_COMPATIBILITY 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + atalk_cv_fhs_compat=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + atalk_cv_fhs_compat=no + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + atalk_cv_fhs_compat=no + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking netatalk lockfile path" >&5 +$as_echo_n "checking netatalk lockfile path... " >&6; } + +# Check whether --with-lockfile was given. +if test "${with_lockfile+set}" = set; then : + withval=$with_lockfile; ac_cv_netatalk_lock=$withval +else + ac_cv_netatalk_lock="" + +fi + + if test -z "$ac_cv_netatalk_lock" ; then + ac_cv_netatalk_lock=/var/spool/locks/netatalk + if test x"$atalk_cv_fhs_compat" = x"yes" ; then + ac_cv_netatalk_lock=/var/run/netatalk.pid + else + case "$host_os" in + *freebsd*) + ac_cv_netatalk_lock=/var/spool/lock/netatalk + ;; + *netbsd*|*openbsd*) + ac_cv_netatalk_lock=/var/run/netatalk.pid + ;; + *linux*) + ac_cv_netatalk_lock=/var/lock/netatalk + ;; + esac + fi + fi + +cat >>confdefs.h <<_ACEOF +#define PATH_NETATALK_LOCK "$ac_cv_netatalk_lock" +_ACEOF + + PATH_NETATALK_LOCK="$ac_cv_netatalk_lock" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netatalk_lock" >&5 +$as_echo "$ac_cv_netatalk_lock" >&6; } + + + + # It's just rude to go over the net to build + XSLTPROC_FLAGS=--nonet + DOCBOOK_ROOT= + XSLTPROC_WORKS=no + + +# Check whether --with-docbook was given. +if test "${with_docbook+set}" = set; then : + withval=$with_docbook; DOCBOOK_ROOT=$withval + +fi + + + if test -n "$DOCBOOK_ROOT" ; then + # Extract the first word of "xsltproc", so it can be a program name with args. +set dummy xsltproc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_XSLTPROC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$XSLTPROC"; then + ac_cv_prog_XSLTPROC="$XSLTPROC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_XSLTPROC="xsltproc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +XSLTPROC=$ac_cv_prog_XSLTPROC +if test -n "$XSLTPROC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC" >&5 +$as_echo "$XSLTPROC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -n "$XSLTPROC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether xsltproc works" >&5 +$as_echo_n "checking whether xsltproc works... " >&6; } + DB_FILE="$DOCBOOK_ROOT/html/docbook.xsl" + $XSLTPROC $XSLTPROC_FLAGS $DB_FILE >/dev/null 2>&1 << END + + + + +END + if test "$?" = 0; then + XSLTPROC_WORKS=yes + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC_WORKS" >&5 +$as_echo "$XSLTPROC_WORKS" >&6; } + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Docbook documentation" >&5 +$as_echo_n "checking whether to build Docbook documentation... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC_WORKS" >&5 +$as_echo "$XSLTPROC_WORKS" >&6; } + + if test x"$XSLTPROC_WORKS" = x"yes"; then + HAVE_XSLTPROC_TRUE= + HAVE_XSLTPROC_FALSE='#' +else + HAVE_XSLTPROC_TRUE='#' + HAVE_XSLTPROC_FALSE= +fi + + + + + + +CPPFLAGS="-I\$(top_srcdir)/include -I\$(top_builddir)/include -I\$(top_srcdir) $CPPFLAGS" +UAMS_PATH="${uams_path}" + + + + + + if test x$solaris_module = xyes; then + SOLARIS_MODULE_TRUE= + SOLARIS_MODULE_FALSE='#' +else + SOLARIS_MODULE_TRUE='#' + SOLARIS_MODULE_FALSE= +fi + + if test x$neta_cv_have_libgcrypt = xyes; then + HAVE_LIBGCRYPT_TRUE= + HAVE_LIBGCRYPT_FALSE='#' +else + HAVE_LIBGCRYPT_TRUE='#' + HAVE_LIBGCRYPT_FALSE= +fi + + if test x$neta_cv_have_openssl = xyes; then + HAVE_OPENSSL_TRUE= + HAVE_OPENSSL_FALSE='#' +else + HAVE_OPENSSL_TRUE='#' + HAVE_OPENSSL_FALSE= +fi + + if test x"$ac_cv_have_acls" = x"yes"; then + HAVE_ACLS_TRUE= + HAVE_ACLS_FALSE='#' +else + HAVE_ACLS_TRUE='#' + HAVE_ACLS_FALSE= +fi + + if test x"$netatalk_cv_ldap" = x"yes"; then + HAVE_LDAP_TRUE= + HAVE_LDAP_FALSE='#' +else + HAVE_LDAP_TRUE='#' + HAVE_LDAP_FALSE= +fi + + if test x$neta_cv_compile_dhx = xyes; then + USE_DHX_TRUE= + USE_DHX_FALSE='#' +else + USE_DHX_TRUE='#' + USE_DHX_FALSE= +fi + + if test x$neta_cv_compile_dhx2 = xyes; then + USE_DHX2_TRUE= + USE_DHX2_FALSE='#' +else + USE_DHX2_TRUE='#' + USE_DHX2_FALSE= +fi + + if test x$neta_cv_have_openssl = xyes; then + USE_RANDNUM_TRUE= + USE_RANDNUM_FALSE='#' +else + USE_RANDNUM_TRUE='#' + USE_RANDNUM_FALSE= +fi + + if test x$use_pam_so = xyes; then + USE_PAM_SO_TRUE= + USE_PAM_SO_FALSE='#' +else + USE_PAM_SO_TRUE='#' + USE_PAM_SO_FALSE= +fi + + if test x$netatalk_cv_install_pam = xyes; then + USE_PAM_TRUE= + USE_PAM_FALSE='#' +else + USE_PAM_TRUE='#' + USE_PAM_FALSE= +fi + + if test x$compile_pam = xyes; then + BUILD_PAM_TRUE= + BUILD_PAM_FALSE='#' +else + BUILD_PAM_TRUE='#' + BUILD_PAM_FALSE= +fi + + if test x$compile_pgp = xyes; then + USE_PGP_TRUE= + USE_PGP_FALSE='#' +else + USE_PGP_TRUE='#' + USE_PGP_FALSE= +fi + + if test x$neta_cv_have_libgcrypt != xyes && test x$neta_cv_have_openssl != xyes; then + DEFAULT_HOOK_TRUE= + DEFAULT_HOOK_FALSE='#' +else + DEFAULT_HOOK_TRUE='#' + DEFAULT_HOOK_FALSE= +fi + + if test x$bdb_required = xyes; then + USE_BDB_TRUE= + USE_BDB_FALSE='#' +else + USE_BDB_TRUE='#' + USE_BDB_FALSE= +fi + + if test x"$ac_neta_haveatfuncs" = x"yes"; then + HAVE_ATFUNCS_TRUE= + HAVE_ATFUNCS_FALSE='#' +else + HAVE_ATFUNCS_TRUE='#' + HAVE_ATFUNCS_FALSE= +fi + + if test x$shadowpw = xyes; then + USE_SHADOWPW_TRUE= + USE_SHADOWPW_FALSE='#' +else + USE_SHADOWPW_TRUE='#' + USE_SHADOWPW_FALSE= +fi + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +ac_config_files="$ac_config_files Makefile bin/Makefile bin/ad/Makefile bin/afppasswd/Makefile bin/cnid/Makefile bin/cnid/cnid2_create bin/megatron/Makefile bin/misc/Makefile config/Makefile config/pam/Makefile contrib/Makefile contrib/macusers/Makefile contrib/macusers/macusers contrib/shell_utils/Makefile contrib/shell_utils/apple_dump contrib/shell_utils/asip-status.pl distrib/Makefile distrib/config/Makefile distrib/config/netatalk-config distrib/initscripts/Makefile distrib/m4/Makefile doc/Makefile doc/html.xsl doc/man.xsl doc/manual/Makefile doc/manual/manual.xml doc/manpages/Makefile doc/manpages/man1/Makefile doc/manpages/man5/Makefile doc/manpages/man8/Makefile etc/Makefile etc/afpd/Makefile etc/cnid_dbd/Makefile etc/netatalk/Makefile etc/spotlight/Makefile etc/uams/Makefile include/Makefile include/atalk/Makefile libatalk/Makefile libatalk/acl/Makefile libatalk/adouble/Makefile libatalk/bstring/Makefile libatalk/cnid/Makefile libatalk/cnid/cdb/Makefile libatalk/cnid/last/Makefile libatalk/cnid/dbd/Makefile libatalk/cnid/tdb/Makefile libatalk/cnid/mysql/Makefile libatalk/compat/Makefile libatalk/dsi/Makefile libatalk/iniparser/Makefile libatalk/talloc/Makefile libatalk/tdb/Makefile libatalk/unicode/Makefile libatalk/unicode/charsets/Makefile libatalk/util/Makefile libatalk/vfs/Makefile macros/Makefile man/Makefile man/man1/Makefile man/man1/ad.1 man/man1/afpldaptest.1 man/man1/afppasswd.1 man/man1/afpstats.1 man/man1/apple_dump.1 man/man1/asip-status.pl.1 man/man1/dbd.1 man/man1/macusers.1 man/man1/netatalk-config.1 man/man1/uniconv.1 man/man5/Makefile man/man5/afp.conf.5 man/man5/afp_signature.conf.5 man/man5/afp_voluuid.conf.5 man/man5/extmap.conf.5 man/man8/Makefile man/man8/afpd.8 man/man8/cnid_dbd.8 man/man8/cnid_metad.8 man/man8/netatalk.8 test/Makefile test/afpd/Makefile" + +ac_config_commands="$ac_config_commands default" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +if test -z "${RUN_LDCONFIG_TRUE}" && test -z "${RUN_LDCONFIG_FALSE}"; then + as_fn_error $? "conditional \"RUN_LDCONFIG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_DBD_DAEMON_TRUE}" && test -z "${BUILD_DBD_DAEMON_FALSE}"; then + as_fn_error $? "conditional \"BUILD_DBD_DAEMON\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_CDB_BACKEND_TRUE}" && test -z "${USE_CDB_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"USE_CDB_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_LAST_BACKEND_TRUE}" && test -z "${USE_LAST_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"USE_LAST_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_TDB_BACKEND_TRUE}" && test -z "${USE_TDB_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"USE_TDB_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_MYSQL_BACKEND_TRUE}" && test -z "${USE_MYSQL_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"USE_MYSQL_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_NETBSD_TRUE}" && test -z "${USE_NETBSD_FALSE}"; then + as_fn_error $? "conditional \"USE_NETBSD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_REDHAT_SYSV_TRUE}" && test -z "${USE_REDHAT_SYSV_FALSE}"; then + as_fn_error $? "conditional \"USE_REDHAT_SYSV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_SUSE_SYSV_TRUE}" && test -z "${USE_SUSE_SYSV_FALSE}"; then + as_fn_error $? "conditional \"USE_SUSE_SYSV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_SOLARIS_TRUE}" && test -z "${USE_SOLARIS_FALSE}"; then + as_fn_error $? "conditional \"USE_SOLARIS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_GENTOO_TRUE}" && test -z "${USE_GENTOO_FALSE}"; then + as_fn_error $? "conditional \"USE_GENTOO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_DEBIAN_SYSV_TRUE}" && test -z "${USE_DEBIAN_SYSV_FALSE}"; then + as_fn_error $? "conditional \"USE_DEBIAN_SYSV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_SYSTEMD_TRUE}" && test -z "${USE_SYSTEMD_FALSE}"; then + as_fn_error $? "conditional \"USE_SYSTEMD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_DEBIAN_SYSTEMD_TRUE}" && test -z "${USE_DEBIAN_SYSTEMD_FALSE}"; then + as_fn_error $? "conditional \"USE_DEBIAN_SYSTEMD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_UNDEF_TRUE}" && test -z "${USE_UNDEF_FALSE}"; then + as_fn_error $? "conditional \"USE_UNDEF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_GSSAPI_TRUE}" && test -z "${USE_GSSAPI_FALSE}"; then + as_fn_error $? "conditional \"USE_GSSAPI\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_BUILTIN_LIBEVENT_TRUE}" && test -z "${USE_BUILTIN_LIBEVENT_FALSE}"; then + as_fn_error $? "conditional \"USE_BUILTIN_LIBEVENT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_BUILTIN_TDB_TRUE}" && test -z "${USE_BUILTIN_TDB_FALSE}"; then + as_fn_error $? "conditional \"USE_BUILTIN_TDB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_TRACKER_TRUE}" && test -z "${HAVE_TRACKER_FALSE}"; then + as_fn_error $? "conditional \"HAVE_TRACKER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEVELOPER_TRUE}" && test -z "${DEVELOPER_FALSE}"; then + as_fn_error $? "conditional \"DEVELOPER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_DTRACE_TRUE}" && test -z "${WITH_DTRACE_FALSE}"; then + as_fn_error $? "conditional \"WITH_DTRACE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_DBUS_GLIB_TRUE}" && test -z "${HAVE_DBUS_GLIB_FALSE}"; then + as_fn_error $? "conditional \"HAVE_DBUS_GLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_XSLTPROC_TRUE}" && test -z "${HAVE_XSLTPROC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_XSLTPROC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SOLARIS_MODULE_TRUE}" && test -z "${SOLARIS_MODULE_FALSE}"; then + as_fn_error $? "conditional \"SOLARIS_MODULE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LIBGCRYPT_TRUE}" && test -z "${HAVE_LIBGCRYPT_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIBGCRYPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_OPENSSL_TRUE}" && test -z "${HAVE_OPENSSL_FALSE}"; then + as_fn_error $? "conditional \"HAVE_OPENSSL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_ACLS_TRUE}" && test -z "${HAVE_ACLS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_ACLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LDAP_TRUE}" && test -z "${HAVE_LDAP_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LDAP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_DHX_TRUE}" && test -z "${USE_DHX_FALSE}"; then + as_fn_error $? "conditional \"USE_DHX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_DHX2_TRUE}" && test -z "${USE_DHX2_FALSE}"; then + as_fn_error $? "conditional \"USE_DHX2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_RANDNUM_TRUE}" && test -z "${USE_RANDNUM_FALSE}"; then + as_fn_error $? "conditional \"USE_RANDNUM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_PAM_SO_TRUE}" && test -z "${USE_PAM_SO_FALSE}"; then + as_fn_error $? "conditional \"USE_PAM_SO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_PAM_TRUE}" && test -z "${USE_PAM_FALSE}"; then + as_fn_error $? "conditional \"USE_PAM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_PAM_TRUE}" && test -z "${BUILD_PAM_FALSE}"; then + as_fn_error $? "conditional \"BUILD_PAM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_PGP_TRUE}" && test -z "${USE_PGP_FALSE}"; then + as_fn_error $? "conditional \"USE_PGP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEFAULT_HOOK_TRUE}" && test -z "${DEFAULT_HOOK_FALSE}"; then + as_fn_error $? "conditional \"DEFAULT_HOOK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_BDB_TRUE}" && test -z "${USE_BDB_FALSE}"; then + as_fn_error $? "conditional \"USE_BDB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_ATFUNCS_TRUE}" && test -z "${HAVE_ATFUNCS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_ATFUNCS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${USE_SHADOWPW_TRUE}" && test -z "${USE_SHADOWPW_FALSE}"; then + as_fn_error $? "conditional \"USE_SHADOWPW\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "bin/Makefile") CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;; + "bin/ad/Makefile") CONFIG_FILES="$CONFIG_FILES bin/ad/Makefile" ;; + "bin/afppasswd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/afppasswd/Makefile" ;; + "bin/cnid/Makefile") CONFIG_FILES="$CONFIG_FILES bin/cnid/Makefile" ;; + "bin/cnid/cnid2_create") CONFIG_FILES="$CONFIG_FILES bin/cnid/cnid2_create" ;; + "bin/megatron/Makefile") CONFIG_FILES="$CONFIG_FILES bin/megatron/Makefile" ;; + "bin/misc/Makefile") CONFIG_FILES="$CONFIG_FILES bin/misc/Makefile" ;; + "config/Makefile") CONFIG_FILES="$CONFIG_FILES config/Makefile" ;; + "config/pam/Makefile") CONFIG_FILES="$CONFIG_FILES config/pam/Makefile" ;; + "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; + "contrib/macusers/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/macusers/Makefile" ;; + "contrib/macusers/macusers") CONFIG_FILES="$CONFIG_FILES contrib/macusers/macusers" ;; + "contrib/shell_utils/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/shell_utils/Makefile" ;; + "contrib/shell_utils/apple_dump") CONFIG_FILES="$CONFIG_FILES contrib/shell_utils/apple_dump" ;; + "contrib/shell_utils/asip-status.pl") CONFIG_FILES="$CONFIG_FILES contrib/shell_utils/asip-status.pl" ;; + "distrib/Makefile") CONFIG_FILES="$CONFIG_FILES distrib/Makefile" ;; + "distrib/config/Makefile") CONFIG_FILES="$CONFIG_FILES distrib/config/Makefile" ;; + "distrib/config/netatalk-config") CONFIG_FILES="$CONFIG_FILES distrib/config/netatalk-config" ;; + "distrib/initscripts/Makefile") CONFIG_FILES="$CONFIG_FILES distrib/initscripts/Makefile" ;; + "distrib/m4/Makefile") CONFIG_FILES="$CONFIG_FILES distrib/m4/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/html.xsl") CONFIG_FILES="$CONFIG_FILES doc/html.xsl" ;; + "doc/man.xsl") CONFIG_FILES="$CONFIG_FILES doc/man.xsl" ;; + "doc/manual/Makefile") CONFIG_FILES="$CONFIG_FILES doc/manual/Makefile" ;; + "doc/manual/manual.xml") CONFIG_FILES="$CONFIG_FILES doc/manual/manual.xml" ;; + "doc/manpages/Makefile") CONFIG_FILES="$CONFIG_FILES doc/manpages/Makefile" ;; + "doc/manpages/man1/Makefile") CONFIG_FILES="$CONFIG_FILES doc/manpages/man1/Makefile" ;; + "doc/manpages/man5/Makefile") CONFIG_FILES="$CONFIG_FILES doc/manpages/man5/Makefile" ;; + "doc/manpages/man8/Makefile") CONFIG_FILES="$CONFIG_FILES doc/manpages/man8/Makefile" ;; + "etc/Makefile") CONFIG_FILES="$CONFIG_FILES etc/Makefile" ;; + "etc/afpd/Makefile") CONFIG_FILES="$CONFIG_FILES etc/afpd/Makefile" ;; + "etc/cnid_dbd/Makefile") CONFIG_FILES="$CONFIG_FILES etc/cnid_dbd/Makefile" ;; + "etc/netatalk/Makefile") CONFIG_FILES="$CONFIG_FILES etc/netatalk/Makefile" ;; + "etc/spotlight/Makefile") CONFIG_FILES="$CONFIG_FILES etc/spotlight/Makefile" ;; + "etc/uams/Makefile") CONFIG_FILES="$CONFIG_FILES etc/uams/Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "include/atalk/Makefile") CONFIG_FILES="$CONFIG_FILES include/atalk/Makefile" ;; + "libatalk/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/Makefile" ;; + "libatalk/acl/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/acl/Makefile" ;; + "libatalk/adouble/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/adouble/Makefile" ;; + "libatalk/bstring/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/bstring/Makefile" ;; + "libatalk/cnid/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/cnid/Makefile" ;; + "libatalk/cnid/cdb/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/cnid/cdb/Makefile" ;; + "libatalk/cnid/last/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/cnid/last/Makefile" ;; + "libatalk/cnid/dbd/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/cnid/dbd/Makefile" ;; + "libatalk/cnid/tdb/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/cnid/tdb/Makefile" ;; + "libatalk/cnid/mysql/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/cnid/mysql/Makefile" ;; + "libatalk/compat/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/compat/Makefile" ;; + "libatalk/dsi/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/dsi/Makefile" ;; + "libatalk/iniparser/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/iniparser/Makefile" ;; + "libatalk/talloc/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/talloc/Makefile" ;; + "libatalk/tdb/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/tdb/Makefile" ;; + "libatalk/unicode/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/unicode/Makefile" ;; + "libatalk/unicode/charsets/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/unicode/charsets/Makefile" ;; + "libatalk/util/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/util/Makefile" ;; + "libatalk/vfs/Makefile") CONFIG_FILES="$CONFIG_FILES libatalk/vfs/Makefile" ;; + "macros/Makefile") CONFIG_FILES="$CONFIG_FILES macros/Makefile" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + "man/man1/Makefile") CONFIG_FILES="$CONFIG_FILES man/man1/Makefile" ;; + "man/man1/ad.1") CONFIG_FILES="$CONFIG_FILES man/man1/ad.1" ;; + "man/man1/afpldaptest.1") CONFIG_FILES="$CONFIG_FILES man/man1/afpldaptest.1" ;; + "man/man1/afppasswd.1") CONFIG_FILES="$CONFIG_FILES man/man1/afppasswd.1" ;; + "man/man1/afpstats.1") CONFIG_FILES="$CONFIG_FILES man/man1/afpstats.1" ;; + "man/man1/apple_dump.1") CONFIG_FILES="$CONFIG_FILES man/man1/apple_dump.1" ;; + "man/man1/asip-status.pl.1") CONFIG_FILES="$CONFIG_FILES man/man1/asip-status.pl.1" ;; + "man/man1/dbd.1") CONFIG_FILES="$CONFIG_FILES man/man1/dbd.1" ;; + "man/man1/macusers.1") CONFIG_FILES="$CONFIG_FILES man/man1/macusers.1" ;; + "man/man1/netatalk-config.1") CONFIG_FILES="$CONFIG_FILES man/man1/netatalk-config.1" ;; + "man/man1/uniconv.1") CONFIG_FILES="$CONFIG_FILES man/man1/uniconv.1" ;; + "man/man5/Makefile") CONFIG_FILES="$CONFIG_FILES man/man5/Makefile" ;; + "man/man5/afp.conf.5") CONFIG_FILES="$CONFIG_FILES man/man5/afp.conf.5" ;; + "man/man5/afp_signature.conf.5") CONFIG_FILES="$CONFIG_FILES man/man5/afp_signature.conf.5" ;; + "man/man5/afp_voluuid.conf.5") CONFIG_FILES="$CONFIG_FILES man/man5/afp_voluuid.conf.5" ;; + "man/man5/extmap.conf.5") CONFIG_FILES="$CONFIG_FILES man/man5/extmap.conf.5" ;; + "man/man8/Makefile") CONFIG_FILES="$CONFIG_FILES man/man8/Makefile" ;; + "man/man8/afpd.8") CONFIG_FILES="$CONFIG_FILES man/man8/afpd.8" ;; + "man/man8/cnid_dbd.8") CONFIG_FILES="$CONFIG_FILES man/man8/cnid_dbd.8" ;; + "man/man8/cnid_metad.8") CONFIG_FILES="$CONFIG_FILES man/man8/cnid_metad.8" ;; + "man/man8/netatalk.8") CONFIG_FILES="$CONFIG_FILES man/man8/netatalk.8" ;; + "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; + "test/afpd/Makefile") CONFIG_FILES="$CONFIG_FILES test/afpd/Makefile" ;; + "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + "default":C) chmod a+x distrib/config/netatalk-config contrib/shell_utils/apple_* + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_sub_configure_args " '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 + fi + + cd "$ac_popdir" + done +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Compilation summary:" >&5 +$as_echo "Compilation summary:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CPPFLAGS = $CPPFLAGS" >&5 +$as_echo " CPPFLAGS = $CPPFLAGS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $CFLAGS" >&5 +$as_echo " CFLAGS = $CFLAGS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $LIBS" >&5 +$as_echo " LIBS = $LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: PTHREADS:" >&5 +$as_echo " PTHREADS:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $PTHREAD_LIBS" >&5 +$as_echo " LIBS = $PTHREAD_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $PTHREAD_CFLAGS" >&5 +$as_echo " CFLAGS = $PTHREAD_CFLAGS" >&6; } + if test x"$ac_cv_have_tracker" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: TRACKER:" >&5 +$as_echo " TRACKER:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $TRACKER_LIBS" >&5 +$as_echo " LIBS = $TRACKER_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $TRACKER_CFLAGS" >&5 +$as_echo " CFLAGS = $TRACKER_CFLAGS" >&6; } + fi + if test x"$neta_cv_have_openssl" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: SSL:" >&5 +$as_echo " SSL:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $SSL_LIBS" >&5 +$as_echo " LIBS = $SSL_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $SSL_CFLAGS" >&5 +$as_echo " CFLAGS = $SSL_CFLAGS" >&6; } + fi + if test x"$neta_cv_have_libgcrypt" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBGCRYPT:" >&5 +$as_echo " LIBGCRYPT:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $LIBGCRYPT_LIBS" >&5 +$as_echo " LIBS = $LIBGCRYPT_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $LIBGCRYPT_CFLAGS" >&5 +$as_echo " CFLAGS = $LIBGCRYPT_CFLAGS" >&6; } + fi + if test x"$netatalk_cv_use_pam" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: PAM:" >&5 +$as_echo " PAM:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $PAM_LIBS" >&5 +$as_echo " LIBS = $PAM_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $PAM_CFLAGS" >&5 +$as_echo " CFLAGS = $PAM_CFLAGS" >&6; } + fi + if test x"$netatalk_cv_use_pam" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: WRAP:" >&5 +$as_echo " WRAP:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $WRAP_LIBS" >&5 +$as_echo " LIBS = $WRAP_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $WRAP_CFLAGS" >&5 +$as_echo " CFLAGS = $WRAP_CFLAGS" >&6; } + fi + if test x"$bdb_required" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: BDB:" >&5 +$as_echo " BDB:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $BDB_LIBS" >&5 +$as_echo " LIBS = $BDB_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $BDB_CFLAGS" >&5 +$as_echo " CFLAGS = $BDB_CFLAGS" >&6; } + fi + if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: GSSAPI:" >&5 +$as_echo " GSSAPI:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $GSSAPI_LIBS" >&5 +$as_echo " LIBS = $GSSAPI_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $GSSAPI_CFLAGS" >&5 +$as_echo " CFLAGS = $GSSAPI_CFLAGS" >&6; } + fi + if test x"$netatalk_cv_use_cups" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CUPS:" >&5 +$as_echo " CUPS:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $CUPS_LIBS" >&5 +$as_echo " LIBS = $CUPS_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $CUPS_CFLAGS" >&5 +$as_echo " CFLAGS = $CUPS_CFLAGS" >&6; } + fi + if test x"$netatalk_cv_zeroconf" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ZEROCONF:" >&5 +$as_echo " ZEROCONF:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $ZEROCONF_LIBS" >&5 +$as_echo " LIBS = $ZEROCONF_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $ZEROCONF_CFLAGS" >&5 +$as_echo " CFLAGS = $ZEROCONF_CFLAGS" >&6; } + fi + if test x"$netatalk_cv_ldap" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LDAP:" >&5 +$as_echo " LDAP:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $LDAP_LDFLAGS $LDAP_LIBS" >&5 +$as_echo " LIBS = $LDAP_LDFLAGS $LDAP_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $LDAP_CFLAGS" >&5 +$as_echo " CFLAGS = $LDAP_CFLAGS" >&6; } + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBEVENT:" >&5 +$as_echo " LIBEVENT:" >&6; } + if test x"$use_bundled_libevent" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5 +$as_echo " bundled" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $LIBEVENT_CFLAGS" >&5 +$as_echo " LIBS = $LIBEVENT_CFLAGS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $LIBEVENT_LDFLAGS" >&5 +$as_echo " CFLAGS = $LIBEVENT_LDFLAGS" >&6; } + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: TDB:" >&5 +$as_echo " TDB:" >&6; } + if test x"$use_bundled_tdb" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5 +$as_echo " bundled" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $TDB_LIBS" >&5 +$as_echo " LIBS = $TDB_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $TDB_CFLAGS" >&5 +$as_echo " CFLAGS = $TDB_CFLAGS" >&6; } + fi + if test x"$ac_cv_with_cnid_mysql" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: MySQL:" >&5 +$as_echo " MySQL:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LIBS = $MYSQL_LIBS" >&5 +$as_echo " LIBS = $MYSQL_LIBS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS = $MYSQL_CFLAGS" >&5 +$as_echo " CFLAGS = $MYSQL_CFLAGS" >&6; } + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Configure summary:" >&5 +$as_echo "Configure summary:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: INIT STYLE:" >&5 +$as_echo " INIT STYLE:" >&6; } + if test "x$init_style" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $init_style" >&5 +$as_echo " $init_style" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo " none" >&6; } + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: AFP:" >&5 +$as_echo " AFP:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Extended Attributes: $neta_cv_eas" >&5 +$as_echo " Extended Attributes: $neta_cv_eas" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ACL support: $ac_cv_have_acls" >&5 +$as_echo " ACL support: $ac_cv_have_acls" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Spotlight: $ac_cv_have_tracker" >&5 +$as_echo " Spotlight: $ac_cv_have_tracker" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: CNID:" >&5 +$as_echo " CNID:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: backends: $compiled_backends" >&5 +$as_echo " backends: $compiled_backends" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: UAMS:" >&5 +$as_echo " UAMS:" >&6; } + uams_using_options="" + if test x"$netatalk_cv_use_pam" != x"no"; then + uams_using_options="PAM" + fi + if test "x$netatalk_cv_use_shadowpw" = "xyes"; then + uams_using_options="$uams_using_options SHADOW" + fi + if test "x$neta_cv_compile_dhx" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: DHX ($uams_using_options)" >&5 +$as_echo " DHX ($uams_using_options)" >&6; } + fi + if test "x$neta_cv_compile_dhx2" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: DHX2 ($uams_using_options)" >&5 +$as_echo " DHX2 ($uams_using_options)" >&6; } + fi + if test "x$neta_cv_have_openssl" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: RANDNUM (afppasswd)" >&5 +$as_echo " RANDNUM (afppasswd)" >&6; } + fi + if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Kerberos V" >&5 +$as_echo " Kerberos V" >&6; } + fi + if test x"$compile_pgp" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: PGP" >&5 +$as_echo " PGP" >&6; } + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: clrtxt ($uams_using_options)" >&5 +$as_echo " clrtxt ($uams_using_options)" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: guest" >&5 +$as_echo " guest" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Options:" >&5 +$as_echo " Options:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Zeroconf support: $netatalk_cv_zeroconf" >&5 +$as_echo " Zeroconf support: $netatalk_cv_zeroconf" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: tcp wrapper support: $netatalk_cv_tcpwrap" >&5 +$as_echo " tcp wrapper support: $netatalk_cv_tcpwrap" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: quota support: $netatalk_cv_quotasupport" >&5 +$as_echo " quota support: $netatalk_cv_quotasupport" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: admin group support: $netatalk_cv_admin_group" >&5 +$as_echo " admin group support: $netatalk_cv_admin_group" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: valid shell check: $netatalk_cv_use_shellcheck" >&5 +$as_echo " valid shell check: $netatalk_cv_use_shellcheck" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: cracklib support: $netatalk_cv_with_cracklib" >&5 +$as_echo " cracklib support: $netatalk_cv_with_cracklib" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ACL support: $with_acl_support" >&5 +$as_echo " ACL support: $with_acl_support" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Kerberos support: $with_kerberos" >&5 +$as_echo " Kerberos support: $with_kerberos" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LDAP support: $netatalk_cv_ldap" >&5 +$as_echo " LDAP support: $netatalk_cv_ldap" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: AFP stats via dbus: $atalk_cv_with_dbus" >&5 +$as_echo " AFP stats via dbus: $atalk_cv_with_dbus" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: dtrace probes: $WDTRACE" >&5 +$as_echo " dtrace probes: $WDTRACE" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Paths:" >&5 +$as_echo " Paths:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Netatalk lockfile: $ac_cv_netatalk_lock" >&5 +$as_echo " Netatalk lockfile: $ac_cv_netatalk_lock" >&6; } + if test "x$init_style" != x"none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: init directory: $ac_cv_init_dir" >&5 +$as_echo " init directory: $ac_cv_init_dir" >&6; } + fi + if test x"$atalk_cv_with_dbus" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: dbus system directory: $ac_cv_dbus_sysdir" >&5 +$as_echo " dbus system directory: $ac_cv_dbus_sysdir" >&6; } + fi + if test x"$use_pam_so" = x"yes"; then + if test x"$netatalk_cv_install_pam" = x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: pam config directory: $ac_cv_pamdir" >&5 +$as_echo " pam config directory: $ac_cv_pamdir" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 +$as_echo "" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: PAM support was configured for your system, but the netatalk PAM configuration file" >&5 +$as_echo "$as_me: WARNING: PAM support was configured for your system, but the netatalk PAM configuration file" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot be installed. Please install the config/netatalk.pamd file manually." >&5 +$as_echo "$as_me: WARNING: cannot be installed. Please install the config/netatalk.pamd file manually." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: If you're running Solaris or BSD you'll have to edit /etc/pam.conf to get PAM working." >&5 +$as_echo "$as_me: WARNING: If you're running Solaris or BSD you'll have to edit /etc/pam.conf to get PAM working." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can also re-run configure and specify --without-pam to disable PAM support." >&5 +$as_echo "$as_me: WARNING: You can also re-run configure and specify --without-pam to disable PAM support." >&2;} + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Documentation:" >&5 +$as_echo " Documentation:" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Docbook: $XSLTPROC_WORKS" >&5 +$as_echo " Docbook: $XSLTPROC_WORKS" >&6; } + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..2f89f8c --- /dev/null +++ b/configure.ac @@ -0,0 +1,327 @@ +dnl configure.ac for netatalk + +AC_INIT(etc/afpd/main.c) + +NETATALK_VERSION=`cat $srcdir/VERSION` +AC_SUBST(NETATALK_VERSION) + +AC_CANONICAL_SYSTEM +AM_INIT_AUTOMAKE(netatalk, ${NETATALK_VERSION}) +AM_CONFIG_HEADER(config.h) +AM_MAINTAINER_MODE([enable]) + +dnl Checks for programs. +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CC_C99 +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_LIBTOOL_DLOPEN +AC_PROG_LIBTOOL +AC_PROG_PERL +AC_PROG_GREP +AC_PROG_PS +AM_PROG_CC_C_O +AC_C_BIGENDIAN +AC_C_INLINE +AC_PROG_LEX +AC_PROG_YACC + +dnl Check if we can use attribute unused (gcc only) from ethereal +AC_MSG_CHECKING(to see if we can add '__attribute__((unused))' to CFLAGS) +if test x$GCC != x ; then + CFLAGS="-D_U_=\"__attribute__((unused))\" $CFLAGS" + AC_MSG_RESULT(yes) +else + CFLAGS="-D_U_=\"\" $CFLAGS" + AC_MSG_RESULT(no) +fi + +dnl Checks for header files, some checks are obsolete, unfortunately the code +dnl uses the resulting macros, so the code has to cleaned up too before +dnl we can remove the checks here. +AC_CHECK_HEADERS(mntent.h unistd.h termios.h ufs/quota.h) +AC_CHECK_HEADERS(netdb.h sgtty.h statfs.h dlfcn.h langinfo.h locale.h) +AC_CHECK_HEADERS(sys/param.h sys/fcntl.h sys/termios.h) +AC_CHECK_HEADERS(sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h) +dnl Checks for header files, confirmed to be required as of 2011 +AC_CHECK_HEADERS([sys/mount.h], , , +[#ifdef HAVE_SYS_PARAM_H +#include +#endif +]) +AC_CHECK_TYPES([fshare_t], [], [], [[#include ]]) + +AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.])) + +dnl -------------------------------------------------------------------------- +dnl check if dlsym needs to add an underscore, uses libtool macros +dnl -------------------------------------------------------------------------- +AC_LTDL_DLLIB +AC_CHECK_FUNCS(dlopen dlsym dlclose) +AC_LTDL_DLSYM_USCORE +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE(DLSYM_PREPEND_UNDERSCORE, 1, [BSD compatibility macro]) +fi + +dnl Special hecks +ac_neta_haveatfuncs=yes +AC_CHECK_FUNCS(openat renameat fstatat unlinkat, , ac_neta_haveatfuncs=no) +if test x"$ac_neta_haveatfuncs" = x"yes" ; then + AC_DEFINE([_ATFILE_SOURCE], 1, AT file source) + AC_DEFINE([HAVE_ATFUNCS], 1, whether at funcs are available) +fi +AC_CHECK_MEMBERS(struct tm.tm_gmtoff,,, [#include ]) + +dnl these tests have been comfirmed to be needed in 2011 +AC_CHECK_FUNCS(backtrace_symbols dirfd getusershell pread pwrite pselect) +AC_CHECK_FUNCS(setlinebuf strlcat strlcpy strnlen mempcpy vasprintf asprintf) +AC_CHECK_FUNCS(mmap utime getpagesize) dnl needed by tbd + +dnl search for necessary libraries +AC_SEARCH_LIBS(gethostbyname, nsl) +AC_SEARCH_LIBS(connect, socket) +AC_CHECK_FUNCS(getifaddrs) dnl comes after gethostbyname and connect so it picks up the libs + +AX_PTHREAD(, [AC_MSG_ERROR([missing pthread_sigmask])]) + +AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW) + +dnl 64bit platform check +AC_NETATALK_64BIT_LIBS + +dnl OS specific checks +AC_NETATALK_OS_SPECIFIC + +dnl Check for optional admin group support +AC_NETATALK_ADMIN_GROUP + +dnl Check for optional AFS support +AC_NETATALK_AFS_CHECK + +dnl --with-pkgconfdir check to change configuration directory location +AC_NETATALK_CONFIG_DIRS + +dnl Check for optional cracklib support +AC_NETATALK_CRACKLIB + +dnl Check whether to enable debug code +AC_NETATALK_DEBUG + +dnl Check whethe to disable tickle SIGALARM stuff, which eases debugging +AC_NETATALK_DEBUGGING + +dnl Check for libiconv support +AC_NETATALK_CHECK_ICONV + +dnl Check for CNID database backends +AC_NETATALK_CNID([bdb_required=yes],[bdb_required=no]) + +dnl Check for quota support +AC_NETATALK_CHECK_QUOTA + +dnl Check for optional Zeroconf support +AC_NETATALK_ZEROCONF + +dnl Check for optional TCP-wrappers support +AC_NETATALK_TCP_WRAPPERS + +dnl Check for PAM libs +AC_NETATALK_PATH_PAM + +dnl Check for optional shadow password support +AC_NETATALK_SHADOW + +dnl Check for optional valid-shell-check support +AC_NETATALK_SHELL_CHECK + +dnl Check for optional sysv initscript install +AC_NETATALK_INIT_STYLE + +dnl Path where UAM modules shall be installed +AC_ARG_WITH(uams-path, [ --with-uams-path=PATH path to UAMs [[$libdir/netatalk/]]], [uams_path="$withval/"], [uams_path="$libdir/netatalk/"]) + +dnl Check for libgcrypt, if found enables DHX2 UAM +AC_NETATALK_PATH_LIBGCRYPT([1:1.2.3]) + +dnl Check for openssl, if found enables DHX UAM and Randnum UAM +AC_NETATALK_PATH_SSL + +dnl Check for Berkeley DB library +AC_NETATALK_PATH_BDB + +dnl Check for crypt +AC_NETATALK_CRYPT + +dnl Check for building PGP UAM module +AC_NETATALK_PGP_UAM + +dnl Check for building Kerberos V UAM module +AC_NETATALK_KRB5_UAM + +dnl Check for Kerberos 5 support +AC_NETATALK_KERBEROS + +dnl Check for overwrite the config files or not +AC_NETATALK_OVERWRITE_CONFIG + +dnl Check for LDAP support, for client-side ACL visibility +AC_NETATALK_LDAP + +dnl Check for ACL support +AC_NETATALK_ACL + +dnl Check for Extended Attributes support +AC_NETATALK_EXTENDED_ATTRIBUTES + +dnl Check if realpath() takes NULL +AC_NETATALK_REALPATH + +dnl Check for sendfile() +AC_NETATALK_SENDFILE +AC_NETATALK_RECVFILE + +dnl Check whether bundled libevent shall not be used +AC_NETATALK_LIBEVENT + +dnl Check whether bundled tdb shall be used +AC_NETATALK_TDB + +dnl Check for Tracker +AC_NETATALK_SPOTLIGHT + +dnl libatalk API checks +AC_DEVELOPER + +dnl Check for dtrace +AC_NETATALK_DTRACE + +dnl Check for dbus-glib, for AFP stats on dbus +AC_NETATALK_DBUS_GLIB + +dnl FHS stuff has to be done last because it overrides other defaults +AC_NETATALK_FHS + +dnl netatalk lockfile path, must come after AC_NETATALK_FHS +AC_NETATALK_LOCKFILE + +dnl Check for Docbook and build documentation if found +AX_CHECK_DOCBOOK + +CPPFLAGS="-I\$(top_srcdir)/include -I\$(top_builddir)/include -I\$(top_srcdir) $CPPFLAGS" +UAMS_PATH="${uams_path}" + +AC_SUBST(LIBS) +AC_SUBST(CFLAGS) +AC_SUBST(UAMS_PATH) + +AM_CONDITIONAL(SOLARIS_MODULE, test x$solaris_module = xyes) +AM_CONDITIONAL(HAVE_LIBGCRYPT, test x$neta_cv_have_libgcrypt = xyes) +AM_CONDITIONAL(HAVE_OPENSSL, test x$neta_cv_have_openssl = xyes) +AM_CONDITIONAL(HAVE_ACLS, test x"$ac_cv_have_acls" = x"yes") +AM_CONDITIONAL(HAVE_LDAP, test x"$netatalk_cv_ldap" = x"yes") +AM_CONDITIONAL(USE_DHX, test x$neta_cv_compile_dhx = xyes) +AM_CONDITIONAL(USE_DHX2, test x$neta_cv_compile_dhx2 = xyes) +AM_CONDITIONAL(USE_RANDNUM, test x$neta_cv_have_openssl = xyes) +AM_CONDITIONAL(USE_PAM_SO, test x$use_pam_so = xyes) +AM_CONDITIONAL(USE_PAM, test x$netatalk_cv_install_pam = xyes) +AM_CONDITIONAL(BUILD_PAM, test x$compile_pam = xyes) +AM_CONDITIONAL(USE_PGP, test x$compile_pgp = xyes) +AM_CONDITIONAL(DEFAULT_HOOK, test x$neta_cv_have_libgcrypt != xyes && test x$neta_cv_have_openssl != xyes) +AM_CONDITIONAL(USE_BDB, test x$bdb_required = xyes) +AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes") +AM_CONDITIONAL(USE_SHADOWPW, test x$shadowpw = xyes) + +dnl Enable silent Automake rules if present +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +dnl --------------------- generate files +AC_OUTPUT([Makefile + bin/Makefile + bin/ad/Makefile + bin/afppasswd/Makefile + bin/cnid/Makefile + bin/cnid/cnid2_create + bin/megatron/Makefile + bin/misc/Makefile + config/Makefile + config/pam/Makefile + contrib/Makefile + contrib/macusers/Makefile + contrib/macusers/macusers + contrib/shell_utils/Makefile + contrib/shell_utils/apple_dump + contrib/shell_utils/asip-status.pl + distrib/Makefile + distrib/config/Makefile + distrib/config/netatalk-config + distrib/initscripts/Makefile + distrib/m4/Makefile + doc/Makefile + doc/html.xsl + doc/man.xsl + doc/manual/Makefile + doc/manual/manual.xml + doc/manpages/Makefile + doc/manpages/man1/Makefile + doc/manpages/man5/Makefile + doc/manpages/man8/Makefile + etc/Makefile + etc/afpd/Makefile + etc/cnid_dbd/Makefile + etc/netatalk/Makefile + etc/spotlight/Makefile + etc/uams/Makefile + include/Makefile + include/atalk/Makefile + libatalk/Makefile + libatalk/acl/Makefile + libatalk/adouble/Makefile + libatalk/bstring/Makefile + libatalk/cnid/Makefile + libatalk/cnid/cdb/Makefile + libatalk/cnid/last/Makefile + libatalk/cnid/dbd/Makefile + libatalk/cnid/tdb/Makefile + libatalk/cnid/mysql/Makefile + libatalk/compat/Makefile + libatalk/dsi/Makefile + libatalk/iniparser/Makefile + libatalk/talloc/Makefile + libatalk/tdb/Makefile + libatalk/unicode/Makefile + libatalk/unicode/charsets/Makefile + libatalk/util/Makefile + libatalk/vfs/Makefile + macros/Makefile + man/Makefile + man/man1/Makefile + man/man1/ad.1 + man/man1/afpldaptest.1 + man/man1/afppasswd.1 + man/man1/afpstats.1 + man/man1/apple_dump.1 + man/man1/asip-status.pl.1 + man/man1/dbd.1 + man/man1/macusers.1 + man/man1/netatalk-config.1 + man/man1/uniconv.1 + man/man5/Makefile + man/man5/afp.conf.5 + man/man5/afp_signature.conf.5 + man/man5/afp_voluuid.conf.5 + man/man5/extmap.conf.5 + man/man8/Makefile + man/man8/afpd.8 + man/man8/cnid_dbd.8 + man/man8/cnid_metad.8 + man/man8/netatalk.8 + test/Makefile + test/afpd/Makefile + ], + [chmod a+x distrib/config/netatalk-config contrib/shell_utils/apple_*] +) + +AC_NETATALK_LIBS_SUMMARY +AC_NETATALK_CONFIG_SUMMARY diff --git a/contrib/Makefile.am b/contrib/Makefile.am new file mode 100644 index 0000000..3c07664 --- /dev/null +++ b/contrib/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for contrib/ + +SUBDIRS = macusers shell_utils diff --git a/contrib/Makefile.in b/contrib/Makefile.in new file mode 100644 index 0000000..e184576 --- /dev/null +++ b/contrib/Makefile.in @@ -0,0 +1,706 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for contrib/ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = contrib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = macusers shell_utils +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign contrib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign contrib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# 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/contrib/macusers/Makefile.am b/contrib/macusers/Makefile.am new file mode 100644 index 0000000..4d2c294 --- /dev/null +++ b/contrib/macusers/Makefile.am @@ -0,0 +1,5 @@ +# Makefile for contrib/macusers/ + +EXTRA_DIST = macusers.in README.macusers + +bin_SCRIPTS = macusers diff --git a/contrib/macusers/Makefile.in b/contrib/macusers/Makefile.in new file mode 100644 index 0000000..7589c9f --- /dev/null +++ b/contrib/macusers/Makefile.in @@ -0,0 +1,590 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for contrib/macusers/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = contrib/macusers +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/macusers.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = macusers +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" +SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = macusers.in README.macusers +bin_SCRIPTS = macusers +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign contrib/macusers/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign contrib/macusers/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +macusers: $(top_builddir)/config.status $(srcdir)/macusers.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binSCRIPTS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binSCRIPTS + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binSCRIPTS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-binSCRIPTS + + +# 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/contrib/macusers/README.macusers b/contrib/macusers/README.macusers new file mode 100644 index 0000000..b34a194 --- /dev/null +++ b/contrib/macusers/README.macusers @@ -0,0 +1,4 @@ +This script is very similar to the nu script, but it shows more detailed +information. However, since ps and lsof outputs vary, it may need some +modifications to work in Unixes other than Red Hat linux. + diff --git a/contrib/macusers/macusers.in b/contrib/macusers/macusers.in new file mode 100644 index 0000000..7366a8b --- /dev/null +++ b/contrib/macusers/macusers.in @@ -0,0 +1,134 @@ +#!@PERL@ + +use strict; +use Socket; +use File::Basename; +use vars qw($MAIN_PID $NETATALK_PROCESS $AFPD_PROCESS $PS_STR $MATCH_STR $ASIP_PORT_NO $ASIP_PORT $LSOF); + +# Written for linux; may have to be modified for your brand of Unix. +# Support for FreeBSD added by Joe Clarke . +# Support Solaris added by Frank Lahm . +# Support has also been added for 16 character usernames. + +if ($ARGV[0] =~ /^(-v|-version|--version)$/ ) { + printf ("%s \(Netatalk @NETATALK_VERSION@\)\n", basename($0)); + exit(1); +} elsif ($ARGV[0] =~ /^(-h|-help|--help)$/ ) { + printf ("usage: %s \[-v|-version|--version|-h|-help|--help\]\n", basename($0)); + printf ("Show users connecting via AFP\n"); + exit(1); +} + +$NETATALK_PROCESS = "netatalk"; +$AFPD_PROCESS = "afpd"; +if ($^O eq "freebsd" || $^O eq "openbsd") { + $PS_STR = "-awwxouser,pid,ppid,start,command"; + $MATCH_STR = '(\w+)\s+(\d+)\s+(\d+)\s+([\d\w:]+)'; +} elsif ($^O eq "solaris") { + $PS_STR = "-eo user,pid,ppid,c,stime,tty,time,comm"; + $MATCH_STR = '\s*(\w+)\s+(\d+)\s+(\d+)\s+\d+\s+([\d\w:]+)'; +} else { + $PS_STR = "-eo user:32,pid,ppid,c,stime,tty,time,cmd"; + $MATCH_STR = '\s*(\w+)\s+(\d+)\s+(\d+)\s+\d+\s+([\d\w:]+)'; +} +$ASIP_PORT = "afpovertcp"; +$ASIP_PORT_NO = 548; + +# Change to 0 if you don't have lsof +$LSOF = 1; +my %mac = (); + +if ($^O eq "freebsd") { + open(SOCKSTAT, "sockstat -4 | grep $AFPD_PROCESS | grep -v grep |"); + + while () { + next if ($_ !~ /$AFPD_PROCESS/); + $_ =~ + /\S+\s+\S+\s+(\d+)\s+\d+\s+[\w\d]+\s+[\d\.:]+\s+([\d\.]+)/; + my ($pid, $addr, $host); + $pid = $1; + $addr = $2; + $host = gethostbyaddr(pack('C4', split (/\./, $addr)), AF_INET); + ($host) = ( $host =~ /(^(\d+\.){3}\d+|[\w\d\-]+)/ ); + $mac{$pid} = $host; + } + print + "PID UID Username Name Logintime Mac\n"; + close(SOCKSTAT); +} elsif ($^O eq "solaris") { + if ($< != 0) { + print "must be run as root\n"; + exit(1); + } + print "PID UID Username Name Logintime Mac\n"; +} elsif ($LSOF == 1) { + open(LSOF, "lsof -i :$ASIP_PORT |"); + + while () { + next if ($_ !~ /$ASIP_PORT/); + $_ =~ /\w+\s+(\d+).*->([\w\.-]+).*/; + my ($pid, $host); + $pid = $1; + $host = $2; + ($host) = ( $host =~ /(^(\d+\.){3}\d+|[\w\d\-]+)/ ); + $mac{$pid} = $host; + } + print + "PID UID Username Name Logintime Mac\n"; + close(LSOF); +} else { + print + "PID UID Username Name Logintime\n"; +} + +open(PS, "ps $PS_STR |") || die "Unable to open a pipe to ``ps''"; + +$MAIN_PID = 1; +while () { + next if ($_ !~ /$NETATALK_PROCESS/); + my ($user, $pid, $ppid, $time, $name, $uid, $t, $ip); + $_ =~ /$MATCH_STR/; + $MAIN_PID = $2; +} + +close(PS); +open(PS, "ps $PS_STR |") || die "Unable to open a pipe to ``ps''"; + +while () { + next if ($_ !~ /$AFPD_PROCESS/); + my ($user, $pid, $ppid, $time, $name, $uid, $t, $ip); + $_ =~ /$MATCH_STR/; + $user = $1; + $pid = $2; + $ppid = $3; + $time = $4; + + if ($ppid != $MAIN_PID) { + if ($^O eq "solaris") { + open(PFILES, "pfiles $pid |"); + while () { + next if ($_ !~ /port: $ASIP_PORT_NO/); + while () { + next if ($_ !~ /peername/); + if ($_ =~ /AF_INET (.*) port/) { + $ip = $1; + if ($ip =~ /::ffff:(.*)/ ) { + $ip = $1; + } + } + $mac{$pid} = $ip; + last; + } + last; + } + close(PFILES); + } + + ($t, $t, $uid, $t, $t, $t, $name, $t, $t) = getpwnam($user); + ($name) = ( $name =~ /(^[^,]+)/ ); + printf "%-8d %-8d %-16s %-20s %-9s %s\n", $pid, $uid, $user, + $name, $time, $mac{$pid}; + } +} + +close(PS); diff --git a/contrib/shell_utils/Makefile.am b/contrib/shell_utils/Makefile.am new file mode 100644 index 0000000..a851322 --- /dev/null +++ b/contrib/shell_utils/Makefile.am @@ -0,0 +1,23 @@ +# Makefile for contrib/shell_utils/ + +pkgconfdir = @PKGCONFDIR@ + +GENERATED_FILES = +TEMPLATE_FILES = +PERLSCRIPTS = \ + asip-status.pl \ + apple_dump + +SUFFIXES = .tmpl . + +.tmpl: + sed -e s@:BINDIR:@${bindir}@ \ + -e s@:SBINDIR:@${sbindir}@ \ + -e s@:ETCDIR:@${pkgconfdir}@ \ + <$< >$@ + +CLEANFILES = $(GENERATED_FILES) + +bin_SCRIPTS = $(PERLSCRIPTS) $(GENERATED_FILES) afpstats + +EXTRA_DIST = $(TEMPLATE_FILES) make-casetable.pl make-precompose.h.pl afpstats fce_ev_script.sh diff --git a/contrib/shell_utils/Makefile.in b/contrib/shell_utils/Makefile.in new file mode 100644 index 0000000..e45fde4 --- /dev/null +++ b/contrib/shell_utils/Makefile.in @@ -0,0 +1,609 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for contrib/shell_utils/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = contrib/shell_utils +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/apple_dump.in $(srcdir)/asip-status.pl.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = apple_dump asip-status.pl +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" +SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgconfdir = @PKGCONFDIR@ +GENERATED_FILES = +TEMPLATE_FILES = +PERLSCRIPTS = \ + asip-status.pl \ + apple_dump + +SUFFIXES = .tmpl . +CLEANFILES = $(GENERATED_FILES) +bin_SCRIPTS = $(PERLSCRIPTS) $(GENERATED_FILES) afpstats +EXTRA_DIST = $(TEMPLATE_FILES) make-casetable.pl make-precompose.h.pl afpstats fce_ev_script.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .tmpl . +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign contrib/shell_utils/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign contrib/shell_utils/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +apple_dump: $(top_builddir)/config.status $(srcdir)/apple_dump.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +asip-status.pl: $(top_builddir)/config.status $(srcdir)/asip-status.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binSCRIPTS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binSCRIPTS + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binSCRIPTS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-binSCRIPTS + + +.tmpl: + sed -e s@:BINDIR:@${bindir}@ \ + -e s@:SBINDIR:@${sbindir}@ \ + -e s@:ETCDIR:@${pkgconfdir}@ \ + <$< >$@ + +# 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/contrib/shell_utils/afpstats b/contrib/shell_utils/afpstats new file mode 100755 index 0000000..8c5413c --- /dev/null +++ b/contrib/shell_utils/afpstats @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +usage = """Usage: +python afpstats.py +""" + +import sys +from traceback import print_exc +import dbus + +def main(): + bus = dbus.SystemBus() + + try: + remote_object = bus.get_object("org.netatalk.AFPStats", + "/org/netatalk/AFPStats") + + except dbus.DBusException: + print_exc() + sys.exit(1) + + iface = dbus.Interface(remote_object, "org.netatalk.AFPStats") + + reply = iface.GetUsers() + for name in reply: + print name + +if __name__ == '__main__': + main() diff --git a/contrib/shell_utils/apple_dump.in b/contrib/shell_utils/apple_dump.in new file mode 100755 index 0000000..30dbb42 --- /dev/null +++ b/contrib/shell_utils/apple_dump.in @@ -0,0 +1,915 @@ +#!@PERL@ +# +# AppleSingle/AppleDouble dump +# +# (c) 2009-2012 by HAT +# +# 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. +# + +# +# References: +# +# Applesingle and AppleDouble format internals (version 1) +# http://users.phg-online.de/tk/netatalk/doc/Apple/v1/ +# +# AppleSingle/AppleDouble Formats for Foreign Files Developer's Note (version2) +# http://users.phg-online.de/tk/netatalk/doc/Apple/v2/AppleSingle_AppleDouble.pdf +# +# Inside Macintosh: Macintosh Toolbox Essentials / +# Chapter 7 - Finder Interface / Finder Interface Reference +# http://developer.apple.com/legacy/mac/library/documentation/mac/toolbox/Toolbox-463.html +# +# Finder Interface Reference +# http://developer.apple.com/legacy/mac/library/documentation/Carbon/Reference/Finder_Interface/Reference/reference.html +# +# Technical Note TN1150 HFS Plus Volume Format +# http://developer.apple.com/mac/library/technotes/tn/tn1150.html#FinderInfo +# +# CarbonHeaders source +# http://www.opensource.apple.com/source/CarbonHeaders/CarbonHeaders-8A428/Finder.h +# http://www.opensource.apple.com/source/CarbonHeaders/CarbonHeaders-9A581/Finder.h +# +# Xcode 3.2.1 +# /usr/bin/SetFile +# /usr/bin/GetFileInfo +# +# Mac OS X 10.6.2 kernel source +# http://www.opensource.apple.com/source/xnu/xnu-1486.2.11/bsd/vfs/vfs_xattr.c +# + +use File::Basename; +use File::Spec; +use File::Temp qw /tempfile/; +use bigint; # require perl >= 5.8 +use IPC::Open2 qw /open2/; + +# check command for extended attributes ----------------------------------- + +if ( 0 == system("which getfattr > /dev/null 2>&1")) { + $eacommand = 1; +} elsif (0 == system("which attr > /dev/null 2>&1")) { + $eacommand = 2; +} elsif (0 == system("which runat > /dev/null 2>&1")) { + $eacommand = 3; +} elsif (0 == system("which getextattr > /dev/null 2>&1")) { + $eacommand = 4; +} else { + $eacommand = 0; +} + +#printf ( "eacommand = %d\n", $eacommand ); # debug + +# parse command line ----------------------------------------------- + +$stdinputmode = 0; +$eaoption = 0; +$finderinfo = 0; # 0: unknown 1: file 2: directory +while ($arg = shift @ARGV) +{ + if ($arg =~ /^(-h|-help|--help)$/ ) { + printf ("usage: %s [-a] [FILE|DIR]\n" ,basename($0)); + printf (" or: %s -e FILE|DIR\n" ,basename($0)); + printf (" or: %s -f [FILE]\n" ,basename($0)); + printf (" or: %s -d [FILE]\n" ,basename($0)); + printf (" or: %s -h|-help|--help\n" ,basename($0)); + printf (" or: %s -v|-version|--version\n" ,basename($0)); + printf ("Dump AppleSingle/AppleDouble format data.\n"); + printf ("With no FILE|DIR, or when FILE|DIR is -, read standard input.\n"); + printf ("\n"); + printf (" -a (default) Dump a AppleSingle/AppleDouble data for FILE or DIR\n"); + printf (" automatically.\n"); + printf (" If FILE is not AppleSingle/AppleDouble format,\n"); + printf (" look for extended attribute, .AppleDouble/FILE and ._FILE.\n"); + printf (" If DIR, look for extended attribute,\n"); + printf (" DIR/.AppleDouble/.Parent and ._DIR.\n"); + printf (" -e Dump extended attribute of FILE or DIR\n"); + printf (" -f Dump FILE. Assume FinderInfo to be FileInfo.\n"); + printf (" -d Dump FILE. Assume FinderInfo to be DirInfo.\n"); + printf (" -h,-help,--help Display this help and exit\n"); + printf (" -v,-version,--version Show version and exit\n"); + printf ("\n"); + printf ("There is no way to detect whether FinderInfo is FileInfo or DirInfo.\n"); + printf ("By default, %s examins whether file or directory,\n" ,basename($0)); + printf ("a parent directory is .AppleDouble, filename is ._*, filename is .Parent,\n"); + printf ("and so on.\n"); + printf ("If setting option -e, -f or -d, %s assume FinderInfo and doesn't look for\n"); + printf ("another file.\n"); + exit 1; + } elsif ($arg =~ /^(-v|-version|--version)$/ ) { + printf ("%s \(Netatalk @NETATALK_VERSION@\)\n", basename($0)); + exit 1; + } elsif ($arg eq "-a") { + $finderinfo = 0; + } elsif ($arg eq "-e") { + if ($eacommand == 0) { + printf (STDERR "%s: unsupported option -e\n", basename($0)); + printf (STDERR "because neither getfattr, attr, runat nor getextattr is found.\n"); + exit 1; + } + $eaoption = 1; + } elsif ($arg eq "-f") { + $finderinfo = 1; + } elsif ($arg eq "-d") { + $finderinfo = 2; + } elsif ($arg eq "-") { + $stdinputmode = 1; + } elsif ($arg =~ /^-/) { + printf (STDERR "%s: invalid option %s\n", basename($0), $arg); + printf (STDERR "Try \`%s\ -h' for more information.\n", basename($0)); + exit 1; + } else { + $afile = $arg; + } +} + +if (!($afile)) { + $stdinputmode = 1; +} elsif (!( -e $afile)) { + printf (STDERR "\"%s\" is not found.\n", $afile); + exit 1; +} + +# detect FinderInfo, and search AppleSingle/AppleDouble file -------------- + +$abspath = File::Spec->rel2abs($afile); +($basename, $path, $ext) = fileparse($abspath); + +if ( $stdinputmode == 1) { + ($eatempfh, $openfile) = tempfile(UNLINK => 1); + system("cat - > $openfile"); + close($eatempfh); + $openmessage = "Dumping Standard Input...\n"; +} elsif ( $eaoption == 1 ) { + if ( -f $afile ) { + $finderinfo = 1; + } elsif ( -d $afile ) { + $finderinfo = 2; + } else { + printf (STDERR "unknown error: %s\n", $afile); + exit 1; + } + if ( 0 == checkea($afile) ) { + printf (STDERR "\"%s\"'s extended attribute is not found\n", $afile); + exit 1; + } + $openfile = eaopenfile($afile); + $openmessage = "Dumping \"$afile\"'s extended attribute...\n"; +} elsif ( $finderinfo != 0 ) { + $openfile = $afile; + $openmessage = "Dumping \"$openfile\"...\n"; +} elsif ( -f $afile ) { + if ( $basename eq ".Parent") { + $finderinfo = 2; + } elsif ( $path =~ /\/.AppleDouble\/$/ ) { + $finderinfo = 1; + } elsif ( $basename =~ /^._/ ) { + if ( -f $path.substr($basename, 2) ) { + $finderinfo = 1; + } elsif ( -d $path.substr($basename, 2) ) { + $finderinfo = 2; + } + } + if (!open(INFILE, "<$afile")) { + printf (STDERR "cannot open %s\n", $afile); + exit 1; + } + read(INFILE,$buf,4); + $val = unpack("N", $buf ); + close(INFILE); + if ($val == 0x00051600 || $val == 0x00051607) { + $openfile = $afile; + $openmessage = "Dumping \"$openfile\"...\n"; + } else { + printf ("\"%s\" is not AppleSingle/AppleDouble format.\n", $afile); + $finderinfo = 1; + $adcount = 0; + $netatalkfile = $path.".AppleDouble/".$basename; + $osxfile = $path."._".$basename; + + if ( 1 == checkea($afile) ) { + printf ("\"%s\"\'s extended attribute is found.\n", $afile); + $adcount++; + $openfile = eaopenfile($afile); + $openmessage = "Dumping \"$afile\"'s extended attribute...\n"; + } + if ( -e $netatalkfile ) { + printf ("\"%s\" is found.\n", $netatalkfile); + $adcount++; + $openfile = $netatalkfile; + $openmessage = "Dumping \"$openfile\"...\n"; + } + if ( -e $osxfile ) { + printf ("\"%s\" is found.\n", $osxfile); + $adcount++; + $openfile = $osxfile; + $openmessage = "Dumping \"$openfile\"...\n"; + } + if ( $adcount == 0 ) { + printf ("AppleSingle/AppleDouble data is not found.\n"); + exit 1; + } + if ( $adcount != 1 ) { + printf ("Specify any one.\n"); + exit 1; + } + } +} elsif ( -d $afile) { + printf ("\"%s\" is a directory.\n", $afile); + $finderinfo = 2; + $adcount = 0; + $netatalkfile = $path.$basename."/.AppleDouble/.Parent"; + $osxfile = $path."._".$basename; + + if ( 1 == checkea($afile) ) { + printf ("\"%s\"\'s extended attribute is found.\n", $afile); + $adcount++; + $openfile = eaopenfile($afile); + $openmessage = "Dumping \"$afile\"'s extended attribute...\n"; + } + if ( -e $netatalkfile ) { + printf ("\"%s\" is found.\n", $netatalkfile); + $adcount++; + $openfile= $netatalkfile; + $openmessage = "Dumping \"$openfile\"...\n"; + } + if ( -e $osxfile ) { + printf ("\"%s\" is found.\n", $osxfile); + $adcount++; + $openfile = $osxfile; + $openmessage = "Dumping \"$openfile\"...\n"; + } + if ( $adcount == 0 ) { + printf ("AppleSingle/AppleDouble data is not found.\n"); + exit 1; + } + if ( $adcount != 1 ) { + printf ("Specify any one.\n"); + exit 1; + } +} else { + printf (STDERR "unknown error: %s\n", $afile); + exit 1; +} + +if (!open(INFILE, "<$openfile")) { + printf (STDERR "cannot open %s\n", $openfile); + exit 1; +} + +printf ($openmessage); + +#Dump -------------------------------------------------------- + +# Magic Number ----------------------------------------------- + +print "-------------------------------------------------------------------------------\n"; + +read(INFILE,$buf,4); +$val = unpack("N", $buf ); +printf("MagicNumber: %08X", $val); +if ( $val == 0x00051600 ) { + printf(" : AppleSingle"); +} +elsif ( $val == 0x00051607 ) { + printf(" : AppleDouble"); +} +else { + printf(" : Unknown" ); +} +print "\n"; + +# Version Number --------------------------------------------- + +read(INFILE,$buf,4); +$version = unpack("N", $buf ); +printf("Version : %08X", $version); +if ( $version == 0x00010000 ) { + printf(" : Version 1"); +} elsif ( $version == 0x00020000 ) { + printf(" : Version 2"); +} else { + printf(" : Unknown" ); +} +print "\n"; + +# v1:Home file system / v2:Filler ---------------------------- + +read(INFILE,$buf,16); +if ( $version == 0x00010000 ) { + print "HomeFileSys:"; +} else { + print "Filler :"; +} +hexdump($buf, 16, 16, " "); + +# Number of entities ----------------------------------------- + +read(INFILE,$buf,2); +$entnum = unpack("n", $buf ); +printf("Num. of ent: %04X ", $entnum); +printf(" : %d", $entnum); +print "\n"; + +# data ------------------------------------------------------- + +for ( $num = 0 ; $num < $entnum ; $num++) { + + seek(INFILE, ($num * 12 + 26), 0); + +# Entry --------------------------------------------------- + + read(INFILE,$buf,4); + $entid = unpack("N", $buf ); + print "\n-------------------------------------------------------------------------------\n"; + printf("Entry ID : %08X", $entid); + if ( $entid == 1 ) { printf(" : Data Fork"); } + elsif ( $entid == 2 ) { printf(" : Resource Fork"); } + elsif ( $entid == 3 ) { printf(" : Real Name"); } + elsif ( $entid == 4 ) { printf(" : Comment"); } + elsif ( $entid == 5 ) { printf(" : Icon, B&W"); } + elsif ( $entid == 6 ) { printf(" : Icon Color"); } + elsif ( $entid == 7 ) { printf(" : File Info"); } + elsif ( $entid == 8 ) { printf(" : File Dates Info"); } + elsif ( $entid == 9 ) { printf(" : Finder Info"); } + elsif ( $entid == 10 ) { printf(" : Macintosh File Info"); } + elsif ( $entid == 11 ) { printf(" : ProDOS File Info"); } + elsif ( $entid == 12 ) { printf(" : MS-DOS File Info"); } + elsif ( $entid == 13 ) { printf(" : Short Name"); } + elsif ( $entid == 14 ) { printf(" : AFP File Info"); } + elsif ( $entid == 15 ) { printf(" : Directory ID"); } + elsif ( $entid == 0x8053567E ) { printf(" : CNID (Netatalk Extended)"); } + elsif ( $entid == 0x8053594E ) { printf(" : DB stamp (Netatalk Extended)"); } + elsif ( $entid == 0x80444556 ) { printf(" : dev (Netatalk Extended)"); } + elsif ( $entid == 0x80494E4F ) { printf(" : inode (Netatalk Extended)"); } + else { printf(" : Unknown"); } + print "\n"; + +# Offset ------------------------------------------------- + + read(INFILE,$buf,4); + $ofst = unpack("N", $buf ); + printf("Offset : %08X", $ofst); + printf(" : %d ", $ofst); + +# Length ------------------------------------------------- + + read(INFILE,$buf,4); + $len = unpack("N", $buf ); + printf("\nLength : %08X", $len); + printf(" : %d", $len); + $quo = $len >> 4; + $rem = $len & 0xF; + print "\n"; + +# Dump for each Entry ID -------------------------------- + +# if ( $entid == 1 ) { ; } # Data Fork +# if ( $entid == 2 ) { ; } # Resource Fork +# if ( $entid == 3 ) { ; } # Real Name +# if ( $entid == 4 ) { ; } # Comment +# if ( $entid == 5 ) { ; } # Icon, B&W +# if ( $entid == 6 ) { ; } # Icon Color +# if ( $entid == 7 ) { ; } # File Info + if ( $entid == 8 ) { filedatesdump($ofst,$len); } + elsif ( $entid == 9 ) { finderinfodump($ofst,$len); } +# if ( $entid == 10 ) { ; } # Macintosh File Info +# if ( $entid == 11 ) { ; } # ProDOS File Info +# if ( $entid == 12 ) { ; } # MS-DOS File Info +# if ( $entid == 13 ) { ; } # Short Name +# if ( $entid == 14 ) { ; } # AFP File Info + elsif ( $entid == 15 ) { print "\n"; bedump($ofst,$len); } # Directory ID + elsif ( $entid == 0x8053567E ) { print "\n"; bedump($ofst,$len); ledump($ofst,$len); } # CNID (Netatalk Extended) + elsif ( $entid == 0x8053594E ) { print "\n"; bedump($ofst,$len); ledump($ofst,$len); } # DB stamp (Netatalk Extended) + elsif ( $entid == 0x80444556 ) { print "\n"; bedump($ofst,$len); ledump($ofst,$len); } # dev (Netatalk Extended) + elsif ( $entid == 0x80494E4F ) { print "\n"; bedump($ofst,$len); ledump($ofst,$len); } # inode (Netatalk Extended) + +# RAW Dump --------------------------------------------------- + + if ( ($quo > 0) || ($rem > 0)) { + print "\n"; + print "-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)\n"; + } + + seek(INFILE, $ofst, 0); + rawdump($quo, $rem); + +} + +close(INFILE); +exit 0; + +#sub ----------------------------------------------------------- + +sub filedatesdump { + my ($ofst, $len) = @_; + my ($datedata); + my ($i); + my ($datestr); + + @datetype =('create ', 'modify ', 'backup ', 'access '); + + seek(INFILE, $ofst, 0); + + print "\n"; + printf ("-DATE------: : (GMT) : (Local)\n"); + + for ( $i = 0 ; $i < 4 ; $i++) { + read(INFILE,$buf,4); + $datedata = unpack("N", $buf ); + if ($datedata < 0x80000000) { + $datestr = gmtime( $datedata + 946684800) + ." : " + .localtime( $datedata + 946684800); + } elsif ($datedata == 0x80000000) { + $datestr = "Unknown or Initial"; + } else { + $datestr = gmtime( $datedata - 3348282496) + ." : " + .localtime( $datedata - 3348282496); + } + printf ("%s : %08X : %s\n",$datetype[$i], $datedata, $datestr); + } +} + +sub finderinfodump { + my ($ofst, $len) = @_; + + seek(INFILE, $ofst, 0); + + if ($finderinfo == 0) { + print "\n"; + print "-NOTE------: cannot detect whether FInfo or DInfo. assume FInfo.\n"; + } + + if ($finderinfo == 0 || $finderinfo == 1) { + filefinderinfodump(); + } elsif ($finderinfo == 2) { + dirfinderinfodump(); + } else { + print STDERR "unknown FinderInfo type\n" + } + + if ($len > 32) { eadump(); } +} + +sub filefinderinfodump { + + print "\n"; + print "-FInfo-----:\n"; + + read(INFILE,$buf,4); + print "Type : "; + hexdump($buf, 4, 4, ""); + + read(INFILE,$buf,4); + print "Creator : "; + hexdump($buf, 4, 4, ""); + + flagsdump(); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Location v : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Location h : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + print "Fldr : "; + hexdump($buf, 2, 4, ""); + + print "\n"; + print "-FXInfo----:\n"; + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Rsvd|IconID: %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + print "Rsvd : "; + hexdump($buf, 2, 4, ""); + read(INFILE,$buf,2); + print "Rsvd : "; + hexdump($buf, 2, 4, ""); + read(INFILE,$buf,2); + print "Rsvd : "; + hexdump($buf, 2, 4, ""); + + xflagsdump(); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Rsvd|commnt: %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,4); + $val = unpack("N", $buf ); + printf("PutAway : %08X", $val); + printf(" : %d\n", $val>0x7FFFFFFF?$val-0x100000000:$val); # Why SInt32? + +} + +sub dirfinderinfodump { + + print "\n"; + print "-DInfo-----:\n"; + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Rect top : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Rect left : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Rect bottom: %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Rect right : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + flagsdump(); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Location v : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Location h : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + print "View : "; + hexdump($buf, 2, 4, ""); + + print "\n"; + print "-DXInfo----:\n"; + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Scroll v : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,2); + $val = unpack("n", $buf ); + printf("Scroll h : %04X", $val); + printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); + + read(INFILE,$buf,4); + $val = unpack("N", $buf ); + printf("Rsvd|OpnChn: %08X", $val); + printf(" : %d\n", $val>0x7FFFFFFF?$val-0x100000000:$val); # Why SInt32? + + xflagsdump(); + + read(INFILE,$buf,2); + print "Comment : "; + hexdump($buf, 2, 4, ""); + + read(INFILE,$buf,4); + $val = unpack("N", $buf ); + printf("PutAway : %08X", $val); + printf(" : %d\n", $val>0x7FFFFFFF?$val-0x100000000:$val); # Why SInt32? + +} +sub flagsdump { + + @colortype =('none', 'gray', 'green', 'purple', 'blue', 'yellow', 'red', 'orange'); + + read(INFILE,$buf,2); + $flags = unpack("n", $buf ); + printf ("isAlias : %d\n", ($flags >> 15) & 1); + printf ("Invisible : %d\n", ($flags >> 14) & 1); + printf ("hasBundle : %d\n", ($flags >> 13) & 1); + printf ("nameLocked : %d\n", ($flags >> 12) & 1); + printf ("Stationery : %d\n", ($flags >> 11) & 1); + printf ("CustomIcon : %d\n", ($flags >> 10) & 1); + printf ("Reserved : %d\n", ($flags >> 9) & 1); + printf ("Inited : %d\n", ($flags >> 8) & 1); + printf ("NoINITS : %d\n", ($flags >> 7) & 1); + printf ("Shared : %d\n", ($flags >> 6) & 1); + printf ("SwitchLaunc: %d\n", ($flags >> 5) & 1); + printf ("Hidden Ext : %d\n", ($flags >> 4) & 1); + printf ("color : %d%d%d : %s\n", ($flags >> 3) & 1, + ($flags >> 2) & 1, + ($flags >> 1) & 1, + @colortype[($flags & 0xE)>>1]); + printf ("isOnDesk : %d\n", ($flags >> 0) & 1); + +} + +sub xflagsdump { + + read(INFILE,$buf,2); + $flags = unpack("n", $buf ); + + if (($flags >> 15) == 1) { + print "Script : "; + hexdump($buf, 1, 4, ""); + } else { + printf ("AreInvalid : %d\n", ($flags >> 15) & 1); + printf ("unknown bit: %d\n", ($flags >> 14) & 1); + printf ("unknown bit: %d\n", ($flags >> 13) & 1); + printf ("unknown bit: %d\n", ($flags >> 12) & 1); + printf ("unknown bit: %d\n", ($flags >> 11) & 1); + printf ("unknown bit: %d\n", ($flags >> 10) & 1); + printf ("unknown bit: %d\n", ($flags >> 9) & 1); + } + + printf ("CustomBadge: %d\n", ($flags >> 8) & 1); + printf ("ObjctIsBusy: %d\n", ($flags >> 7) & 1); + printf ("unknown bit: %d\n", ($flags >> 6) & 1); + printf ("unknown bit: %d\n", ($flags >> 5) & 1); + printf ("unknown bit: %d\n", ($flags >> 4) & 1); + printf ("unknown bit: %d\n", ($flags >> 3) & 1); + printf ("RoutingInfo: %d\n", ($flags >> 2) & 1); + printf ("unknown bit: %d\n", ($flags >> 1) & 1); + printf ("unknown bit: %d\n", ($flags >> 0) & 1); + +} + +sub eadump { + + print "\n"; + print "-EA--------:\n"; + + read(INFILE,$buf,2); + print "pad : "; + hexdump($buf, 2, 4, ""); + + read(INFILE,$buf,4); + print "magic : "; + hexdump($buf, 4, 4, ""); + + read(INFILE,$buf,4); + $ea_debug_tag = unpack("N", $buf ); + printf("debug_tag : %08X", $ea_debug_tag); + printf(" : %d\n", $ea_debug_tag); + + read(INFILE,$buf,4); + $ea_total_size = unpack("N", $buf ); + printf("total_size : %08X", $ea_total_size); + printf(" : %d\n", $ea_total_size); + + read(INFILE,$buf,4); + $ea_data_start = unpack("N", $buf ); + printf("data_start : %08X", $ea_data_start); + printf(" : %d\n", $ea_data_start); + + read(INFILE,$buf,4); + $ea_data_length = unpack("N", $buf ); + printf("data_length: %08X", $ea_data_length); + printf(" : %d\n", $ea_data_length); + + read(INFILE,$buf,4); + print "reserved[0]: "; + hexdump($buf, 4, 4, ""); + + read(INFILE,$buf,4); + print "reserved[1]: "; + hexdump($buf, 4, 4, ""); + + read(INFILE,$buf,4); + print "reserved[2]: "; + hexdump($buf, 4, 4, ""); + + read(INFILE,$buf,2); + print "flags : "; + hexdump($buf, 2, 4, ""); + + read(INFILE,$buf,2); + $ea_num_attrs = unpack("n", $buf ); + printf("num_attrs : %04X", $ea_num_attrs); + printf(" : %d\n", $ea_num_attrs); + + $pos = tell(INFILE); + + for ($i = 0 ; $i < $ea_num_attrs ; $i++) { + + $pos = (($pos & 0x3) == 0) ? ($pos) : ((($pos >> 2) + 1) << 2); + seek(INFILE, $pos, 0); + + print "-EA ENTRY--:\n"; + + read(INFILE,$buf,4); + $ea_offset = unpack("N", $buf ); + printf("offset : %08X", $ea_offset); + printf(" : %d\n", $ea_offset); + + read(INFILE,$buf,4); + $ea_length = unpack("N", $buf ); + printf("length : %08X", $ea_length); + printf(" : %d\n", $ea_length); + + read(INFILE,$buf,2); + print "flags : "; + hexdump($buf, 2, 4, ""); + + read(INFILE,$buf,1); + $ea_namelen = unpack("C", $buf ); + printf("namelen : %02X", $ea_namelen); + printf(" : %d\n", $ea_namelen); + + $ea_namequo = $ea_namelen >> 4; + $ea_namerem = $ea_namelen & 0xF; + print "-EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)\n"; + rawdump($ea_namequo, $ea_namerem); + + $pos = tell(INFILE); + + seek(INFILE, $ea_offset, 0); + $ea_quo = $ea_length >> 4; + $ea_rem = $ea_length & 0xF; + print "-EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)\n"; + rawdump($ea_quo, $ea_rem); + } +} + +sub bedump { + my ($ofst, $len) = @_; + my ($i); + my ($value); + + seek(INFILE, $ofst, 0); + + printf("%2dbit-BE : ", $len * 8 ); + + $value = 0; + for ( $i=0 ; $i < $len ; $i++ ) { + read(INFILE,$buf,1); + $bytedata[$i] = unpack("C", $buf ); + $value += $bytedata[$i] << (($len - $i -1) * 8) ; + } + + for ( $i=0 ; $i < $len ; $i++ ) { + printf("%02X", $bytedata[$i]); + } + + printf(" : %s", $value); + print "\n"; +} + +sub ledump { + my ($ofst, $len) = @_; + my ($i); + my ($value); + + seek(INFILE, $ofst, 0); + + printf("%2dbit-LE : ", $len * 8 ); + + $value = 0; + for ( $i=0 ; $i < $len ; $i++ ) { + read(INFILE,$buf,1); + $bytedata[$len - $i - 1] = unpack("C", $buf ); + $value += $bytedata[$len - $i -1] << ($i * 8) ; + } + + for ( $i=0 ; $i < $len ; $i++ ) { + printf("%02X", $bytedata[$i]); + } + + printf(" : %s", $value); + print "\n"; +} + +sub rawdump { + my ($quo, $rem) = @_; + my ($addrs, $line, $buf); + + $addrs = 0; + for ( $line = 0 ; $line < $quo ; $line++) { + read(INFILE, $buf, 16); + printf ( "%08X :", $addrs); + hexdump($buf, 16, 16, " "); + $addrs = $addrs + 0x10; + } + if ( $rem != 0 ) { + read(INFILE, $buf, $rem); + printf ( "%08X :", $addrs); + hexdump($buf, $rem, 16, " "); + } +} + +sub hexdump { + my ($buf, $len, $col, $delimit) = @_; + my ($i); + + $hexstr = ""; + $ascstr = ""; + + for ( $i=0 ; $i < $len ; $i++ ) { + $val = substr($buf, $i, 1); + $ascval = ord($val); + $hexstr .= sprintf("%s%02X", $delimit, $ascval); + + if (($ascval < 32) || ( $ascval > 126 )) { + $val = "."; + } + $ascstr .= $val; + } + for ( ; $i < $col ; $i++) { + $hexstr .= " ".$delimit; + $ascstr .= " "; + } + + printf("%s : %s", $hexstr,$ascstr); + + print "\n"; +} + +sub checkea { + my ($file) = @_; + + if ( $eacommand == 1 ) { + open2(\*EALIST, \*EAIN, 'getfattr', $file) or die $@; + while() { + if ( $_ eq "user.org.netatalk.Metadata\n" ) { + close (EALIST, EAIN); + return 1; + } + } + close (EALIST, EAIN); + return 0; + } elsif ( $eacommand == 2 ) { + open2(\*EALIST, \*EAIN, 'attr', '-q', '-l', $file) or die $@; + while() { + if ( $_ eq "org.netatalk.Metadata\n" ) { + close (EALIST, EAIN); + return 1; + } + } + close (EALIST, EAIN); + return 0; + } elsif ( $eacommand == 3 ) { + open2(\*EALIST, \*EAIN, 'runat', $file, 'ls', '-1') or die $@; + while() { + if ( $_ eq "org.netatalk.Metadata\n" ) { + close (EALIST, EAIN); + return 1; + } + } + close (EALIST, EAIN); + return 0; + } elsif ( $eacommand == 4 ) { + open2(\*EALIST, \*EAIN, 'lsextattr', '-q', 'user', $file) or die $@; + while() { + $_ = "\t".$_; + if ( $_ =~ /\torg\.netatalk\.Metadata[\n\t]/ ) { + close (EALIST, EAIN); + return 1; + } + } + close (EALIST, EAIN); + return 0; + } else { + return 0; + } +} + +sub eaopenfile { + my ($file) = @_; + my @eacommands = (); + + if ( $eacommand == 1 ) { + @eacommands = ('getfattr', '--only-values', '-n', 'user.org.netatalk.Metadata', $file); + } elsif ( $eacommand == 2 ) { + @eacommands = ('attr', '-q', '-g', 'org.netatalk.Metadata', $file); + } elsif ( $eacommand == 3 ) { + @eacommands = ('runat', $file, 'cat', 'org.netatalk.Metadata',); + } elsif ( $eacommand == 4 ) { + @eacommands = ('getextattr', '-q', 'user', 'org.netatalk.Metadata', $file); + } else { + return ""; + } + + my ($eatempfh, $eatempfile) = tempfile(UNLINK => 1); + open2(my $ealist, my $eain, @eacommands) or die $@; + print $eatempfh $_ while(<$ealist>); + close($ealist, $eain); + close($eatempfh); + return $eatempfile; +} + +#EOF diff --git a/contrib/shell_utils/asip-status.pl.in b/contrib/shell_utils/asip-status.pl.in new file mode 100755 index 0000000..c4036a8 --- /dev/null +++ b/contrib/shell_utils/asip-status.pl.in @@ -0,0 +1,557 @@ +#!@PERL@ +# +# asip-status - send DSIGetStatus to an AppleShare IP file server (aka +# ASIP, aka AFP over TCP port 548). A returned UAM of +# "No User Authen" means that the server supports guest access. +# +# author: James W. Abendschan +# license: GPL - http://www.gnu.org/copyleft/gpl.html +# url: http://www.jammed.com/~jwa/hacks/security/asip/ +# Date: 7 May 1997 (v1.0) - original version +# see also: +# - http://developer.apple.com/techpubs/macos8/NetworkCommSvcs/AppleShare/ +# - http://www2.opendoor.com/asip/ (excellent Mac sharing / security site) +# +# todo: log in as guest & get a list of shares +# + +# +# This edition is a part of netatalk @NETATALK_VERSION@. +# + +use strict; +use IO::Socket; # sucks because Timeout doesn't + +my ($arg); +my ($hostport); +my ($host); +my ($port); + +while ($arg = shift @ARGV) +{ + $main::show_icon = 1 if ($arg eq "-i"); + $main::debug = 1 if ($arg eq "-d"); + $main::hexdump = 1 if ($arg eq "-x"); + $main::showver = 1 if ($arg eq "-v"); + $main::showver = 1 if ($arg eq "-version"); + $main::showver = 1 if ($arg eq "--version"); + $hostport = $arg if ($arg !~ /^-/); +} + +if ($main::showver ==1) +{ + print "$0\n"; + print "Original edition: 7 May 1997 \(v1.0\) James W. Abendschan\n"; + print "This edition is a part of Netatalk @NETATALK_VERSION@\n"; + exit(-1); +} + +if ($hostport eq "") +{ + print "usage: $0 [-d] [-i] [-x] hostname[:port]\n"; + print " $0 -v|-version|--version\n"; + print "Queries AFP servers for their capabilities.\n"; + print " -d: Enable debug output.\n"; + print " -i: Show icon if it exists.\n"; + print " -x: Enable hex dump output.\n"; + print " -v,-version,--version: Show version.\n"; + exit(-1); +} + +($host, $port) = split(/\:/, $hostport); +$port = "548" if ($port eq ""); + +my ($packet) = build_packet(); +my ($code) = sendpacket($host, $port, $packet); +exit $code; + + +sub build_packet +{ + my (@packet) = + ( + 0x00, # 0- request, 1-reply + 0x03, # 3- DSIGetStatus + 0xde, 0xad, 0x00, # request ID + 0x00, 0x00, 0x00, 0x00, # data field + 0x00, 0x00, 0x00, 0x00, # length of data stream header + 0x00, 0x00, 0x00, 0x00 # reserved + ); + + + my ($packet) = pack("C*", @packet); + + return $packet; + +} + +sub sendpacket +{ + my ($host, $port, $packet) = @_; + my ($b, $buf); + + print "opening $host:$port\n" if ($main::debug); + + my ($asip_sock) = IO::Socket::INET->new( + PeerAddr => $host, + PeerPort => $port, + Proto => 'tcp', + Type => SOCK_STREAM, + Timeout => 10 + ) || die "connect to $host failure: $!"; + $asip_sock->autoflush(1); + + print "sending packet\n" if ($main::debug); + + my ($count) = syswrite($asip_sock, $packet, length($packet)); + + if ($count != length($packet)) + { + print "only wrote $count of " . length($packet) . " bytes?\n"; + exit(-1); + } + + # reply can span multiple packets + + print "sysread: " if ($main::debug); + while (sysread($asip_sock, $b, 256)) + { + $buf .= $b; + print "." if ($main::debug); + } + + close ($asip_sock); + + print " read " . length($buf) . " bytes\n" if ($main::debug); + + if (length($buf) == 0) + { + print "empty reply packet?\n"; + return -2; + } + else + { + print "AFP reply from $host:$port\n"; + return (parse_packet($buf)); + } +} + + +sub parse_packet +{ + my ($buf) = shift @_; + my (@packet); + my ($i); + + hexdump($buf) if ($main::hexdump); + + for ($i=0;$i 0) && ($cmd == 3)) + { + my (@AFPpacket) = @packet[($edo+16)..($edo+16+$datalen)]; + return (parse_FPGetSrvrInfo(@AFPpacket)); + } + else + { + print "I don't know how to parse this type of packet.\n"; + return(2); + } +} + + + +sub parse_FPGetSrvrInfo() +{ + my (@packet) = @_; + my ($i); + + my ($machinetype_offset) = unpack("n", @packet[0] . @packet[1]); + print "Machine type offset in packet: $machinetype_offset\n" if ($main::debug); + my ($machinetype) = extract(1, $machinetype_offset, @packet); + print "Machine type: $machinetype\n"; + + my ($afpversioncount_offset) = unpack("n", @packet[2] . @packet[3]); + print "AFPversion count offset: $afpversioncount_offset\n" if ($main::debug); + my (@afpversions) = extract(0, $afpversioncount_offset, @packet); + print "AFP versions: " . join(",", @afpversions) . "\n"; + + my ($uamcount_offset) = unpack("n", @packet[4] . @packet[5]); + print "UAMcount offset: $uamcount_offset\n" if ($main::debug); + my (@uams) = extract(0, $uamcount_offset, @packet); + print "UAMs: " . join(",", @uams) . "\n"; + + my ($allow_guest) = 0; + $allow_guest = 1 if (grep(/No User Authen/, @uams)); + + # it would be cute to see the icon. + + my ($icon_offset) = unpack("n", @packet[6] . @packet[7]); + print "Volume Icon & Mask offset: $icon_offset\n" if ($main::debug); + print "Volume Icon & Mask: "; + if ($icon_offset) { + print "Yes\n"; + } else { + print "No\n"; + } + + my ($flags) = unpack("n", @packet[8] . @packet[9]); + my (@flags) = parse_afp_flags($flags); + + print "Flags: "; + print "$flags" if ($main::debug); + print "\n"; + print join("\n", @flags) . "\n"; + + # server name starts at offset+10, length byte first. + + my ($servername_len) = unpack("C1", @packet[10]); + my ($servername) = join("", @packet[11..(11+$servername_len-1)]); + print "Server name length: $servername_len\n" if ($main::debug); + print "Server name: $servername\n"; + + my ($offset) = 11 + $servername_len; + + # quietly ++ the $offset to account for the padding that happens + # in the reply packet if the field names don't align on an even boundary + + $offset++ if ($servername_len % 2 == 0); + + print "New offset: $offset\n" if ($main::debug); + + my ($signature_offset) = unpack("n2", @packet[$offset] . @packet[$offset+1]); + print "Signature offset: $signature_offset\n" if ($main::debug); + if ($signature_offset) + { + my ($signature) = join("", @packet[$signature_offset..$signature_offset+15]); + + print "Signature:\n"; + hexdump($signature); + } + + my ($network_address_count_offset) = unpack("n2", @packet[$offset+2] . @packet[$offset+3]); + print "Network address count offset: $network_address_count_offset\n" if ($main::debug); + + extract_network_address($network_address_count_offset, @packet); + + $offset += 4; + if ($flags & (1<<8)) { # Supports directory services + my ($directory_service_offset) = unpack("n2", @packet[$offset] . @packet[$offset+1]); + print "Directory service offset: $directory_service_offset\n" if ($main::debug); + if ($directory_service_offset) + { + my (@dirsvcs) = extract(0, $directory_service_offset, @packet); + while (@dirsvcs) + { + printf "Directory Service: %s\n", shift @dirsvcs; + } + } + $offset +=2; + } + + if ($flags & (1<<9)) { # Supports UTF8 servername + my ($utf8_name_offset) = unpack("n2", @packet[$offset] . @packet[$offset+1]); + print "UTF8 name offset: $utf8_name_offset\n" if ($main::debug); + if ($utf8_name_offset) + { + my ($utf8name) = extract(1, $utf8_name_offset+1, @packet); + print "UTF8 Servername: $utf8name\n"; + } + } + + draw_icon($icon_offset, @packet) if ($main::show_icon && $icon_offset); + + return $allow_guest; +} + +# getsrvbyname .. sorta .. + +sub getasipsrv +{ + my ($what, $code) = @_; + + if ($what eq "flags") + { + return "Request" if ($code == 0); + return "Reply" if ($code == 1); + } + + if ($what eq "command") + { + return "DSICloseSession" if ($code == 1); + return "DSICommand" if ($code == 2); + return "DSIGetStatus" if ($code == 3); + return "DSIOpenSession" if ($code == 4); + return "DSITickle" if ($code == 5); + return "DSIWrite" if ($code == 6); + return "DSIAttention" if ($code == 7); + } + return "[$what/$code] unknown"; +} + + +# return "counted" data at @packet[$offset] +# when called with a zero as the first argument, this will +# look in the packet for the count. Otherwise, it will +# assume I know what I'm doing. (hah, what a foolish function..) + +sub extract +{ + my ($count, $offset, @packet) = @_; + my ($i, $j); + my (@items, $data); + my ($hack); + + if ($count == 0) + { + ($count) = unpack("C", @packet[$offset]); + return if ($count == 0); + $offset++; + } + else + { + $hack = 1; + } + #print ">> extracting $count items from offset $offset\n"; + for ($i=0;$i<$count;$i++) + { + #print "Working on count $i\n"; + my ($len) = unpack("C1", @packet[$offset]); + $data = join("", @packet[$offset+1..$offset+$len]); + #print "$i. [$data] ($len)\n"; + push (@items, $data); + $offset = $offset + $len + 1; + #print "new offset is $offset\n"; + } + return $data if ($hack); + return @items; +} + +sub draw_icon +{ + my ($offset, @packet) = @_; + my ($cols); + my ($i, $j); + + # icons are 32x32 bitmaps; 128 byte icon + 128 byte mask + # to show the mask, change 128 to 256. + + for ($i=0;$i<128;$i++) + { + my ($c) = @packet[$i+$offset]; + my ($bin) = unpack ("B*", $c); + + for ($j=0;$j<8;$j++) + { + if (substr($bin, $j, 1)) + { + print "#"; + } + else + { + print " "; + } + } + $cols++; + if ($cols == 4) + { + $cols = 0; + print "\n"; + } + + } + print "\n"; +} + + +sub parse_afp_flags +{ + my ($flags) = shift @_; + my (@flags); + + # $flags is a 16 bit little-endian number + + push (@flags, " SupportsCopyFile") if ($flags & (1<<0)); + push (@flags, " SupportsChgPwd") if ($flags & (1<<1)); + push (@flags, " DontAllowSavePwd") if ($flags & (1<<2)); + push (@flags, " SupportsServerMessages") if ($flags & (1<<3)); + push (@flags, " SupportsServerSignature") if ($flags & (1<<4)); + push (@flags, " SupportsTCP/IP") if ($flags & (1<<5)); + push (@flags, " SupportsSrvrNotifications") if ($flags & (1<<6)); + push (@flags, " SupportsReconnect") if ($flags & (1<<7)); + push (@flags, " SupportsOpenDirectory") if ($flags & (1<<8)); + push (@flags, " SupportsUTF8Servername") if ($flags & (1<<9)); + push (@flags, " SupportsUUIDs") if ($flags & (1<<10)); + push (@flags, " SupportsExtSleep") if ($flags & (1<<11)); + push (@flags, " UnknownBit12") if ($flags & (1<<12)); + push (@flags, " UnknownBit13") if ($flags & (1<<13)); + push (@flags, " UnknownBit14") if ($flags & (1<<14)); + push (@flags, " SupportsSuperClient") if ($flags & (1<<15)); + + return @flags; +} + + +sub hexdump +{ + my ($buf) = @_; + my ($p, $c, $pc, $str); + my ($i); + + for ($i=0;$i 31) && ($c < 127)) + { + $str .= $p; + } + else + { + $str .= "."; + } + if ($pc == 16) + { + print " $str\n"; + undef $str; + $pc = 0; + } + } + print " " x (16 - $pc); + print " $str \n"; +} + + +sub extract_network_address +{ + my ($offset, @packet) = @_; + my ($count); + my ($i) = 0; + my ($data); + + # get the number of addresses + ($count) = unpack("C", @packet[$offset]); + return if ($count == 0); + $offset++; + + #print "\n>> extracting $count items from offset $offset\n"; + for ($i=0;$i<$count;$i++) + { + #print "Working on count $i\n"; + my ($len) = unpack("C1", @packet[$offset]); + #printf "len: %u\n",$len; + my ($type) = unpack("C1", @packet[$offset+1]); + #printf "type: %u\n",$type; + $data = join("", @packet[$offset+2..$offset+$len-1]); + #print "$i. [$data] ($len)\n"; + $offset = $offset + $len ; + #print "new offset is $offset\n"; + + + # 1st byte is 'tag' + # 1 - IP address; 4 bytes + # 2 - IP address (4) + port (2) + # 3 - DDP (2 bytes net, 1 byte node, 1 byte socket) + # 4 - DNS address + # 5 - IP address (4) + port (2), for SSH tunnel + # 6 - IPV6 address (16) + # 7 - IPV6 address (16) + port (2) + + my (@nap) = unpack("C*", $data); + + if ($type == 1) + { + # quad + my ($ip) = sprintf "%d.%d.%d.%d (TCP/IP address)", + $nap[0], $nap[1], @nap[2], @nap[3]; + + print "Network address: $ip\n"; + } + elsif ($type == 2) + { + # quad+port + my ($ipport) = sprintf "%d.%d.%d.%d:%d", + @nap[0], @nap[1], @nap[2], @nap[3], (@nap[4]*256 + @nap[5]); + print "Network address: $ipport (TCP/IP address and port)\n"; + } + elsif ($type == 3) + { + printf "Network address: %d.%d (ddp address)\n", + (@nap[0] * 256) + @nap[1], @nap[2]; + } + elsif ($type == 4) + { + print "Network address: $data (DNS address)\n"; + } + elsif ($type == 5) + { + # according to the specs this should be an IP address + # however, OSX Server uses the FQDN instead + print "Network address: $data (SSH tunnel address)\n"; + } + elsif ($type == 6 || $type == 7) + { + print "Network address: "; + my ($j) = 0; + for ( $j = 0; $j<=13; $j = $j+2) { + printf("%.2x%.2x:", @nap[$j], @nap[$j+1]); + } + printf("%.2x%.2x", @nap[14], @nap[15]); + if ($type == 7 ) { + printf(":%d", (@nap[16]*256) + @nap[17]); + print " (IPv6 address + port)\n"; + } + else { + print " (IPv6 address)\n"; + } + } + else + { + printf "unsupported address type: %u\n", $type; + } + + } +} diff --git a/contrib/shell_utils/fce_ev_script.sh b/contrib/shell_utils/fce_ev_script.sh new file mode 100644 index 0000000..8e3410c --- /dev/null +++ b/contrib/shell_utils/fce_ev_script.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +usage="$(basename $0) [-h] [-v version] [-e event] [-P path] [-S source path] -- FCE sample script + +where: + -h show this help text + -v version + -e event + -P path + -S source path for events like rename/move + -u username + -p pid + -i event ID +" + +while getopts ':hs:v:e:P:S:u:p:i:' option; do + case "$option" in + h) echo "$usage" + exit + ;; + v) version=$OPTARG + ;; + e) event=$OPTARG + ;; + P) path=$OPTARG + ;; + S) srcpath=$OPTARG + ;; + u) user=$OPTARG + ;; + p) pid=$OPTARG + ;; + i) evid=$OPTARG + ;; + ?) printf "illegal option: '%s'\n" "$OPTARG" >&2 + echo "$usage" >&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) + +printf "FCE Event: $event" >> /tmp/fce.log +if [ -n "$version" ] ; then + printf ", protocol: $version" >> /tmp/fce.log +fi +if [ -n "$evid" ] ; then + printf ", ID: $evid" >> /tmp/fce.log +fi +if [ -n "$pid" ] ; then + printf ", pid: $pid" >> /tmp/fce.log +fi +if [ -n "$user" ] ; then + echo -n ", user: $user" >> /tmp/fce.log +fi +if [ -n "$srcpath" ] ; then + echo -n ", source: $srcpath" >> /tmp/fce.log +fi +if [ -n "$path" ] ; then + echo -n ", path: $path" >> /tmp/fce.log +fi +printf "\n" >> /tmp/fce.log diff --git a/contrib/shell_utils/make-casetable.pl b/contrib/shell_utils/make-casetable.pl new file mode 100755 index 0000000..5d2a314 --- /dev/null +++ b/contrib/shell_utils/make-casetable.pl @@ -0,0 +1,324 @@ +#!/usr/bin/perl +# +# usage: make-casetable.pl +# make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c +# +# (c) 2011 by HAT +# +# 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. +# + +# See +# http://www.unicode.org/reports/tr44/ +# http://www.unicode.org/Public/UNIDATA/UnicodeData.txt + +# One block has 64 chars. +# +# BMP +# block 0 = dummy +# block 1 = U+0000 - U+003F +# block 2 = U+0040 - U+007F +# ..... +# block 1024 = U+FFC0 - U+FFFF +# block 1025 = dummy +# +# Surrogate Pair +# block 1024 = dummy +# block 1025 = U+010000 - U+01003F +# block 1026 = U+010040 - U+01007F +# ..... +# block 17408 = U+10FFC0 - U+10FFFF +# block 17409 = dummy +# +# Dummy block is for edge detection. +# If block include upper/lower chars, block_enable[]=1. + +use strict; +use warnings; + +our $code0; +our $Name1; +our $General_Category2; +our $Canonical_Combining_Class3; +our $Bidi_Class4; +our $Decomposition_Mapping5; +our $Numeric_Value6; +our $Numeric_Value7; +our $Numeric_Value8; +our $Bidi_Mirrored9; +our $Unicode_1_Name10; +our $ISO_Comment11; +our $Simple_Uppercase_Mapping12; +our $Simple_Lowercase_Mapping13; +our $Simple_Titlecase_Mapping14; + +our $hex_code0; +our $Mapping; +our $hex_Mapping; + +our $char; +our $sp; +our $block; + +our @table; +our @table_sp; + +our @block_enable; +our @block_enable_sp; + +our $table_no; +our $block_start; +our $block_end; +our $char_start; +our $char_end; + +open(CHEADER, ">$ARGV[1]"); +open(CSOURCE, ">$ARGV[2]"); + +printf (CHEADER "\/\*\n"); +printf (CHEADER "DO NOT EDIT BY HAND\!\!\!\n"); +printf (CHEADER "\n"); +printf (CHEADER "This file is generated by\n"); +printf (CHEADER " contrib/shell_utils/make-casetable.pl %s %s %s\n", $ARGV[0], $ARGV[1], $ARGV[2]); +printf (CHEADER "\n"); +printf (CHEADER "%s is got from\n", $ARGV[0]); +printf (CHEADER "http\:\/\/www.unicode.org\/Public\/UNIDATA\/UnicodeData.txt\n"); +printf (CHEADER "\*\/\n"); +printf (CHEADER "\n"); + +printf (CSOURCE "\/\*\n"); +printf (CSOURCE "DO NOT EDIT BY HAND\!\!\!\n"); +printf (CSOURCE "\n"); +printf (CSOURCE "This file is generated by\n"); +printf (CSOURCE " contrib/shell_utils/make-casetable.pl %s %s %s\n", $ARGV[0], $ARGV[1], $ARGV[2]); +printf (CSOURCE "\n"); +printf (CSOURCE "%s is got from\n", $ARGV[0]); +printf (CSOURCE "http\:\/\/www.unicode.org\/Public\/UNIDATA\/UnicodeData.txt\n"); +printf (CSOURCE "\*\/\n"); +printf (CSOURCE "\n"); +printf (CSOURCE "\#include \\n"); +printf (CSOURCE "\#include \\n"); +printf (CSOURCE "\#include \"%s\"\n", $ARGV[1]); +printf (CSOURCE "\n"); + +&make_array("upper"); +&make_array("lower"); + +printf (CHEADER "\/\* EOF \*\/\n"); +printf (CSOURCE "\/\* EOF \*\/\n"); + +close(CHEADER); +close(CSOURCE); + + +########################################################################### +sub make_array{ + + # init table ----------------------------------------------------- + + for ($char = 0 ; $char <= 0xFFFF ; $char++) { + $table[$char][0] = $char; # mapped char + $table[$char][1] = $char; # orig char + $table[$char][2] = ""; # char name + } + + for ($char = 0x10000 ; $char <= 0x10FFFF ; $char++) { + $sp = ((0xD800 - (0x10000 >> 10) + ($char >> 10)) << 16) + + (0xDC00 + ($char & 0x3FF)); + $table_sp[$char][0] = $sp; # mapped surrogate pair + $table_sp[$char][1] = $sp; # orig surrogate pair + $table_sp[$char][2] = $char; # mapped char + $table_sp[$char][3] = $char; # orig char + $table_sp[$char][4] = ""; # char name + } + + for ($block = 0 ; $block <= 1025 ; $block++) { + $block_enable[$block] = 0; + } + + $block_enable[1] = 1; # ASCII block is forcibly included + $block_enable[2] = 1; # in the array for Speed-Up. + + for ($block = 1024 ; $block <= 17409 ; $block++) { + $block_enable_sp[$block] = 0; + } + + # write data to table -------------------------------------------- + + open(UNICODEDATA, "<$ARGV[0]"); + + while () { + chop; + ( + $code0, + $Name1, + $General_Category2, + $Canonical_Combining_Class3, + $Bidi_Class4, + $Decomposition_Mapping5, + $Numeric_Value6, + $Numeric_Value7, + $Numeric_Value8, + $Bidi_Mirrored9, + $Unicode_1_Name10, + $ISO_Comment11, + $Simple_Uppercase_Mapping12, + $Simple_Lowercase_Mapping13, + $Simple_Titlecase_Mapping14 + ) = split(/\;/); + + if ($_[0] eq "upper") { + $Mapping = $Simple_Uppercase_Mapping12; + } elsif ($_[0] eq "lower") { + $Mapping = $Simple_Lowercase_Mapping13; + } else { + exit(1); + } + + next if ($Mapping eq ""); + + $hex_code0 = hex($code0); + $hex_Mapping = hex($Mapping); + + if ($hex_code0 <= 0xFFFF) { + $table[$hex_code0][0] = $hex_Mapping; + #table[$hex_code0][1] already set + $table[$hex_code0][2] = $Name1; + $block_enable[($hex_code0 / 64) +1] = 1; + } else { + $sp = ((0xD800 - (0x10000 >> 10) + ($hex_Mapping >> 10)) << 16) + + (0xDC00 + ($hex_Mapping & 0x3FF)); + $table_sp[$hex_code0][0] = $sp; + #table_sp[$hex_code0][1] already set + $table_sp[$hex_code0][2] = $hex_Mapping; + #table_sp[$hex_code0][3] already set + $table_sp[$hex_code0][4] = $Name1; + $block_enable_sp[($hex_code0 / 64) +1] = 1; + } + } + + close(UNICODEDATA); + + # array for BMP -------------------------------------------------- + + printf(CSOURCE "\/*******************************************************************\n"); + printf(CSOURCE " Convert a wide character to %s case.\n", $_[0]); + printf(CSOURCE "*******************************************************************\/\n"); + printf(CSOURCE "ucs2\_t to%s\_w\(ucs2\_t val\)\n", $_[0]); + printf(CSOURCE "{\n"); + + $table_no = 1; + + for ($block = 1 ; $block <= 1024 ; $block++) { + + # rising edge detection + if ($block_enable[$block - 1] == 0 && $block_enable[$block] == 1) { + $block_start = $block; + } + + # falling edge detection + if ($block_enable[$block] == 1 && $block_enable[$block + 1] == 0) { + $block_end = $block; + + $char_start = ($block_start -1)* 64; + $char_end = ($block_end * 64) -1; + + printf(CHEADER "static const uint16\_t %s\_table\_%d\[%d\] \= \{\n", + $_[0], $table_no, $char_end - $char_start +1); + + for ($char = $char_start ; $char <= $char_end ; $char++) { + printf(CHEADER " 0x%04X, /*U\+%04X*/ /*%s*/\n", + $table[$char][0], + $table[$char][1], + $table[$char][2] + ); + } + printf(CHEADER "\}\;\n"); + printf(CHEADER "\n"); + + if ($char_start == 0x0000) { + printf(CSOURCE " if \( val \<\= 0x%04X)\n", + $char_end); + printf(CSOURCE " return %s\_table\_%d\[val]\;\n", + $_[0], $table_no); + } else { + printf(CSOURCE " if \( val \>\= 0x%04X \&\& val \<\= 0x%04X)\n", + $char_start, $char_end); + printf(CSOURCE " return %s\_table\_%d\[val-0x%04X\]\;\n", + $_[0], $table_no, $char_start); + } + printf(CSOURCE "\n"); + + $table_no++; + } + } + + printf(CSOURCE "\treturn \(val\)\;\n"); + printf(CSOURCE "\}\n"); + printf(CSOURCE "\n"); + + # array for Surrogate Pair --------------------------------------- + + printf(CSOURCE "\/*******************************************************************\n"); + printf(CSOURCE " Convert a surrogate pair to %s case.\n", $_[0]); + printf(CSOURCE "*******************************************************************\/\n"); + printf(CSOURCE "uint32\_t to%s\_sp\(uint32\_t val\)\n", $_[0]); + printf(CSOURCE "{\n"); + + $table_no = 1; + + for ($block = 1025 ; $block <= 17408 ; $block++) { + + # rising edge detection + if ((($block_enable_sp[$block - 1] == 0) || ((($block - 1) & 0xF) == 0)) + && ($block_enable_sp[$block] == 1)) { + $block_start = $block; + } + + # falling edge detection + if (($block_enable_sp[$block] == 1) && + ((($block - 1) & 0xF == 0xF) || ($block_enable_sp[$block + 1] == 0))) { + $block_end = $block; + + $char_start = ($block_start -1)* 64; + $char_end = ($block_end * 64) -1; + + printf(CHEADER "static const uint32\_t %s\_table\_sp\_%d\[%d\] \= \{\n", + $_[0], $table_no, $char_end - $char_start +1); + + for ($char = $char_start ; $char <= $char_end ; $char++) { + printf(CHEADER " 0x%08X, /*0x%08X*/ /*U\+%06X*/ /*U\+%06X*/ /*%s*/\n", + $table_sp[$char][0], + $table_sp[$char][1], + $table_sp[$char][2], + $table_sp[$char][3], + $table_sp[$char][4] + ); + } + printf(CHEADER "\}\;\n"); + printf(CHEADER "\n"); + + printf(CSOURCE " if \( val \>\= 0x%08X \&\& val \<\= 0x%08X)\n", + $table_sp[$char_start][1], $table_sp[$char_end][1]); + printf(CSOURCE " return %s\_table\_sp\_%d\[val-0x%08X\]\;\n", + $_[0], $table_no, $table_sp[$char_start][1]); + printf(CSOURCE "\n"); + + $table_no++; + } + } + + printf(CSOURCE "\treturn \(val\)\;\n"); + printf(CSOURCE "\}\n"); + printf(CSOURCE "\n"); +} + +# EOF diff --git a/contrib/shell_utils/make-precompose.h.pl b/contrib/shell_utils/make-precompose.h.pl new file mode 100755 index 0000000..ad42d9c --- /dev/null +++ b/contrib/shell_utils/make-precompose.h.pl @@ -0,0 +1,260 @@ +#!/usr/bin/perl +# +# usage: make-precompose.h.pl UnicodeData.txt > precompose.h +# +# (c) 2008-2011 by HAT +# +# 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. +# + +# See +# http://www.unicode.org/Public/UNIDATA/UCD.html +# http://www.unicode.org/reports/tr15/ +# http://www.unicode.org/Public/*/ucd/UnicodeData*.txt +# http://www.unicode.org/Public/UNIDATA/UnicodeData.txt + + +# temp files for binary search (compose.TEMP, compose_sp.TEMP) ------------- + +open(UNICODEDATA, "<$ARGV[0]"); + +open(COMPOSE_TEMP, ">compose.TEMP"); +open(COMPOSE_SP_TEMP, ">compose_sp.TEMP"); + +while () { + chop; + ( + $code0, + $Name1, + $General_Category2, + $Canonical_Combining_Class3, + $Bidi_Class4, + $Decomposition_Mapping5, + $Numeric_Value6, + $Numeric_Value7, + $Numeric_Value8, + $Bidi_Mirrored9, + $Unicode_1_Name10, + $ISO_Comment11, + $Simple_Uppercase_Mapping12, + $Simple_Lowercase_Mapping13, + $Simple_Titlecase_Mapping14 + ) = split(/\;/); + + if (($Decomposition_Mapping5 ne "") && ($Decomposition_Mapping5 !~ /\ 0xFFFF) { + + $code0_sp_hi = 0xD800 - (0x10000 >> 10) + (hex($code0) >> 10); + $code0_sp_lo = 0xDC00 + (hex($code0) & 0x3FF); + + $base_sp_hi = 0xD800 - (0x10000 >> 10) + (hex($base) >> 10); + $base_sp_lo = 0xDC00 + (hex($base) & 0x3FF); + + $comb_sp_hi = 0xD800 - (0x10000 >> 10) + (hex($comb) >> 10); + $comb_sp_lo = 0xDC00 + (hex($comb) & 0x3FF); + + printf(COMPOSE_SP_TEMP "%s0x%04X%04X, 0x%04X%04X, 0x%04X%04X%s\/\* %s \*\/\n", + $leftbracket, $code0_sp_hi ,$code0_sp_lo, $base_sp_hi, $base_sp_lo, $comb_sp_hi, $comb_sp_lo, $rightbracket, $Name1); + + $leftbracket = "\/\*{ "; + $rightbracket =" },\*\/ "; + } + + printf(COMPOSE_TEMP "%s0x%08X, 0x%08X, 0x%08X%s\/\* %s \*\/\n", $leftbracket, hex($code0), hex($base), hex($comb), $rightbracket, $Name1); + + } +} + +close(UNICODEDATA); + +close(COMPOSE_TEMP); +close(COMPOSE_SP_TEMP); + +# macros for BMP (PRECOMP_COUNT, DECOMP_COUNT, MAXCOMBLEN) ---------------- + +open(COMPOSE_TEMP, ") { + if (m/^\/\*/) { + next; + } + $comp_table[$comp_count][0] = substr($_, 4, 10); + $comp_table[$comp_count][1] = substr($_, 16, 10); + $comp_count++; +} + +$maxcomblen = 2; # Hangul's maxcomblen is already 2. That is, VT. + +for ($i = 0 ; $i < $comp_count ; $i++) { + $base = $comp_table[$i][1]; + $comblen = 1; + $j = 0; + while ($j < $comp_count) { + if ($base ne $comp_table[$j][0]) { + $j++; + next; + } else { + $comblen++; + $base = $comp_table[$j][1]; + $j = 0; + } + } + $maxcomblen = ($maxcomblen > $comblen) ? $maxcomblen : $comblen; +} + +close(COMPOSE_TEMP); + +# macros for SP (PRECOMP_SP_COUNT,DECOMP_SP_COUNT, MAXCOMBSPLEN) ----------- + +open(COMPOSE_SP_TEMP, ") { + if (m/^\/\*/) { + next; + } + $comp_sp_table[$comp_sp_count][0] = substr($_, 4, 10); + $comp_sp_table[$comp_sp_count][1] = substr($_, 16, 10); + $comp_sp_count++; +} + +$maxcombsplen = 2; # one char have 2 codepoints, like a D8xx DCxx. + +for ($i = 0 ; $i < $comp_sp_count ; $i++) { + $base_sp = $comp_sp_table[$i][1]; + $comblen = 2; + $j = 0; + while ($j < $comp_sp_count) { + if ($base_sp ne $comp_sp_table[$j][0]) { + $j++; + next; + } else { + $comblen += 2; + $base_sp = $comp_sp_table[$j][1]; + $j = 0; + } + } + $maxcombsplen = ($maxcombsplen > $comblen) ? $maxcombsplen : $comblen; +} + +close(COMPOSE_SP_TEMP); + +# macro for buffer length (COMBBUFLEN) ------------------------------------- + +$combbuflen = ($maxcomblen > $maxcombsplen) ? $maxcomblen : $maxcombsplen; + +# sort --------------------------------------------------------------------- + +system("sort -k 3 compose.TEMP \> precompose.SORT"); +system("sort -k 2 compose.TEMP \> decompose.SORT"); + +system("sort -k 3 compose_sp.TEMP \> precompose_sp.SORT"); +system("sort -k 2 compose_sp.TEMP \> decompose_sp.SORT"); + +# print ------------------------------------------------------------------- + +print ("\/\* DO NOT EDIT BY HAND\!\!\! \*\/\n"); +print ("\/\* This file is generated by \*\/\n"); +printf ("\/\* contrib/shell_utils/make-precompose.h.pl %s \*\/\n", $ARGV[0]); +print ("\n"); +printf ("\/\* %s is got from \*\/\n", $ARGV[0]); +print ("\/\* http\:\/\/www.unicode.org\/Public\/UNIDATA\/UnicodeData.txt \*\/\n"); +print ("\n"); + +print ("\#define SBASE 0xAC00\n"); +print ("\#define LBASE 0x1100\n"); +print ("\#define VBASE 0x1161\n"); +print ("\#define TBASE 0x11A7\n"); +print ("\#define LCOUNT 19\n"); +print ("\#define VCOUNT 21\n"); +print ("\#define TCOUNT 28\n"); +print ("\#define NCOUNT 588 \/\* (VCOUNT \* TCOUNT) \*\/\n"); +print ("\#define SCOUNT 11172 \/\* (LCOUNT \* NCOUNT) \*\/\n"); +print ("\n"); + +printf ("\#define PRECOMP_COUNT %d\n", $comp_count); +printf ("\#define DECOMP_COUNT %d\n", $comp_count); +printf ("\#define MAXCOMBLEN %d\n", $maxcomblen); +print ("\n"); +printf ("\#define PRECOMP_SP_COUNT %d\n", $comp_sp_count); +printf ("\#define DECOMP_SP_COUNT %d\n", $comp_sp_count); +printf ("\#define MAXCOMBSPLEN %d\n", $maxcombsplen); +print ("\n"); +printf ("\#define COMBBUFLEN %d \/\* max\(MAXCOMBLEN\,MAXCOMBSPLEN\) \*\/\n", $combbuflen); +print ("\n"); + +print ("static const struct \{\n"); +print (" unsigned int replacement\;\n"); +print (" unsigned int base\;\n"); +print (" unsigned int comb\;\n"); +print ("\} precompositions\[\] \= \{\n"); + +system("cat precompose.SORT"); + +print ("\}\;\n"); +print ("\n"); + +print ("static const struct \{\n"); +print (" unsigned int replacement\;\n"); +print (" unsigned int base\;\n"); +print (" unsigned int comb\;\n"); +print ("\} decompositions\[\] \= \{\n"); + +system("cat decompose.SORT"); + +print ("\}\;\n"); +print ("\n"); + + + +print ("static const struct \{\n"); +print (" unsigned int replacement_sp\;\n"); +print (" unsigned int base_sp\;\n"); +print (" unsigned int comb_sp\;\n"); +print ("\} precompositions_sp\[\] \= \{\n"); + +system("cat precompose_sp.SORT"); + +print ("\}\;\n"); +print ("\n"); + +print ("static const struct \{\n"); +print (" unsigned int replacement_sp\;\n"); +print (" unsigned int base_sp\;\n"); +print (" unsigned int comb_sp\;\n"); +print ("\} decompositions_sp\[\] \= \{\n"); + +system("cat decompose_sp.SORT"); + +print ("\}\;\n"); +print ("\n"); + +print ("\/\* EOF \*\/\n"); + +# EOF diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..e1f51f4 --- /dev/null +++ b/depcomp @@ -0,0 +1,787 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2012-07-12.20; # UTC + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' "$nl" < "$tmpdepfile" | +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependent.h'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. + # However on + # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\': + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + # tcc 0.9.26 (FIXME still under development at the moment of writing) + # will emit a similar output, but also prepend the continuation lines + # with horizontal tabulation characters. + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form 'foo.o: dependent.h', + # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ + < "$tmpdepfile" > "$depfile" + sed ' + s/[ '"$tab"'][ '"$tab"']*/ /g + s/^ *// + s/ *\\*$// + s/^[^:]*: *// + /^$/d + /:$/d + s/$/ :/ + ' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + base=`echo "$source" | sed -e 's|^.*/||' -e 's/\.[-_a-zA-Z0-9]*$//'` + tmpdepfile="$base.d" + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir="$base.d-lock" + trap "echo '$0: caught signal, cleaning up...' >&2; rm -rf $lockdir" 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0 ; do + # mkdir is a portable test-and-set. + if mkdir $lockdir 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rm -rf $lockdir + break + else + ## the lock is being held by a different process, + ## wait until the winning process is done or we timeout + while test -d $lockdir && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test "$stat" = 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' "$nl" < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/distrib/Makefile.am b/distrib/Makefile.am new file mode 100644 index 0000000..765af27 --- /dev/null +++ b/distrib/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for distrib/ + +SUBDIRS = config initscripts m4 diff --git a/distrib/Makefile.in b/distrib/Makefile.in new file mode 100644 index 0000000..a59a914 --- /dev/null +++ b/distrib/Makefile.in @@ -0,0 +1,706 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for distrib/ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = distrib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = config initscripts m4 +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign distrib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign distrib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# 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/distrib/config/Makefile.am b/distrib/config/Makefile.am new file mode 100644 index 0000000..7f38719 --- /dev/null +++ b/distrib/config/Makefile.am @@ -0,0 +1,3 @@ +# Makefile for distrib/config/ + +bin_SCRIPTS = netatalk-config diff --git a/distrib/config/Makefile.in b/distrib/config/Makefile.in new file mode 100644 index 0000000..bfef27e --- /dev/null +++ b/distrib/config/Makefile.in @@ -0,0 +1,589 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for distrib/config/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = distrib/config +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/netatalk-config.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = netatalk-config +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" +SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +bin_SCRIPTS = netatalk-config +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign distrib/config/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign distrib/config/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +netatalk-config: $(top_builddir)/config.status $(srcdir)/netatalk-config.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binSCRIPTS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binSCRIPTS + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binSCRIPTS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-binSCRIPTS + + +# 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/distrib/config/netatalk-config.in b/distrib/config/netatalk-config.in new file mode 100644 index 0000000..5d9b576 --- /dev/null +++ b/distrib/config/netatalk-config.in @@ -0,0 +1,233 @@ +#!/bin/sh +# netatalk-config + +af_libs= +af_cflags= +prefix=@prefix@ +exec_prefix=@exec_prefix@ + + +## +## Define usage() +## +usage() +{ + cat <&2 +fi + +# at least one option should be selected +case "$1" in + --*) + ;; + *) + usage 1 1>&2 + ;; +esac + +# grab all -- arguments +while test $# -gt 0; do + case "$1" in + -*=*) af_optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) af_optarg= ;; + esac + + case $1 in + --help) + usage 0 0>&2 + ;; + --cflags) + af_echo_cflags=yes + ;; + --libs) + af_echo_libs_L=yes + af_echo_libs_l=yes + ;; + --libs-dirs) + af_echo_libs_L=yes + ;; + --libs-names) + af_echo_libs_l=yes + ;; + --macros*) + +echo -I @prefix@/include/netatalk/macros +exit + + ;; + --prefix=*) + prefix=$af_optarg + af_prefix_set=yes + ;; + --prefix) + af_echo_prefix=yes + ;; + --exec_prefix=*) + exec_prefix=$af_optarg + af_exec_prefix_set=yes + ;; + --exec_prefix) + af_echo_exec_prefix=yes + ;; + --version) + af_echo_version=yes + ;; + --*) + usage 1 1>&2 + ;; + *) + break + ;; + esac + shift +done + +# if we have a default library use it +if test $# -eq 0; then +if test "X$af_lib_default" != "X"; then + af_lib__AF_LIB_DEFAULT=yes + return +fi +fi + +while test $# -gt 0; do + case $1 in + netatalk) + af_lib_netatalk=yes + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done +} + +print_result() +{ +if test "X$af_echo_cflags" = "Xyes"; then + af_all_flags="$af_cflags" +fi + +if test "X$af_echo_libs_L" = "Xyes" || test "X$af_echo_libs_l" = "Xyes"; then + af_all_flags="$af_all_flags $af_libs" +fi + +if test -z "$af_all_flags" || test "X$af_all_flags" = "X "; then + exit 1 +fi + +# Straight out any possible duplicates, but be careful to +# get `-lfoo -lbar -lbaz' for `-lfoo -lbaz -lbar -lbaz' +af_other_flags= +af_lib_L_flags= +af_rev_libs= +for i in $af_all_flags; do + case "$i" in + # a library, save it for later, in reverse order + -l*) af_rev_libs="$i $af_rev_libs" ;; + -L*|-R*) + if test "X$af_echo_libs_L" = "Xyes"; then + case " $af_lib_L_flags " in + *\ $i\ *) ;; # already there + *) af_lib_L_flags="$af_lib_L_flags $i" ;; # add it to output + esac + fi;; + *) + case " $af_other_flags " in + *\ $i\ *) ;; # already there + *) af_other_flags="$af_other_flags $i" ;; # add it to output + esac ;; + esac +done + +af_ord_libs= +if test "X$af_echo_libs_l" = "Xyes"; then + for i in $af_rev_libs; do + case " $af_ord_libs " in + *\ $i\ *) ;; # already there + *) af_ord_libs="$i $af_ord_libs" ;; # add it to output in reverse order + esac + done +fi + +echo $af_other_flags $af_lib_L_flags $af_ord_libs +} + +## +## Main Body +## + +parse $* + + +## +## Initialize names +## + + + + + +if test "X$af_echo_prefix" = "Xyes"; then + echo $prefix +fi + +if test "X$af_echo_exec_prefix" = "Xyes"; then + echo $exec_prefix +fi + +if test "X$af_echo_version" = "Xyes"; then + echo @NETATALK_VERSION@ + exit 0 +fi + + +## +## Libraries +## + +#dummy because this should always be selected + + +if test "@includedir@" != /usr/include ; then + includes="-I@includedir@" +fi +if test "@libdir@" != /usr/lib ; then + libs="-L@libdir@" +fi +af_cflags="$af_cflags $includes" +af_libs="$libs -latalk" + + + + +print_result + +exit 0 + diff --git a/distrib/initscripts/Makefile.am b/distrib/initscripts/Makefile.am new file mode 100644 index 0000000..bcf1779 --- /dev/null +++ b/distrib/initscripts/Makefile.am @@ -0,0 +1,235 @@ +## Makefile for distrib/initscripts/ + +SUFFIXES = .tmpl . + +pkgconfdir = @PKGCONFDIR@ + +# +# Template Generation +# + +.tmpl: + sed -e s@:BINDIR:@${bindir}@ \ + -e s@:SBINDIR:@${sbindir}@ \ + -e s@:ETCDIR:@${pkgconfdir}@ \ + -e s@:NETATALK_VERSION:@${NETATALK_VERSION}@ \ + -e s@:PATH_NETATALK_LOCK:@${PATH_NETATALK_LOCK}@ \ + <$< >$@ + +GENERATED_FILES = \ + rc.bsd \ + rc.debian \ + rc.gentoo \ + rc.netbsd \ + rc.redhat \ + rc.solaris \ + rc.suse \ + service.systemd \ + netatalk.xml + +TEMPLATES = \ + rc.bsd.tmpl \ + rc.debian.tmpl \ + rc.gentoo.tmpl \ + rc.netbsd.tmpl \ + rc.redhat.tmpl \ + rc.solaris.tmpl \ + rc.suse.tmpl \ + service.systemd.tmpl \ + netatalk.xml.tmpl + +CLEANFILES = $(GENERATED_FILES) $(sysv_SCRIPTS) $(service_DATA) afpd cnid_metad +EXTRA_DIST = $(TEMPLATES) +noinst_DATA = $(GENERATED_FILES) + +# overwrite automake uninstall +# not beautiful, but this way we can call the OS specific init script +# tools, like chkconfig, insserv or rc-update + +uninstall: uninstall-startup + +# +# checking for "redhat" style sysv scripts: +# + +if USE_REDHAT_SYSV + +sysvdir = $(INIT_DIR) +sysv_SCRIPTS = netatalk + +$(sysv_SCRIPTS): rc.redhat + cp -f rc.redhat $(sysv_SCRIPTS) + chmod a+x $(sysv_SCRIPTS) + +install-data-hook: + -chkconfig --add $(sysv_SCRIPTS) + +uninstall-startup: + -chkconfig --del $(sysv_SCRIPTS) + rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) + +endif + +# +# checking for general systemd scripts: +# + +if USE_SYSTEMD + +servicedir = $(INIT_DIR) +service_DATA = netatalk.service + +netatalk.service: service.systemd + cp -f service.systemd netatalk.service + +install-data-hook: + -systemctl daemon-reload + +uninstall-startup: + -systemctl disable $(service_DATA) + rm -f $(DESTDIR)$(servicedir)/netatalk.service + -systemctl daemon-reload + +endif + +# +# checking for "Debian" style systemd scripts: +# + +if USE_DEBIAN_SYSTEMD + +servicedir = $(INIT_DIR) +service_DATA = netatalk.service + +netatalk.service: service.systemd + cp -f service.systemd netatalk.service + +install-data-hook: + -systemctl daemon-reload + +uninstall-startup: + -systemctl disable $(service_DATA) + rm -f $(DESTDIR)$(servicedir)/netatalk.service + -systemctl daemon-reload + +endif + +# +# checking for "SuSE" style sysv scripts: +# + +if USE_SUSE_SYSV + +sysvdir = $(INIT_DIR) +sysv_SCRIPTS = netatalk + +$(sysv_SCRIPTS): rc.suse + cp -f rc.suse $(sysv_SCRIPTS) + chmod a+x $(sysv_SCRIPTS) + +install-data-hook: + -insserv $(sysv_SCRIPTS) + +uninstall-startup: + -insserv -d $(sysv_SCRIPTS) + rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) + +endif + +# +# checking for NetBSD init scripts +# + +if USE_NETBSD + +sysvdir = $(INIT_DIR) +sysv_SCRIPTS = netatalk + +netatalk: rc.netbsd + cp -f $< $@ + chmod a+x $@ + +install-data-hook: + +uninstall-hook: + +uninstall-startup: uninstall-am + +endif + +# +# checking for Solaris init scripts +# + +if USE_SOLARIS + +servicedir = $(INIT_DIR) +service_DATA = netatalk.xml + +install-data-hook: + svccfg import netatalk.xml + +uninstall-startup: + svccfg delete network/netatalk + +endif + +# +# checking for "Gentoo" style sysv scripts: +# + +if USE_GENTOO + +sysvdir = $(INIT_DIR) +sysv_SCRIPTS = netatalk + +$(sysv_SCRIPTS): rc.gentoo + cp -f rc.gentoo $(sysv_SCRIPTS) + chmod a+x $(sysv_SCRIPTS) + +install-data-hook: +# -rc-update add $(sysv_SCRIPTS) default + +uninstall-startup: +# -rc-update del $(sysv_SCRIPTS) default +# rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) + +endif + +# +# checking for "Debian" style sysv scripts: +# + +if USE_DEBIAN_SYSV + +sysvdir = $(INIT_DIR) +sysv_SCRIPTS = netatalk + +$(sysv_SCRIPTS): rc.debian + cp -f rc.debian $(sysv_SCRIPTS) + chmod a+x $(sysv_SCRIPTS) + +install-data-hook: +# update-rc.d $(sysv_SCRIPTS) defaults 90 10 + +uninstall-startup: +# rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) +# update-rc.d netatalk remove + +endif + + +# +# defaults, no init scripts installed +# + +if USE_UNDEF + +install-data-hook: + +uninstall-hook: + +uninstall-startup: uninstall-am + +endif + diff --git a/distrib/initscripts/Makefile.in b/distrib/initscripts/Makefile.in new file mode 100644 index 0000000..53566dd --- /dev/null +++ b/distrib/initscripts/Makefile.in @@ -0,0 +1,797 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = distrib/initscripts +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(sysvdir)" "$(DESTDIR)$(servicedir)" +SCRIPTS = $(sysv_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(noinst_DATA) $(service_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUFFIXES = .tmpl . +pkgconfdir = @PKGCONFDIR@ +GENERATED_FILES = \ + rc.bsd \ + rc.debian \ + rc.gentoo \ + rc.netbsd \ + rc.redhat \ + rc.solaris \ + rc.suse \ + service.systemd \ + netatalk.xml + +TEMPLATES = \ + rc.bsd.tmpl \ + rc.debian.tmpl \ + rc.gentoo.tmpl \ + rc.netbsd.tmpl \ + rc.redhat.tmpl \ + rc.solaris.tmpl \ + rc.suse.tmpl \ + service.systemd.tmpl \ + netatalk.xml.tmpl + +CLEANFILES = $(GENERATED_FILES) $(sysv_SCRIPTS) $(service_DATA) afpd cnid_metad +EXTRA_DIST = $(TEMPLATES) +noinst_DATA = $(GENERATED_FILES) +# -rc-update del $(sysv_SCRIPTS) default +# rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) + +# +# checking for "Debian" style sysv scripts: +# +@USE_DEBIAN_SYSV_TRUE@sysvdir = $(INIT_DIR) + +# +# checking for "Gentoo" style sysv scripts: +# +@USE_GENTOO_TRUE@sysvdir = $(INIT_DIR) + +# +# checking for NetBSD init scripts +# +@USE_NETBSD_TRUE@sysvdir = $(INIT_DIR) + +# +# checking for "redhat" style sysv scripts: +# +@USE_REDHAT_SYSV_TRUE@sysvdir = $(INIT_DIR) + +# +# checking for "SuSE" style sysv scripts: +# +@USE_SUSE_SYSV_TRUE@sysvdir = $(INIT_DIR) +@USE_DEBIAN_SYSV_TRUE@sysv_SCRIPTS = netatalk +@USE_GENTOO_TRUE@sysv_SCRIPTS = netatalk +@USE_NETBSD_TRUE@sysv_SCRIPTS = netatalk +@USE_REDHAT_SYSV_TRUE@sysv_SCRIPTS = netatalk +@USE_SUSE_SYSV_TRUE@sysv_SCRIPTS = netatalk + +# +# checking for "Debian" style systemd scripts: +# +@USE_DEBIAN_SYSTEMD_TRUE@servicedir = $(INIT_DIR) + +# +# checking for Solaris init scripts +# +@USE_SOLARIS_TRUE@servicedir = $(INIT_DIR) + +# +# checking for general systemd scripts: +# +@USE_SYSTEMD_TRUE@servicedir = $(INIT_DIR) +@USE_DEBIAN_SYSTEMD_TRUE@service_DATA = netatalk.service +@USE_SOLARIS_TRUE@service_DATA = netatalk.xml +@USE_SYSTEMD_TRUE@service_DATA = netatalk.service +all: all-am + +.SUFFIXES: +.SUFFIXES: .tmpl . +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign distrib/initscripts/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign distrib/initscripts/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sysvSCRIPTS: $(sysv_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(sysv_SCRIPTS)'; test -n "$(sysvdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sysvdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sysvdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(sysvdir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(sysvdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sysvSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(sysv_SCRIPTS)'; test -n "$(sysvdir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(sysvdir)'; $(am__uninstall_files_from_dir) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-serviceDATA: $(service_DATA) + @$(NORMAL_INSTALL) + @list='$(service_DATA)'; test -n "$(servicedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(servicedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(servicedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(servicedir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(servicedir)" || exit $$?; \ + done + +uninstall-serviceDATA: + @$(NORMAL_UNINSTALL) + @list='$(service_DATA)'; test -n "$(servicedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(servicedir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(sysvdir)" "$(DESTDIR)$(servicedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@USE_DEBIAN_SYSTEMD_FALSE@@USE_DEBIAN_SYSV_FALSE@@USE_GENTOO_FALSE@@USE_NETBSD_FALSE@@USE_REDHAT_SYSV_FALSE@@USE_SOLARIS_FALSE@@USE_SUSE_SYSV_FALSE@@USE_SYSTEMD_FALSE@@USE_UNDEF_FALSE@install-data-hook: +@USE_NETBSD_FALSE@@USE_UNDEF_FALSE@uninstall-hook: +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-serviceDATA install-sysvSCRIPTS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-serviceDATA uninstall-sysvSCRIPTS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: install-am install-data-am install-strip uninstall-am + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-data-hook install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-serviceDATA install-strip install-sysvSCRIPTS \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ + uninstall-hook uninstall-serviceDATA uninstall-sysvSCRIPTS + + +# +# Template Generation +# + +.tmpl: + sed -e s@:BINDIR:@${bindir}@ \ + -e s@:SBINDIR:@${sbindir}@ \ + -e s@:ETCDIR:@${pkgconfdir}@ \ + -e s@:NETATALK_VERSION:@${NETATALK_VERSION}@ \ + -e s@:PATH_NETATALK_LOCK:@${PATH_NETATALK_LOCK}@ \ + <$< >$@ + +# overwrite automake uninstall +# not beautiful, but this way we can call the OS specific init script +# tools, like chkconfig, insserv or rc-update + +uninstall: uninstall-startup + +@USE_REDHAT_SYSV_TRUE@$(sysv_SCRIPTS): rc.redhat +@USE_REDHAT_SYSV_TRUE@ cp -f rc.redhat $(sysv_SCRIPTS) +@USE_REDHAT_SYSV_TRUE@ chmod a+x $(sysv_SCRIPTS) + +@USE_REDHAT_SYSV_TRUE@install-data-hook: +@USE_REDHAT_SYSV_TRUE@ -chkconfig --add $(sysv_SCRIPTS) + +@USE_REDHAT_SYSV_TRUE@uninstall-startup: +@USE_REDHAT_SYSV_TRUE@ -chkconfig --del $(sysv_SCRIPTS) +@USE_REDHAT_SYSV_TRUE@ rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) + +@USE_SYSTEMD_TRUE@netatalk.service: service.systemd +@USE_SYSTEMD_TRUE@ cp -f service.systemd netatalk.service + +@USE_SYSTEMD_TRUE@install-data-hook: +@USE_SYSTEMD_TRUE@ -systemctl daemon-reload + +@USE_SYSTEMD_TRUE@uninstall-startup: +@USE_SYSTEMD_TRUE@ -systemctl disable $(service_DATA) +@USE_SYSTEMD_TRUE@ rm -f $(DESTDIR)$(servicedir)/netatalk.service +@USE_SYSTEMD_TRUE@ -systemctl daemon-reload + +@USE_DEBIAN_SYSTEMD_TRUE@netatalk.service: service.systemd +@USE_DEBIAN_SYSTEMD_TRUE@ cp -f service.systemd netatalk.service + +@USE_DEBIAN_SYSTEMD_TRUE@install-data-hook: +@USE_DEBIAN_SYSTEMD_TRUE@ -systemctl daemon-reload + +@USE_DEBIAN_SYSTEMD_TRUE@uninstall-startup: +@USE_DEBIAN_SYSTEMD_TRUE@ -systemctl disable $(service_DATA) +@USE_DEBIAN_SYSTEMD_TRUE@ rm -f $(DESTDIR)$(servicedir)/netatalk.service +@USE_DEBIAN_SYSTEMD_TRUE@ -systemctl daemon-reload + +@USE_SUSE_SYSV_TRUE@$(sysv_SCRIPTS): rc.suse +@USE_SUSE_SYSV_TRUE@ cp -f rc.suse $(sysv_SCRIPTS) +@USE_SUSE_SYSV_TRUE@ chmod a+x $(sysv_SCRIPTS) + +@USE_SUSE_SYSV_TRUE@install-data-hook: +@USE_SUSE_SYSV_TRUE@ -insserv $(sysv_SCRIPTS) + +@USE_SUSE_SYSV_TRUE@uninstall-startup: +@USE_SUSE_SYSV_TRUE@ -insserv -d $(sysv_SCRIPTS) +@USE_SUSE_SYSV_TRUE@ rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) + +@USE_NETBSD_TRUE@netatalk: rc.netbsd +@USE_NETBSD_TRUE@ cp -f $< $@ +@USE_NETBSD_TRUE@ chmod a+x $@ + +@USE_NETBSD_TRUE@install-data-hook: + +@USE_NETBSD_TRUE@uninstall-hook: + +@USE_NETBSD_TRUE@uninstall-startup: uninstall-am + +@USE_SOLARIS_TRUE@install-data-hook: +@USE_SOLARIS_TRUE@ svccfg import netatalk.xml + +@USE_SOLARIS_TRUE@uninstall-startup: +@USE_SOLARIS_TRUE@ svccfg delete network/netatalk + +@USE_GENTOO_TRUE@$(sysv_SCRIPTS): rc.gentoo +@USE_GENTOO_TRUE@ cp -f rc.gentoo $(sysv_SCRIPTS) +@USE_GENTOO_TRUE@ chmod a+x $(sysv_SCRIPTS) + +@USE_GENTOO_TRUE@install-data-hook: +# -rc-update add $(sysv_SCRIPTS) default + +@USE_GENTOO_TRUE@uninstall-startup: + +@USE_DEBIAN_SYSV_TRUE@$(sysv_SCRIPTS): rc.debian +@USE_DEBIAN_SYSV_TRUE@ cp -f rc.debian $(sysv_SCRIPTS) +@USE_DEBIAN_SYSV_TRUE@ chmod a+x $(sysv_SCRIPTS) + +@USE_DEBIAN_SYSV_TRUE@install-data-hook: +# update-rc.d $(sysv_SCRIPTS) defaults 90 10 + +@USE_DEBIAN_SYSV_TRUE@uninstall-startup: +# rm -f $(DESTDIR)$(sysvdir)/$(sysv_SCRIPTS) +# update-rc.d netatalk remove + +# +# defaults, no init scripts installed +# + +@USE_UNDEF_TRUE@install-data-hook: + +@USE_UNDEF_TRUE@uninstall-hook: + +@USE_UNDEF_TRUE@uninstall-startup: uninstall-am + +# 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/distrib/initscripts/netatalk.xml.tmpl b/distrib/initscripts/netatalk.xml.tmpl new file mode 100644 index 0000000..6349e0c --- /dev/null +++ b/distrib/initscripts/netatalk.xml.tmpl @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/distrib/initscripts/rc.bsd.tmpl b/distrib/initscripts/rc.bsd.tmpl new file mode 100644 index 0000000..fd00a7b --- /dev/null +++ b/distrib/initscripts/rc.bsd.tmpl @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Netatalk :NETATALK_VERSION: daemons. +# + +echo -n 'starting netatalk daemons:' + +if [ -x :SBINDIR:/netatalk ]; then + :SBINDIR:/netatalk + echo -n ' netatalk' +fi + +echo '.' diff --git a/distrib/initscripts/rc.debian.tmpl b/distrib/initscripts/rc.debian.tmpl new file mode 100644 index 0000000..9b26b61 --- /dev/null +++ b/distrib/initscripts/rc.debian.tmpl @@ -0,0 +1,67 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: netatalk +# Required-Start: $remote_fs $syslog +# Should-Start: avahi-daemon +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +### END INIT INFO +# +# netatalk Netatalk :NETATALK_VERSION: initscript +# + +set -e + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DESC="Netatalk" +NAME=netatalk +SCRIPTNAME=/etc/init.d/$NAME + +# Guard to prevent execution if netatalk was removed. +test -x :SBINDIR:/netatalk || exit 0 + +# Start Netatalk servers. +netatalk_startup() { + if [ -x :SBINDIR:/netatalk ] ; then + :SBINDIR:/netatalk + echo -n " netatalk" + fi + +} + +case "$1" in + start) + echo -n "Starting Netatalk services: " + netatalk_startup + echo "." + ;; + + stop) + echo -n "Stopping Netatalk Daemons:" + echo -n " netatalk" + start-stop-daemon --stop --quiet --oknodo --exec :SBINDIR:/netatalk + + echo "." + ;; + + restart) + $0 force-reload + ;; + + force-reload) + echo -n "Restarting Netatalk Daemons" + $0 stop + echo -n "." + sleep 2 + echo -n "." + if $0 start; then + echo "done." + fi + ;; + + *) + echo "Usage: $0 {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac diff --git a/distrib/initscripts/rc.gentoo.tmpl b/distrib/initscripts/rc.gentoo.tmpl new file mode 100644 index 0000000..b8f6460 --- /dev/null +++ b/distrib/initscripts/rc.gentoo.tmpl @@ -0,0 +1,14 @@ +#!/sbin/runscript +# Copyright 1999-2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# +# Netatalk :NETATALK_VERSION: daemons. + +command=":SBINDIR:/${SVCNAME}" + +depend() { + need net + use avahi-daemon + use logger dns + after entropy +} diff --git a/distrib/initscripts/rc.netbsd.tmpl b/distrib/initscripts/rc.netbsd.tmpl new file mode 100644 index 0000000..af5602a --- /dev/null +++ b/distrib/initscripts/rc.netbsd.tmpl @@ -0,0 +1,19 @@ +#!/bin/sh +# +# PROVIDE: netatalk +# KEYWORD: shutdown +# +# AFP fileserver for Macintosh clients (netatalk :NETATALK_VERSION:) +# + +. /etc/rc.subr + +name="netatalk" +rcvar=$name +command=":SBINDIR:/netatalk" +etcdir=":ETCDIR:" +pidfile="/var/run/${name}.pid" +required_files="$etcdir/afp.conf" + +load_rc_config $name +run_rc_command "$1" diff --git a/distrib/initscripts/rc.redhat.tmpl b/distrib/initscripts/rc.redhat.tmpl new file mode 100644 index 0000000..0721d9f --- /dev/null +++ b/distrib/initscripts/rc.redhat.tmpl @@ -0,0 +1,95 @@ +#! /bin/sh +# chkconfig: - 91 35 +# description: Netatalk AFP fileserver for Macintosh clients +# +# Netatalk :NETATALK_VERSION: + +NETATALK_CONF_DIR=:ETCDIR: +NETATALK_SBIN=:SBINDIR: +prog=netatalk + +# Source function library. +. /etc/rc.d/init.d/functions + +# Source networking configuration. +. /etc/sysconfig/network + +# initialize return values +RETVAL=1 + +# startup code for everything +netatalk_startup() { + # Check that networking is up. + if [ ${NETWORKING} = "no" ]; then + echo "[Network isn't started]"; + exit 1; + fi + + if [ -x ${NETATALK_SBIN}/netatalk ] ; then + echo -n $"Starting $prog: " + daemon ${NETATALK_SBIN}/netatalk + RETVAL=$? + echo + fi + + if [ $RETVAL -eq 0 ]; then + touch /var/lock/subsys/netatalk || RETVAL=1 + fi +} + +# stop code for everything +netatalk_stop() { + if [ -x ${NETATALK_SBIN}/netatalk ]; then + echo -n $"Stopping $prog: " + killproc netatalk + RETVAL=$? + echo + fi + + if [ $RETVAL -eq 0 ] ; then + rm -f /var/lock/subsys/netatalk || RETVAL=1 + fi +} + +# restart code +netatalk_restart() { + netatalk_stop + netatalk_startup +} + +# reload config files +netatalk_reload() { + if [ -x ${NETATALK_SBIN}/netatalk ]; then + echo -n $"Reloading $prog: " + killproc netatalk -HUP + RETVAL=$? + echo + fi +} + +case "$1" in + 'start') + netatalk_startup + ;; + 'stop') + netatalk_stop + ;; + 'restart') + netatalk_restart + ;; + 'reload'|'graceful') + netatalk_reload + ;; + 'status') + status netatalk + RETVAL=$? + ;; + 'condrestart') + [ -f /var/lock/subsys/netatalk ] && netatalk_restart || : + ;; + *) + echo "Usage: $0 {start|stop|restart|reload|status|condrestart}" + exit 2 +esac + +exit $RETVAL diff --git a/distrib/initscripts/rc.solaris.tmpl b/distrib/initscripts/rc.solaris.tmpl new file mode 100644 index 0000000..5b244da --- /dev/null +++ b/distrib/initscripts/rc.solaris.tmpl @@ -0,0 +1,60 @@ +#! /bin/sh +# +# Start/stop the Netatalk :NETATALK_VERSION: daemons. +# + +# +# kill the named process(es) +# +killproc() { + pid=`/usr/bin/ps -e | + /usr/bin/grep $1 | + /usr/bin/sed -e 's/^ *//' -e 's/ .*//'` + [ "$pid" != "" ] && kill $pid +} + +# +# Start the netatalk server processes. +# + +netatalk_startup() { + echo 'starting netatalk daemons: \c' + + if [ -x :SBINDIR:/netatalk ]; then + :SBINDIR:/netatalk + echo ' netatalk\c' + fi + + echo '.' +} + + +case "$1" in + + 'start') + netatalk_startup + ;; + +# +# Stop the netatalk server processes. +# + 'stop') + + echo 'stopping netatalk daemons:\c' + + if [ -x :SBINDIR:/netatalk ]; then + killproc netatalk; echo ' netatalk\c' + fi + + echo '.' + ;; + +# +# Usage statement. +# + + *) + echo "usage: $0 {start|stop}" + exit 1 + ;; +esac diff --git a/distrib/initscripts/rc.suse.tmpl b/distrib/initscripts/rc.suse.tmpl new file mode 100644 index 0000000..26e019e --- /dev/null +++ b/distrib/initscripts/rc.suse.tmpl @@ -0,0 +1,60 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: netatalk +# Required-Start: $local_fs +# Required-Stop: $local_fs +# Should-Start: $network $named $remote_fs $syslog avahi-daemon +# Should-Stop: $remote_fs $network $syslog +# Default-Start: 3 5 +# Default-Stop: +# Description: Netatalk AFP fileserver for Macintosh clients +### END INIT INFO + +# Netatalk :NETATALK_VERSION: + +. /etc/rc.status + +# startup code for everything +netatalk_startup() { + if [ -x :SBINDIR:/netatalk ] ; then + echo -n " Starting netatalk " + startproc :SBINDIR:/netatalk + rc_status -v + fi + + touch /var/lock/subsys/netatalk +} + +case "$1" in + start) + if test ! -z "$UID" -a "$UID" != 0 ; then + echo "you have to be root to start netatalk daemons" + rc_failed + else + echo "Starting netatalk..." + netatalk_startup + fi + ;; + stop) + echo -n "Shutting down netatalk" + killproc -TERM :SBINDIR:/netatalk + rc_status -v + ;; + restart|reload|force-reload) + $0 stop + $0 start + rc_status + ;; + status) + echo "Checking for netatalk services" + checkproc :SBINDIR:/netatalk && echo "netatalk: OK" || echo "netatalk: No process" + checkproc :SBINDIR:/netatalk + rc_status -v + ;; + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 + ;; +esac + +rc_exit diff --git a/distrib/initscripts/service.systemd.tmpl b/distrib/initscripts/service.systemd.tmpl new file mode 100644 index 0000000..cd17076 --- /dev/null +++ b/distrib/initscripts/service.systemd.tmpl @@ -0,0 +1,19 @@ +# This file is part of netatalk :NETATALK_VERSION:. + +[Unit] +Description=Netatalk AFP fileserver for Macintosh clients +Documentation=man:afp.conf(5) man:netatalk(8) man:afpd(8) man:cnid_metad(8) man:cnid_dbd(8) +Documentation=http://netatalk.sourceforge.net/ +After=syslog.target network.target avahi-daemon.service + +[Service] +Type=forking +GuessMainPID=no +ExecStart=/bin/sh -c :SBINDIR:/netatalk +PIDFile=:PATH_NETATALK_LOCK: +ExecReload=/bin/kill -HUP $MAINPID +Restart=always +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/distrib/m4/Makefile.am b/distrib/m4/Makefile.am new file mode 100644 index 0000000..5205bab --- /dev/null +++ b/distrib/m4/Makefile.am @@ -0,0 +1,6 @@ +# Makefile for distrib/m4/ + +m4datadir = $(datadir)/aclocal +m4data_DATA = netatalk.m4 + +EXTRA_DIST = $(m4data_DATA) diff --git a/distrib/m4/Makefile.in b/distrib/m4/Makefile.in new file mode 100644 index 0000000..3f83f82 --- /dev/null +++ b/distrib/m4/Makefile.in @@ -0,0 +1,574 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for distrib/m4/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = distrib/m4 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(m4datadir)" +DATA = $(m4data_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +m4datadir = $(datadir)/aclocal +m4data_DATA = netatalk.m4 +EXTRA_DIST = $(m4data_DATA) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign distrib/m4/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign distrib/m4/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-m4dataDATA: $(m4data_DATA) + @$(NORMAL_INSTALL) + @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(m4datadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(m4datadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(m4datadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(m4datadir)" || exit $$?; \ + done + +uninstall-m4dataDATA: + @$(NORMAL_UNINSTALL) + @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(m4datadir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(m4datadir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-m4dataDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-m4dataDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-m4dataDATA install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + uninstall uninstall-am uninstall-m4dataDATA + + +# 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/distrib/m4/netatalk.m4 b/distrib/m4/netatalk.m4 new file mode 100644 index 0000000..dc759a2 --- /dev/null +++ b/distrib/m4/netatalk.m4 @@ -0,0 +1,158 @@ +# Configure paths for netatalk +# Based on libsigc++ script by Karl Nelson +# Modified by jeff b (jeff@univrel.pr.uconn.edu) + +dnl Test for netatalk, and define NETATALK_CFLAGS and NETATALK_LIBS +dnl to be used as follows: +dnl AM_PATH_NETATALK(MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([AM_PATH_NETATALK], +[dnl +dnl Get the cflags and libraries from the netatalk-config script +dnl + +dnl +dnl Prefix options +dnl +AC_ARG_WITH(netatalk-prefix, +[ --with-netatalk-prefix=PREFIX + Prefix where netatalk is installed (optional)] +, netatalk_config_prefix="$withval", netatalk_config_prefix="") + +AC_ARG_WITH(netatalk-exec-prefix, +[ --with-netatalk-exec-prefix=PREFIX + Exec prefix where netatalk is installed (optional)] +, netatalk_config_exec_prefix="$withval", netatalk_config_exec_prefix="") + +AC_ARG_ENABLE(netatalktest, +[ --disable-netatalktest Do not try to compile and run a test netatalk + program], +, enable_netatalktest=yes) + +dnl +dnl Prefix handling +dnl + if test x$netatalk_config_exec_prefix != x ; then + netatalk_config_args="$netatalk_config_args --exec-prefix=$netatalk_config_exec_prefix" + if test x${NETATALK_CONFIG+set} != xset ; then + NETATALK_CONFIG=$netatalk_config_exec_prefix/bin/netatalk-config + fi + fi + if test x$netatalk_config_prefix != x ; then + netatalk_config_args="$netatalk_config_args --prefix=$netatalk_config_prefix" + if test x${NETATALK_CONFIG+set} != xset ; then + NETATALK_CONFIG=$netatalk_config_prefix/bin/netatalk-config + fi + fi + +dnl +dnl See if netatalk-config is alive +dnl + AC_PATH_PROG(NETATALK_CONFIG, netatalk-config, no) + netatalk_version_min=$1 + +dnl +dnl Version check +dnl + AC_MSG_CHECKING(for netatalk - version >= $netatalk_version_min) + no_netatalk="" + if test "$NETATALK_CONFIG" = "no" ; then + no_netatalk=yes + else + netatalk_version=`$NETATALK_CONFIG --version` + + NETATALK_CFLAGS=`$NETATALK_CONFIG $netatalk_config_args --cflags` + NETATALK_LIBS=`$NETATALK_CONFIG $netatalk_config_args --libs` + + netatalk_major_version=`echo $netatalk_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + netatalk_minor_version=`echo $netatalk_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + netatalk_micro_version=`echo $netatalk_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + netatalk_major_min=`echo $netatalk_major_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + netatalk_minor_min=`echo $netatalk_minor_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + netatalk_micro_min=`echo $netatalk_micro_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + netatalk_version_proper=`expr \ + $netatalk_major_version \> $netatalk_major_min \| \ + $netatalk_major_version \= $netatalk_major_min \& \ + $netatalk_minor_version \> $netatalk_minor_min \| \ + $netatalk_major_version \= $netatalk_major_min \& \ + $netatalk_minor_version \= $netatalk_minor_min \& \ + $netatalk_micro_version \>= $netatalk_micro_min ` + + if test "$netatalk_version_proper" = "1" ; then + AC_MSG_RESULT([$netatalk_major_version.$netatalk_minor_version.$netatalk_micro_version]) + else + AC_MSG_RESULT(no) + no_netatalk=yes + fi + + if test "X$no_netatalk" = "Xyes" ; then + enable_netatalktest=no + fi + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + +dnl +dnl +dnl + if test "x$enable_netatalktest" = "xyes" ; then + AC_MSG_CHECKING(if netatalk sane) + ac_save_CXXFLAGS="$CXXFLAGS" + ac_save_LIBS="$LIBS" + CXXFLAGS="$CXXFLAGS $NETATALK_CFLAGS" + LIBS="$LIBS $NETATALK_LIBS" + + rm -f conf.netatalktest + + AC_TRY_RUN([ +#include +#include + +int main(int argc,char **argv) + { + if (netatalk_major_version!=$netatalk_major_version || + netatalk_minor_version!=$netatalk_minor_version || + netatalk_micro_version!=$netatalk_micro_version) + { printf("(%d.%d.%d) ", + netatalk_major_version,netatalk_minor_version,netatalk_micro_version); + return 1; + } + } + +],[ + AC_MSG_RESULT(yes) +],[ + AC_MSG_RESULT(no) + no_netatalk=yes +] +,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + + CXXFLAGS="$ac_save_CXXFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + dnl + dnl + if test "x$no_netatalk" = x ; then + ifelse([$2], , :, [$2]) + else + NETATALK_CFLAGS="" + NETATALK_LIBS="" + ifelse([$3], , :, [$3]) + fi + + AC_LANG_RESTORE + + AC_SUBST(NETATALK_CFLAGS) + AC_SUBST(NETATALK_LIBS) +]) + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..f8ccbb7 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,9 @@ +SUBDIRS = manpages manual + +DISTCLEANFILES = html.xsl man.xsl + +release-notes: www/ReleaseNotes + cd www && ./create-relnotes.sh + +upload-release-notes: release-notes + scp www/ReleaseNotes.html $$USER,netatalk@web.sourceforge.net:/home/project-web/netatalk/htdocs/3.1/ReleaseNotes$(VERSION).html diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..614e5b0 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,717 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = doc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/html.xsl.in $(srcdir)/man.xsl.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = html.xsl man.xsl +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = manpages manual +DISTCLEANFILES = html.xsl man.xsl +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +html.xsl: $(top_builddir)/config.status $(srcdir)/html.xsl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +man.xsl: $(top_builddir)/config.status $(srcdir)/man.xsl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +release-notes: www/ReleaseNotes + cd www && ./create-relnotes.sh + +upload-release-notes: release-notes + scp www/ReleaseNotes.html $$USER,netatalk@web.sourceforge.net:/home/project-web/netatalk/htdocs/3.1/ReleaseNotes$(VERSION).html + +# 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/doc/html.xsl.in b/doc/html.xsl.in new file mode 100644 index 0000000..b2fbfd3 --- /dev/null +++ b/doc/html.xsl.in @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/doc/man.xsl.in b/doc/man.xsl.in new file mode 100644 index 0000000..fca9fec --- /dev/null +++ b/doc/man.xsl.in @@ -0,0 +1,26 @@ + + + + + +1 + + (//refmiscinfo[@class='date'])[last()] + + + +1 + + + + + + + + + + + + + + diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am new file mode 100644 index 0000000..4bc3be5 --- /dev/null +++ b/doc/manpages/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = man1 man5 man8 \ No newline at end of file diff --git a/doc/manpages/Makefile.in b/doc/manpages/Makefile.in new file mode 100644 index 0000000..d596308 --- /dev/null +++ b/doc/manpages/Makefile.in @@ -0,0 +1,704 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = doc/manpages +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = man1 man5 man8 +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/manpages/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/manpages/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# 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/doc/manpages/man1/Makefile.am b/doc/manpages/man1/Makefile.am new file mode 100644 index 0000000..fbb1848 --- /dev/null +++ b/doc/manpages/man1/Makefile.am @@ -0,0 +1,40 @@ +XSLTPROC=@XSLTPROC@ +XSLTPROC_FLAGS=@XSLTPROC_FLAGS@ +MAN_STYLESHEET=$(top_srcdir)/doc/man.xsl +CLEANFILES = + +MAN_MANPAGES = \ + ad.1 \ + afpldaptest.1 \ + afppasswd.1 \ + afpstats.1 \ + apple_dump.1 \ + asip-status.pl.1 \ + dbd.1 \ + macusers.1 \ + megatron.1 \ + netatalk-config.1 \ + uniconv.1 + +EXTRA_DIST = \ + ad.1.xml \ + afpldaptest.1.xml \ + afppasswd.1.xml \ + afpstats.1.xml \ + apple_dump.1.xml \ + asip-status.pl.1.xml \ + dbd.1.xml \ + macusers.1.xml \ + megatron.1.xml \ + netatalk-config.1.xml \ + uniconv.1.xml + +if HAVE_XSLTPROC +CLEANFILES += $(MAN_MANPAGES) + +%.1 : %.1.xml + @xsltproc $(MAN_STYLESHEET) $< + @cp $@ $(top_builddir)/man/man1/$@.in + +html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET) +endif diff --git a/doc/manpages/man1/Makefile.in b/doc/manpages/man1/Makefile.in new file mode 100644 index 0000000..4ef8573 --- /dev/null +++ b/doc/manpages/man1/Makefile.in @@ -0,0 +1,551 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_XSLTPROC_TRUE@am__append_1 = $(MAN_MANPAGES) +subdir = doc/manpages/man1 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAN_STYLESHEET = $(top_srcdir)/doc/man.xsl +CLEANFILES = $(am__append_1) +MAN_MANPAGES = \ + ad.1 \ + afpldaptest.1 \ + afppasswd.1 \ + afpstats.1 \ + apple_dump.1 \ + asip-status.pl.1 \ + dbd.1 \ + macusers.1 \ + megatron.1 \ + netatalk-config.1 \ + uniconv.1 + +EXTRA_DIST = \ + ad.1.xml \ + afpldaptest.1.xml \ + afppasswd.1.xml \ + afpstats.1.xml \ + apple_dump.1.xml \ + asip-status.pl.1.xml \ + dbd.1.xml \ + macusers.1.xml \ + megatron.1.xml \ + netatalk-config.1.xml \ + uniconv.1.xml + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/manpages/man1/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/manpages/man1/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@HAVE_XSLTPROC_FALSE@html-local: +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: html-local + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am html-local info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +@HAVE_XSLTPROC_TRUE@%.1 : %.1.xml +@HAVE_XSLTPROC_TRUE@ @xsltproc $(MAN_STYLESHEET) $< +@HAVE_XSLTPROC_TRUE@ @cp $@ $(top_builddir)/man/man1/$@.in + +@HAVE_XSLTPROC_TRUE@html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET) + +# 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/doc/manpages/man1/ad.1.xml b/doc/manpages/man1/ad.1.xml new file mode 100644 index 0000000..b6a9f55 --- /dev/null +++ b/doc/manpages/man1/ad.1.xml @@ -0,0 +1,402 @@ + + + + ad + + 1 + + 02 Sep 2011 + + @NETATALK_VERSION@ + + + + ad + + Netatalk compatible UNIX file utility suite. + + + + + ad + + ls | cp | mv | rm + + ... + + + + ad + + -v | --version + + + + + Description + + ad is a UNIX file utility suite with Netatalk + compatibility. AppleDouble + AppleDouble + files in .AppleDouble directories and + the CNID databases are updated as appropriate. + + + + Available Commands + + + ad ls + + -dRlu + + file|dir ... + + + List files and directories. + + + ad cp + + -aipvf + + src_file + + dst_file + + + + ad cp -R + + -aipvf + + src_file|src_directory ... + + dst_directory + + + Copy files and directories. + + + ad mv + + -finv + + src_file + + dst_file + + + + ad mv + + -finv + + src_file|src_directory ... + + dst_directory + + + Move files and directories. + + + ad rm + + -Rv + + file|directory + + + + ad -v|--version + + + Show version. + + + + ad ls + + List files and directories. Options: + + + + -d + + + Directories are listed as plain files + + + + + -R + + + list subdirectories recursively + + + + + -l + + + Long output, list AFP info + + + + + -u + + + List UNIX info + + + + + Long output description + + <unixinfo> <FinderFlags> <AFP Attributes> <Color> <Type> <Creator> <CNID from AppleDouble> <name> + +FinderFlags (valid for (f)iles and/or (d)irectories): + + d = On Desktop (f/d) + e = Hidden extension (f/d) + m = Shared (can run multiple times) (f) + n = No INIT resources (f) + i = Inited (f/d) + c = Custom icon (f/d) + t = Stationery (f) + s = Name locked (f/d) + b = Bundle (f/d) + v = Invisible (f/d) + a = Alias file (f/d) + +AFP Attributes: + + y = System (f/d) + w = No write (f) + p = Needs backup (f/d) + r = No rename (f/d) + l = No delete (f/d) + o = No copy (f) + +Note: any letter appearing in uppercase means the flag is set but it's a directory for which the flag is not allowed. + + + + ad cp + + Copy files and directories. + + In the first synopsis form, the cp utility copies the contents of + the source_file to the target_file. In the second synopsis form, the + contents of each named source_file is copied to the destination + target_directory. The names of the files themselves are not changed. If cp + detects an attempt to copy a file to itself, the copy will fail. + + Netatalk AFP volumes are detected by means of their ".AppleDesktop" + directory which is located in their volume root. When a copy targeting an + AFP volume is detected, its CNID database daemon is connected and all + copies will also go through the CNID database. AppleDouble files are also + copied and created as needed when the target is an AFP volume. + + Options: + + + + -a + + + Archive mode. Same as -Rp. + + + + + -f + + + For each existing destination pathname, remove it and create a + new file, without prompting for confirmation regardless of its + permis- sions. (The -f option overrides any previous -i or -n + options.) + + + + + -i + + + Cause cp to write a prompt to the standard error output before + copying a file that would overwrite an existing file. If the + response from the standard input begins with the character 'y' or + 'Y', the file copy is attempted. (The -i option overrides any pre- + vious -f or -n options.) + + + + + -n + + + Do not overwrite an existing file. (The -n option overrides + any previous -f or -i options.) + + + + + -p + + + Cause cp to preserve the following attributes of each source + file in the copy: modification time, access time, file flags, file + mode, user ID, and group ID, as allowed by permissions. If the user + ID and group ID cannot be preserved, no error message is displayed + and the exit value is not altered. + + + + + -R + + + If source_file designates a directory, cp copies the directory + and the entire subtree connected at that point.If the source_file + ends in a /, the contents of the directory are copied rather than + the directory itself. + + + + + -v + + + Cause cp to be verbose, showing files as they are + copied. + + + + + -x + + + File system mount points are not traversed. + + + + + + + ad mv + + Move files and directories. + + Move files around within an AFP volume, updating the CNID database + as needed. If either: + + source or destination is not an AFP volume + + + + source AFP volume != destination AFP volume + + the files are copied and removed from the source. + + Options: + + + + -f + + + Do not prompt for confirmation before overwriting the + destination path. (The -f option overrides any previous -i or -n + options.) + + + + + -i + + + Cause mv to write a prompt to standard error before moving a + file that would overwrite an existing file. If the response from the + standard input begins with the character `y' or `Y', the move is + attempted. (The -i option overrides any previous -f or -n + options.) + + + + + -n + + + Do not overwrite an existing file. (The -n option overrides + any previous -f or -i options.) + + + + + -v + + + Cause mv to be verbose, showing files after they are + moved. + + + + + + + ad rm + + Remove files and directories. + + The rm utility attempts to remove the non-directory type files + specified on the command line. If the files and directories reside on an + AFP volume, the corresponding CNIDs are deleted from the volumes + database. + + The options are as follows: + + + + -R + + + Attempt to remove the file hierarchy rooted in each file + argument. + + + + + -v + + + Be verbose when deleting files, showing them as they are + removed. + + + + + + + Reporting Bugs + + Report bugs to the Netatalk-devel list + <netatalk-devel@lists.sourceforge.net>. + + + + See also + + + dbd + + 1 + , + apple_dump + + 1 + . + + diff --git a/doc/manpages/man1/afpldaptest.1.xml b/doc/manpages/man1/afpldaptest.1.xml new file mode 100644 index 0000000..a7e73cd --- /dev/null +++ b/doc/manpages/man1/afpldaptest.1.xml @@ -0,0 +1,97 @@ + + + + afpldaptest + + 1 + + 22 Mar 2012 + + @NETATALK_VERSION@ + + + + afpldaptest + + Syntactically check ldap parameters in afp.conf + + + + + afpldaptestafpldaptest + + + -u USER + -g GROUP + -i UUID + + + + + afpldaptestafpldaptest + + + -h + -? + -: + + + + + + + DESCRIPTION + + afpldaptest is a simple command to syntactically + check ldap parameters in @pkgconfdir@/afp.conf. + + + + + OPTIONS + + + + USER + + + Show uuid for USER. + + + + + GROUP + + + Show uuid for GROUP. + + + + + UUID + + + Show user, group or local-uuid for + UUID. + + + + + + + + + Show the help and exit. + + + + + + + + + SEE ALSO + + afp.conf5 + + diff --git a/doc/manpages/man1/afppasswd.1.xml b/doc/manpages/man1/afppasswd.1.xml new file mode 100644 index 0000000..e67727f --- /dev/null +++ b/doc/manpages/man1/afppasswd.1.xml @@ -0,0 +1,151 @@ + + + + afppasswd + + 1 + + 22 Mar 2012 + + @NETATALK_VERSION@ + + + + afppasswd + + netatalk password maintenance utility + + + + + afppasswd + afppasswd + + UAM + + User Authentication Module + + + -acfn + + -p + passwdfile + + -u + minimumuid + + + + + DESCRIPTION + + afppasswd allows the maintenance of afppasswd + files created by netatalk for use by the uams_randnum.so UAM (providing + the "Randnum exchange" and "2-Way Randnum exchange" User Authentication + Modules). + + afppasswd can either be called by root with + parameters, or can be called by local system users with no parameters to + change their AFP passwords. + + + With this utility you can only change the passwords used by two + specific UAMs. As they provide only weak password encryption, the use of + the "Randnum exchange" and "2-Way Randnum exchange" UAMs is deprecated + unless one has to support very old AFP clients, that can not deal with + the more secure "DHCAST128" and "DHX2" UAM instead. Please compare with + the Authentication chapter inside + Netatalk's documentation. + + + + + EXAMPLE + + Local user changing their own password: + + example% afppasswd +Enter NEW AFP password: (hidden) +Enter NEW AFP password again: (hidden) +afppasswd: updated password. + + + + + OPTIONS + + + + + + + Add a new user to the afppasswd + file. + + + + + + + + Create and/or initialize afppasswd file or + specific user. + + + + + + + + Force the current action. + + + + + path + + + Path to afppasswd file. + + + + + + + + If cracklib support is built into netatalk this option will cause cracklib + checking to be disabled, if the superuser does not want to have the + password run against the cracklib dictionary. + + + + + minimum + uid + + + This is the minimum user id + (uid) that afppasswd will use when creating + users. + + + + + + + SEE ALSO + + + afpd + + 8 + , + afp.conf + + 5 + . + + \ No newline at end of file diff --git a/doc/manpages/man1/afpstats.1.xml b/doc/manpages/man1/afpstats.1.xml new file mode 100644 index 0000000..c2e9799 --- /dev/null +++ b/doc/manpages/man1/afpstats.1.xml @@ -0,0 +1,50 @@ + + + + afpstats + + 1 + + 24 Mar 2013 + + @NETATALK_VERSION@ + + + + afpstats + + List AFP statistics + + + + + afpstatsafpstats + + + + + DESCRIPTION + + afpstats list AFP statistics via D-Bus IPC. + + + + + NOTE + + afpd must support D-Bus. Check it by + "afpd -V". + + "" must be set in + @pkgconfdir@/afp.conf. + + + + + SEE ALSO + + afpd8, + afp.conf5, + dbus-daemon1 + + diff --git a/doc/manpages/man1/apple_dump.1.xml b/doc/manpages/man1/apple_dump.1.xml new file mode 100644 index 0000000..2457d1d --- /dev/null +++ b/doc/manpages/man1/apple_dump.1.xml @@ -0,0 +1,182 @@ + + + + apple_dump + + 1 + + 16 Jul 2012 + + @NETATALK_VERSION@ + + + + apple_dump + + Dump AppleSingle/AppleDouble format data + + + + + apple_dumpapple_dump + + -a + + + FILE + DIR + + + + + apple_dumpapple_dump + + -e + + + FILE + DIR + + + + + apple_dumpapple_dump + + -f + + FILE + + + + apple_dumpapple_dump + + -d + + FILE + + + + apple_dumpapple_dump + + + -h + -help + --help + + + + + apple_dumpapple_dump + + + -v + -version + --version + + + + + + + DESCRIPTION + + apple_dump is a perl script to dump + AppleSingle/AppleDouble format data. + This script can dump various AppleSingle/AppleDouble data created + by mailer, archiver, Mac OS X, Netatalk and so on. + With no FILE|DIR, or when FILE|DIR is -, read standard input. + + + + + OPTIONS + + + + [FILE|DIR] + + + This is default. + Dump a AppleSingle/AppleDouble file for + FILE or DIR + automatically. + If FILE is not AppleSingle/AppleDouble format, + look for extended attribute, + .AppleDouble/FILE and + ._FILE. + If DIR, look for + extended attribute, + DIR/.AppleDouble/.Parent and + ._DIR. + + + + + FILE|DIR + + + Dump extended attribute ofFILE or DIR. + + + + + [FILE] + + + Dump FILE. Assume FinderInfo to be FileInfo. + + + + + [FILE] + + + Dump FILE. Assume FinderInfo to be DirInfo. + + + + + + + + + Display the help and exit + + + + + + + + + Show version and exit + + + + + + + + + NOTE + + There is no way to detect whether FinderInfo is FileInfo or DirInfo. + By default, apple_dump examines whether file or directory, a parent directory + is .AppleDouble, filename is ._*, filename is .Parent, and so on. + + If setting option -e, -f or -d, assume FinderInfo and doesn't look + for another file. + + + + + SEE ALSO + + ad1, + getfattr1, + attr1, + runat1, + getextattr8, + lsextattr8 + + diff --git a/doc/manpages/man1/asip-status.pl.1.xml b/doc/manpages/man1/asip-status.pl.1.xml new file mode 100644 index 0000000..859b063 --- /dev/null +++ b/doc/manpages/man1/asip-status.pl.1.xml @@ -0,0 +1,162 @@ + + + + asip-status.pl + + 1 + + 24 Jul 2012 + + @NETATALK_VERSION@ + + + + asip-status.pl + + Queries AFP servers for their capabilities + + + + + asip-status.pl + asip-status.pl + + + -d + -i + -x + + HOSTNAME[:PORT] + + + + + + asip-status.pl + asip-status.pl + + + + -v + -version + --version + + + + + + + DESCRIPTION + + asip-status.pl is a perl script that + sends a FPGetSrvrInfo request to an AFP server at HOSTNAME:PORT and + displays the results, namely "Machine type", the server's name, supported + AFP versions, UAMs and AFP flags, the "server signature" and the network + addresses, the server provides AFP services on. + + When you don't supply :PORT, then the default AFP port, 548, will be + used. + + + + OPTIONS + + + + + + + Enable debug output. + + + + + + + + Show icon if it exists. + + + + + + + + Enable hex dump output. + + + + + + + + Show version. + + + + + + + + EXAMPLES + + asip-status.pl 192.168.1.15 +AFP reply from 192.168.1.15:548 +Flags: 1 Cmd: 3 ID: 57005 +Reply: DSIGetStatus +Request ID: 57005 +Machine type: Macintosh +AFP versions: AFPVersion 1.1,AFPVersion 2.0,AFPVersion 2.1,AFP2.2 +UAMs: Cleartxt passwrd,Randnum exchange,2-Way Randnum exchange +Volume Icon & Mask: Yes +Flags: + SupportsCopyFile + SupportsChgPwd + SupportsServerMessages + SupportsServerSignature + SupportsTCP/IP + SupportsSuperClient +Server name: bookchan +Signature: +04 1d 65 23 04 1d 65 23 04 1d 65 23 04 1d 65 23 ..e#..e#..e#..e# + +Network address: 192.168.1.15:548 (TCP/IP address and port) +Network address: 65280.128 (ddp address) + + + asip-status.pl myserver:10548 +AFP reply from myserver:10548 +Flags: 1 Cmd: 3 ID: 57005 +Reply: DSIGetStatus +Request ID: 57005 +Machine type: Netatalk3.0 +AFP versions: AFP2.2,AFPX03,AFP3.1,AFP3.2,AFP3.3 +UAMs: DHX2,DHCAST128 +Volume Icon & Mask: Yes +Flags: + SupportsCopyFile + SupportsServerMessages + SupportsServerSignature + SupportsTCP/IP + SupportsSrvrNotifications + SupportsOpenDirectory + SupportsUTF8Servername + SupportsUUIDs + SupportsExtSleep + SupportsSuperClient +Server name: myserver +Signature: +8a c6 12 3a 0e d9 95 3e 6f 31 e3 a9 17 f5 70 f6 ...:...>o1....p. + +Network address: 192.168.1.154:10548 (TCP/IP address and port) +UTF8 Servername: myserver + + + + + REPORTING BUGS + + Report bugs to the Netatalk-devel list + <netatalk-devel@lists.sourceforge.net>. + + diff --git a/doc/manpages/man1/dbd.1.xml b/doc/manpages/man1/dbd.1.xml new file mode 100644 index 0000000..4675378 --- /dev/null +++ b/doc/manpages/man1/dbd.1.xml @@ -0,0 +1,132 @@ + + + + dbd + + 1 + + 28 Dec 2012 + + @NETATALK_VERSION@ + + + + dbd + + CNID database maintenance + + + + + dbd + dbd + + + -cfFstuvV + + volumepath + + + + + Description + + dbd scans all file and directories of AFP + volumes, updating the CNID database of the volume. It must be run with + appropriate permissions i.e. as root.. + + + + Options + + + + -c + + + convert from adouble:v2 to adouble:ea + + + + + -f + + + delete and recreate CNID database + + + + + -F + + + location of the afp.conf config file + + + + + -s + + + scan volume: treat the volume as read only and don't perform + any filesystem modifications + + + + + -t + + + show statistics while running + + + + + -u + + + username for use with AFP volumes using user variable $u + + + + + -v + + + verbose + + + + + -V + + + display version info + + + + + + + CNID background + + The CNID backends maintains name to ID mappings. If you change a + filename outside afpd(8) (shell, samba), the CNID database will not + reflect that change. Netatalk tries to recover from such inconsistencies + as gracefully as possible. + + + + See also + + + cnid_metad + + 8 + , + cnid_dbd + + 8 + + + diff --git a/doc/manpages/man1/macusers.1.xml b/doc/manpages/man1/macusers.1.xml new file mode 100644 index 0000000..5cfee6f --- /dev/null +++ b/doc/manpages/man1/macusers.1.xml @@ -0,0 +1,75 @@ + + + + macusers + + 1 + + 13 Oct 2011 + + @NETATALK_VERSION@ + + + + macusers + + List the users connecting via AFP + + + + + macusersmacusers + + + + macusersmacusers + + + -v + -version + --version + -h + -help + --help + + + + + + + DESCRIPTION + + macusers list the users connecting via AFP. + + + + + OPTIONS + + + + + + + Show version and exit + + + + + + + + + Display the help and exit + + + + + + + + SEE ALSO + + afpd8 + + diff --git a/doc/manpages/man1/megatron.1.xml b/doc/manpages/man1/megatron.1.xml new file mode 100644 index 0000000..20b6405 --- /dev/null +++ b/doc/manpages/man1/megatron.1.xml @@ -0,0 +1,143 @@ + + + + megatron + + 1 + + 02 Sep 2011 + + @NETATALK_VERSION@ + + + + megatron + + unhex + + unbin + + unsingle + + hqx2bin + + single2bin + + macbinary + + Macintosh file format transformer + + + + + megatronmegatron + + sourcefile + + + + unbinunbin + + sourcefile + + + + unhexunhex + + sourcefile + + + + unsingleunsingle + + sourcefile + + + + hqx2binhqx2bin + + sourcefile + + + + single2binsingle2bin + + sourcefile + + + + macbinarymacbinary + + sourcefile + + + + + DESCRIPTION + + megatron is used to transform files from BinHex, + MacBinary, AppleSingle, or netatalk style + AppleDouble formats into MacBinary or netatalk + style AppleDouble formats. The netatalk + style AppleDouble format is the file format used by afpd, + the netatalk Apple Filing Protocol + (AppleShare) server. BinHex, MacBinary, and AppleSingle are commonly used + formats for transferring Macintosh files between machines via email or + file transfer protocols. megatron uses its name to + determine what type of transformation is being asked of it. + + If megatron is called as unhex + , unbin or unsingle, it tries to + convert file(s) from BinHex, MacBinary, or AppleSingle into AppleDouble + format. BinHex is the format most often used to send Macintosh files by + e-mail. Usually these files have an extension of ".hqx". MacBinary + is the format most often used by terminal emulators "on the fly" + when transferring Macintosh files in binary mode. MacBinary files often + have an extension of ".bin". Some Macintosh LAN-based email + packages use uuencoded AppleSingle format to "attach" or + "enclose" files in email. AppleSingle files don't have a + standard filename extension. + + If megatron is called as hqx2bin, + single2bin, or macbinary, it will + try to convert the file(s) from BinHex, AppleSingle, or AppleDouble into + MacBinary. This last translation may be useful in moving Macintosh files + from your afpd server to some other machine when you + can't copy them from the server using a Macintosh for some reason. + + If megatron is called with any other name, it + uses the default translation, namely unhex. + + If no source file is given, or if sourcefile + is `-', and if the + conversion is from a BinHex or MacBinary file, megatron + will read from standard input. + + The filename used to store any output file is the filename that is + encoded in the source file. MacBinary files are created with a + ".bin" extension. In the case of conflicts, the old file is + overwritten! + + + + OPTIONS + + + + + + + Show version. + + + + + + + + + SEE ALSO + + afpd8 + + diff --git a/doc/manpages/man1/netatalk-config.1.xml b/doc/manpages/man1/netatalk-config.1.xml new file mode 100644 index 0000000..69da13f --- /dev/null +++ b/doc/manpages/man1/netatalk-config.1.xml @@ -0,0 +1,163 @@ + + + + netatalk-config + + 1 + + 09 June 2001 + + @NETATALK_VERSION@ + + The Netatalk Project + + + + netatalk-config + + script to get information about the installed version of + netatalk + + + + + netatalk-confignetatalk-config + + --prefix =DIR + + --exec_prefix =DIR + + --help + + --version + + --libs + + --libs-dirs + + --libs-names + + --cflags + + --macros + + + + + DESCRIPTION + + netatalk-config is a tool that is used to + determine the compiler and linker flags that should be used + to compile and link programs that use the netatalk + run-time libraries. + + + + OPTIONS + + netatalk-config accepts the following options: + + + + + + + Print a short help for this command and exit. + + + + + + + + Print the currently installed version of netatalk + on the standard output. + + + + + + + + Print the linker flags that are necessary to link against the + netatalk run-time libraries. + + + + + + + + Print only the -l/-R part of --libs. + + + + + + + + Print only the -l part of --libs. + + + + + + + + Print the compiler flags that are necessary to compile a + program linked against the netatalk + run-time libraries. + + + + + + + + Print the netatalk m4 + directory. + + + + + + + + If specified, use PREFIX instead of the installation prefix + that netatalk was built with when + computing the output for the --cflags and --libs options. This + option is also used for the exec prefix if --exec-prefix was not + specified. This option must be specified before any --libs or + --cflags options. + + + + + + + + If specified, use PREFIX instead of the installation exec + prefix that netatalk was built with + when computing the output for the --cflags and --libs options. This + option must be specified before any --libs or --cflags options. + + + + + + + COPYRIGHT + + Copyright © 1998 Owen Taylor + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in supporting + documentation. + + Man page adapted for netatalk-config by Sebastian + Rittau in 2001. + + diff --git a/doc/manpages/man1/uniconv.1.xml b/doc/manpages/man1/uniconv.1.xml new file mode 100644 index 0000000..d563c28 --- /dev/null +++ b/doc/manpages/man1/uniconv.1.xml @@ -0,0 +1,227 @@ + + + + + uniconv + + 1 + + 19 Jan 2013 + + @NETATALK_VERSION@ + + + + uniconv + + convert Netatalk volume encoding + + + + + uniconvuniconv + + -ndv + + -c cnidbackend + + -f fromcode + + -t tocode + + -m maccode + + volumepath + + + + + Description + + uniconv converts the volume encoding of + volumepath from the fromcode + to the tocode encoding. + + + + Options + + + + -c + + + CNID backend used on this volume, usually cdb or dbd. Should + match the backend selected with afpd for this volume. If not + specified, the default CNID backend "@DEFAULT_CNID_SCHEME@" is + used + + + + + -d + + + don't HEX encode leading dots (:2e), equivalent to + in afp.conf5 + + + + + -f + + + encoding to convert from, use ASCII for HEX encoded volumes + + + + + -h + + + display help + + + + + -m + + + Macintosh client codepage, required for HEX encoded volumes. + Defaults to "MAC_ROMAN" + + + + + -n + + + "dry run", don't do any real changes + + + + + -t + + + volume encoding to convert to, e.g. UTF8 + + + + + -v + + + verbose output, use twice for maximum logging. + + + + + -V + + + print version and exit + + + + + + + + + WARNING + + Setting the wrong options might render your data unusable!!! Make + sure you know what you are doing. Always backup your data first. + + It is *strongly* recommended to do + a "dry run" first and to check the output for conversion errors. + + afpd8 + should not be running while you change the volume + encoding. Remember to change or + in + afp.conf5 + to the new codepage, before restarting afpd. + + In case of MacChineseTraditional, + MacJapanese or + MacKorean, + uniconv cannot be used. + + USE AT YOUR OWN RISK!!! + + + + Selectable charsets + + Netatalk provides internal support for UTF-8 (pre- and decomposed) + and HEX. If you want to use other charsets, they must be provided by + iconv1 + + uniconv also knows iso-8859.adapted, an old style + 1.x NLS widely used. This is only intended for upgrading old volumes, + afpd8 + cannot handle iso-8859.adapted anymore. + + + + CNID background + + The CNID backends maintains name to ID mappings. If you change a + filename outside afpd(8) (shell, samba), the CNID db, i.e. the DIDNAME + index, gets inconsistent. Netatalk tries to recover from such + inconsistencies as gracefully as possible. The mechanisms to resolve such + inconsistencies may fail sometimes, though, as this is not an easy task to + accomplish. I.e. if several names in the path to the file or directory + have changed, things may go wrong. + + If you change a lot of filenames at once, chances are higher that + the afpds fallback mechanisms fail, i.e. files will be assigned new IDs, + even though the file hasn't changed. uniconv + therefore updates the CNID entry for each file/directory directly after it + changes the name to avoid inconsistencies. The two supported backends for + volumes, dbd and cdb, use the same CNID db format. Therefore, you + could use uniconv with cdb and + afpd with dbd later. + + Warning: There must not be two + processes opening the CNID database using different backends at once! If a + volume is still opened with dbd (cnid_metad/cnid_dbd) and you start + uniconv with cdb, the result will be a corrupted CNID + database, as the two backends use different locking schemes. You might run + into additional problems, e.g. if dbd is compiled with transactions, cdb + will not update the transaction logs. + + In general, it is recommended to use the same backend for + uniconv you are using with + afpd8. + + + + Examples + + convert 1.x CAP encoded volume to UTF-8, clients used MacRoman + codepage, cnidscheme is dbd: + + example% uniconv -c dbd -f ASCII -t UTF8 -m MAC_ROMAN /path/to/share + + convert iso8859-1 volume to UTF-8, cnidscheme is cdb: + + example% uniconv -c cdb -f ISO-8859-1 -t UTF8 -m MAC_ROMAN /path/to/share + + convert 1.x volume using iso8859-1 adapted NLS to HEX encoding: + + example% uniconv -f ISO-8859-ADAPTED -t ASCII -m MAC_ROMAN/path/to/share + + convert UTF-8 volume to HEX, for MacCyrillic clients: + + example% uniconv -f UTF8 -t ASCII -m MAC_CYRILLIC /path/to/share + + + + See also + + afp.conf5,afpd8,iconv1,cnid_metad8,cnid_dbd8 + + diff --git a/doc/manpages/man5/Makefile.am b/doc/manpages/man5/Makefile.am new file mode 100644 index 0000000..1af5734 --- /dev/null +++ b/doc/manpages/man5/Makefile.am @@ -0,0 +1,26 @@ +XSLTPROC=@XSLTPROC@ +XSLTPROC_FLAGS=@XSLTPROC_FLAGS@ +MAN_STYLESHEET=$(top_srcdir)/doc/man.xsl +CLEANFILES = + +MAN_MANPAGES = \ + afp.conf.5 \ + afp_signature.conf.5 \ + afp_voluuid.conf.5 \ + extmap.conf.5 + +EXTRA_DIST = \ + afp_signature.conf.5.xml \ + afp_voluuid.conf.5.xml \ + afp.conf.5.xml \ + extmap.conf.5.xml + +if HAVE_XSLTPROC +CLEANFILES += $(MAN_MANPAGES) + +%.5 : %.5.xml + @xsltproc $(MAN_STYLESHEET) $< + @cp $@ $(top_builddir)/man/man5/$@.in + +html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET) +endif \ No newline at end of file diff --git a/doc/manpages/man5/Makefile.in b/doc/manpages/man5/Makefile.in new file mode 100644 index 0000000..0e90ad5 --- /dev/null +++ b/doc/manpages/man5/Makefile.in @@ -0,0 +1,537 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_XSLTPROC_TRUE@am__append_1 = $(MAN_MANPAGES) +subdir = doc/manpages/man5 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAN_STYLESHEET = $(top_srcdir)/doc/man.xsl +CLEANFILES = $(am__append_1) +MAN_MANPAGES = \ + afp.conf.5 \ + afp_signature.conf.5 \ + afp_voluuid.conf.5 \ + extmap.conf.5 + +EXTRA_DIST = \ + afp_signature.conf.5.xml \ + afp_voluuid.conf.5.xml \ + afp.conf.5.xml \ + extmap.conf.5.xml + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/manpages/man5/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/manpages/man5/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@HAVE_XSLTPROC_FALSE@html-local: +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: html-local + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am html-local info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +@HAVE_XSLTPROC_TRUE@%.5 : %.5.xml +@HAVE_XSLTPROC_TRUE@ @xsltproc $(MAN_STYLESHEET) $< +@HAVE_XSLTPROC_TRUE@ @cp $@ $(top_builddir)/man/man5/$@.in + +@HAVE_XSLTPROC_TRUE@html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET) + +# 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/doc/manpages/man5/afp.conf.5.xml b/doc/manpages/man5/afp.conf.5.xml new file mode 100644 index 0000000..b5a16e1 --- /dev/null +++ b/doc/manpages/man5/afp.conf.5.xml @@ -0,0 +1,2297 @@ + + + + afp.conf + + 5 + + 06 Aug 2014 + + @NETATALK_VERSION@ + + + + afp.conf + + Netatalk configuration file + afp.conf + + + + + SYNOPSIS + + The afp.conf file is the configuration file for + the Netatalk AFP file server. + + All AFP specific configuration and AFP volume definitions are done + via this file. + + + + FILE FORMAT + + The file consists of sections and parameters. A section begins with + the name of the section in square brackets and continues until the next + section begins. Sections contain parameters of the form: + name = value + + + The file is line-based - that is, each newline-terminated line + represents either a comment, a section name or a parameter. + + Section and parameter names are case sensitive. + + Only the first equals sign in a parameter is significant. Whitespace + before or after the first equals sign is discarded. Leading, trailing and + internal whitespace in section and parameter names is irrelevant. Leading + and trailing whitespace in a parameter value is discarded. Internal + whitespace within a parameter value is retained verbatim. + + Any line beginning with a semicolon (;) or a hash + (#) character is ignored, as are lines containing only + whitespace. + + Any line ending in a \ is + continued on the next line in the customary UNIX fashion. + + The values following the equals sign in parameters are all either a + string (no quotes needed) or a boolean, which may be given as yes/no, 1/0 + or true/false. Case is not significant in boolean values, but is preserved + in string values. Some items such as create masks are numeric. + + The parameter allows you to include one config + file inside another. The file is included literally, as though typed in + place. Nested includes are not supported. + + + + SECTION DESCRIPTIONS + + Each section in the configuration file (except for the [Global] + section) describes a shared resource (known as a volume). + The section name is the name of the volume and the parameters within the + section define the volume attributes and options. + + There are two special sections, [Global] and [Homes], which are + described under special sections. The following notes + apply to ordinary section descriptions. + + A volume consists of a directory to which access is being given plus + a description of the access rights which are granted to the user of the + service. For volumes the option must specify the + directory to share. + + Any volume section without option is + considered a vol preset which can be selected in + other volume sections via the option and + constitutes defaults for the volume. For any option specified both in a + preset and in a volume section the volume section + setting completely substitutes the preset option. + + The access rights granted by the server are masked by the access + rights granted to the specified or guest UNIX user by the host system. The + server does not grant more access than the host system grants. + + The following sample section defines an AFP volume. The user has + full access to the path /foo/bar. The share is + accessed via the share name baz: [baz] + path = /foo/bar + + + + SPECIAL SECTIONS + + + The [Global] section + + Parameters in this section apply to the server as a whole. + Parameters denoted by a (G) below are must be set in this + section. + + + + The [Homes] section + + This section enable sharing of the UNIX server user home + directories. Specifying an optional parameter + means that not the whole user home will be shared but the subdirectory + . It is necessary to define the option. It should be a regex which matches the parent + directory of the user homes. Parameters denoted by a (H) belong to + volume sections. The optional parameter can + be used to change the AFP volume name which $u's + home by default. See below under VARIABLE + SUBSTITUTIONS. + + The following example illustrates this. Given all user home + directories are stored under /home: + [Homes] + path = afp-data + basedir regex = /home For a user + john this results in an AFP home volume with a path + of /home/john/afp-data. + + If contains symlink, set the + canonicalized absolute path. When /home links to + /usr/home: [Homes] + basedir regex = /usr/home + + + + + PARAMETERS + + Parameters define the specific attributes of sections. + + Some parameters are specific to the [Global] section (e.g., + log type). All others are permissible only in volume + sections. The letter G in parentheses indicates that + a parameter is specific to the [Global] section. The letter + V indicates that a parameter can be specified in a + volume specific section. + + + + VARIABLE SUBSTITUTIONS + + You can use variables in volume names. The use of variables in paths + is limited to $u. + + + + if you specify an unknown variable, it will not get + converted. + + + + if you specify a known variable, but that variable doesn't have + a value, it will get ignored. + + + + The variables which can be used for substitutions are: + + + + $b + + + basename + + + + + $c + + + client's ip address + + + + + $d + + + volume pathname on server + + + + + $f + + + full name (contents of the gecos field in the passwd + file) + + + + + $g + + + group name + + + + + $h + + + hostname + + + + + $i + + + client's ip, without port + + + + + $s + + + server name (this can be the hostname) + + + + + $u + + + user name (if guest, it is the user that guest is running + as) + + + + + $v + + + volume name + + + + + $$ + + + prints dollar sign ($) + + + + + + + EXPLANATION OF GLOBAL PARAMETERS + + + Authentication Options + + + + ad domain = DOMAIN + (G) + + + Append @DOMAIN to username when authenticating. Useful in + Active Directory environments that otherwise would require the + user to enter the full user@domain string. + + + + + admin auth user = user + (G) + + + Specifying eg "" + whenever a normal user login fails, afpd will try to authenticate + as the specified . If this + succeeds, a normal session is created for the original connecting + user. Said differently: if you know the password of , you can authenticate as any other user. + + + + + k5 keytab = path + (G) + + k5 service = service + (G) + + k5 realm = realm + (G) + + + These are required if the server supports the Kerberos 5 + authentication UAM. + + + + + nt domain = DOMAIN + (G) + + nt separator = SEPARATOR + (G) + + + Use for eg. winbind authentication, prepends both strings + before the username from login and then tries to authenticate with + the result through the available and active UAM authentication + modules. + + + + + save password = BOOLEAN (default: + yes) (G) + + + Enables or disables the ability of clients to save passwords + locally. + + + + + set password = BOOLEAN (default: + no) (G) + + + Enables or disables the ability of clients to change their + passwords via chooser or the "connect to server" dialog. + + + + + uam list = uam list + (G) + + + Space or comma separated list of UAMs. (The default is + "uams_dhx.so uams_dhx2.so"). + + The most commonly used UAMs are: + + + + uams_guest.so + + + allows guest logins + + + + + uams_clrtxt.so + + + (uams_pam.so or uams_passwd.so) Allow logins with + passwords transmitted in the clear. (legacy) + + + + + uams_randum.so + + + allows Random Number and Two-Way Random Number + Exchange for authentication (requires a separate file + containing the passwords, either @pkgconfdir@/afppasswd file or + the one specified via "". See + + afppasswd + + 1 + for details. (legacy) + + + + + uams_dhx.so + + + (uams_dhx_pam.so or uams_dhx_passwd.so) Allow + Diffie-Hellman eXchange (DHX) for authentication. + + + + + uams_dhx2.so + + + (uams_dhx2_pam.so or uams_dhx2_passwd.so) Allow + Diffie-Hellman eXchange 2 (DHX2) for authentication. + + + + + uam_gss.so + + + Allow Kerberos V for authentication (optional) + + + + + + + + uam path = path + (G) + + + Sets the default path for UAMs for this server (default is + @libdir@/netatalk). + + + + + + + Charset Options + + With OS X Apple introduced the AFP3 protocol. One of the big + changes was, that AFP3 uses Unicode names encoded as Decomposed UTF-8 + (UTF8-MAC). Previous AFP/OS versions used charsets like MacRoman, + MacCentralEurope, etc. + + To be able to serve AFP3 and older clients at the same time, + afpd needs to be able to convert between UTF-8 and + Mac charsets. Even OS X clients partly still rely on the mac charset. As + there's no way, afpd can detect the codepage a pre + AFP3 client uses, you have to specify it using the option. The default is MacRoman, which should be fine + for most western users. + + As afpd needs to interact with UNIX operating + system as well, it need's to be able to convert from UTF8-MAC / Mac + charset to the UNIX charset. By default afpd uses + UTF8. You can set the UNIX charset using the + option. If you're using extended + characters in the configuration files for afpd, make + sure your terminal matches the . + + + + mac charset = CHARSET + (G)/(V) + + + Specifies the Mac clients charset, e.g. + MAC_ROMAN. This is used to convert strings + and filenames to the clients codepage for OS9 and Classic, i.e. + for authentication and AFP messages (SIGUSR2 messaging). This will + also be the default for the volumes . + Defaults to MAC_ROMAN. + + + + + unix charset = CHARSET + (G) + + + Specifies the servers unix charset, e.g. + ISO-8859-15 or EUC-JP. + This is used to convert strings to/from the systems locale, e.g. + for authentication, server messages and volume names. If + LOCALE is set, the systems locale is used. + Defaults to UTF8. + + + + + vol charset = CHARSET + (G)/(V) + + + Specifies the encoding of the volumes filesystem. By + default, it is the same as . + + + + + + + Password Options + + + + passwd file = path + (G) + + + Sets the path to the Randnum UAM passwd file for this server + (default is @pkgconfdir@/afppasswd). + + + + + passwd minlen = number + (G) + + + Sets the minimum password length, if supported by the + UAM + + + + + + + Network Options + + + + advertise ssh = BOOLEAN (default: + no) (G) + + + Allows old Mac OS X clients (10.3.3-10.4) to automagically + establish a tunneled AFP connection through SSH. If this option is + set, the server's answers to client's FPGetSrvrInfo requests + contain an additional entry. It depends on both client's settings + and a correctly configured and running + sshd + + 8 + on the server to let things work. + + + Setting this option is not recommended since globally + encrypting AFP connections via SSH will increase the server's + load significantly. On the other hand, Apple's client side + implementation of this feature in MacOS X versions prior to + 10.3.4 contained a security flaw. + + + + + + afp interfaces = name [name ...] + (G) + + Specifies the network interfaces that the server should + listens on. The default is advertise the first IP address of the + system, but to listen for any incoming request. + + + + + afp listen = ip address[:port] [ip address[:port] + ...] (G) + + + Specifies the IP address that the server should advertise + and listens to. The default is + advertise the first IP address of the system, but to listen for + any incoming request. The network address may be specified either + in dotted-decimal format for IPv4 or in hexadecimal format for + IPv6. + IPv6 address + port combination must use URL the format + using square brackets [IPv6]:port + + + + + afp port = port number + (G) + + + Allows a different TCP port to be used for AFP. The default + is 548. Also sets the default port applied when none specified in + an option. + + + + + cnid listen = ip address[:port] [ip + address[:port] ...] (G) + + + Specifies the IP address that the CNID server should listen + on. The default is localhost:4700. + + + + + disconnect time = number + (G) + + + Keep disconnected AFP sessions for + number hours before dropping them. Default + is 24 hours. + + + + + dsireadbuf = number + (G) + + + Scale factor that determines the size of the DSI/TCP + readahead buffer, default is 12. This is multiplies with the DSI + server quantum (default ~300k) to give the size of the buffer. + Increasing this value might increase throughput in fast local + networks for volume to volume copies. Note: + This buffer is allocated per afpd child process, so specifying + large values will eat up large amount of memory (buffer size * + number of clients). + + + + + fqdn = name:port + (G) + + + Specifies a fully-qualified domain name, with an optional + port. This is discarded if the server cannot resolve it. This + option is not honored by AppleShare clients <= 3.8.3. This + option is disabled by default. Use with caution as this will + involve a second name resolution step on the client side. Also + note that afpd will advertise this name:port combination but not + automatically listen to it. + + + + + hostname = name + (G) + + + Use this instead of the result from calling hostname for + determining which IP address to advertise, therefore the hostname + is resolved to an IP which is the advertised. This is NOT used for + listening and it is also overwritten by . + + + + + max connections = number + (G) + + + Sets the maximum number of clients that can simultaneously + connect to the server (default is 200). + + + + + server quantum = number + (G) + + + This specifies the DSI server quantum. The default value is + 0x100000 (1 MiB). The maximum value is 0xFFFFFFFFF, the minimum is + 32000. If you specify a value that is out of range, the default + value will be set. Do not change this value unless you're + absolutely sure, what you're doing + + + + + sleep time = number + (G) + + + Keep sleeping AFP sessions for number + hours before disconnecting clients in sleep mode. Default is 10 + hours. + + + + + tcprcvbuf = number + (G) + + + Try to set TCP receive buffer using setsockpt(). Often OSes + impose restrictions on the applications ability to set this + value. + + + + + tcpsndbuf = number + (G) + + + Try to set TCP send buffer using setsockpt(). Often OSes + impose restrictions on the applications ability to set this + value. + + + + + recvfile = BOOLEAN (default: + no) (G) + + + Whether to use splice() on Linux for receiving data. + + + + + splice size = number (default: + 64k) (G) + + + Maximum number of bytes spliced. + + + + + use sendfile = BOOLEAN (default: + yes) (G) + + + Whether to use sendfile + sendfile + syscall for sending file data to clients. + + + + + + zeroconf = BOOLEAN (default: + yes) (G) + + + Whether to use automatic Zeroconf + Zeroconf + + Bonjour + service registration if Avahi or mDNSResponder were + compiled in. + + + + + + + Miscellaneous Options + + + + admin group = group + (G) + + + Allows users of a certain group to be seen as the superuser + when they log in. This option is disabled by default. + + + + + afp read locks = BOOLEAN (default: + no) (G) + + + Whether to apply locks to the byte region read in FPRead + calls. The AFP spec mandates this, but it's not really in line + with UNIX semantics and is a performance hug. + + + + + afpstats = BOOLEAN (default: + no) (G) + + + Whether to provide AFP runtime statistics (connected + users, open volumes) via dbus. + + + + + basedir regex = regex + (H) + + + Regular expression which matches the parent directory of the + user homes. If contains symlink, + you must set the canonicalized absolute path. In the simple case + this is just a path ie + + + + + chmod request = preserve (default) | ignore | simple + (G/V) + + + Advanced permission control that deals with ACLs. + + + - UNIX chmod() + requests are completely ignored, use this option to + allow the parent directory's ACL inheritance full + control over new items. + + - preserve ZFS ACEs for + named users and groups or POSIX ACL group mask + + + - just to a chmod() as + requested without any extra steps + + + + + + + close vol = BOOLEAN (default: + no) (G) + + + Whether to close volumes possibly opened by clients when + they're removed from the configuration and the configuration is + reloaded. + + + + + cnid mysql host = MySQL server address + (G) + + + name or address of a MySQL server for use with the mysql CNID + backend. + + + + + cnid mysql user = MySQL user + (G) + + + MySQL user for authentication with the server. + + + + + cnid mysql pw = password + (G) + + + Password for MySQL server. + + + + + cnid mysql db = database name + (G) + + + Name of an existing database for which the specified user + has full privileges. + + + + + cnid server = ipaddress[:port] + (G)/(V) + + + Specifies the IP address and port of a cnid_metad server, + required for CNID dbd backend. Defaults to localhost:4700. The + network address may be specified either in dotted-decimal format + for IPv4 or in hexadecimal format for IPv6.- + + + + + dbus daemon = path + (G) + + + Sets the path to dbus-daemon binary used by Spotlight feature. + The default is /bin/dbus-daemon. + + + + + dircachesize = number + (G) + + + Maximum possible entries in the directory cache. The cache + stores directories and files. It is used to cache the full path to + directories and CNIDs which considerably speeds up directory + enumeration. + + Default size is 8192, maximum size is 131072. Given value is + rounded up to nearest power of 2. Each entry takes about 100 + bytes, which is not much, but remember that every afpd child + process for every connected user has its cache. + + + + + extmap file = path + (G) + + + Sets the path to the file which defines file extension + type/creator mappings. (default is @pkgconfdir@/extmap.conf). + + + + + force xattr with sticky bit = + BOOLEAN (default: + no) (G/V) + + + Writing metadata xattr on directories with the + sticky bit set may fail even though we may have write + access to a directory, because if the sticky bit is set + only the owner is allowed to write xattrs. + + By enabling this option Netatalk will write the + metadata xattr as root. + + + + + guest account = name + (G) + + + Specifies the user that guests should use (default is + "nobody"). The name should be quoted. + + + + + home name = name + (H) + + + AFP user home volume name. The default is user's + home. + + + + + ignored attributes = all | nowrite | nodelete | norename + (G)/(V) + + + Speficy a set of file and directory attributes that shall + be ignored by the server, includes all + the other options. + In OS X when the Finder sets a lock on a file/directory or you + set the BSD uchg flag in the Terminal, all three attributes are + used. Thus in order to ignore the Finder lock/BSD uchg flag, add + set ignored attributes = all. + + + + + login message = message + (G)/(V) + + + Sets a message to be displayed when clients logon to the + server. The message should be in and + should be quoted. Extended characters are allowed. + + + + + mimic model = model + (G) + + + Specifies the icon model that appears on clients. Defaults + to off. Note that afpd must support Zeroconf. + Examples: RackMac (same as Xserve), PowerBook, PowerMac, + Macmini, iMac, MacBook, MacBookPro, MacBookAir, MacPro, + AppleTV1,1, AirPort. + + + + + signature = <text> (G) + + + Specify a server signature. The maximum length is 16 + characters. This option is useful for clustered environments, to + provide fault isolation etc. By default, afpd generate signature + and saving it to + @localstatedir@/netatalk/afp_signature.conf + automatically (based on random number). See also + asip-status.pl(1). + + + + + solaris share reservations = + BOOLEAN (default: + yes) (G) + + + Use share reservations on Solaris. Solaris CIFS server uses + this too, so this makes a lock coherent multi protocol + server. + + + + + sparql results limit = + NUMBER (default: + UNLIMITED) (G) + + + Impose a limit on the number of results queried from Tracker + via SPARQL queries. + + + + + spotlight = + BOOLEAN (default: + no) (G)/(V) + + + Whether to enable Spotlight searches. Note: once the global + option is enabled, any volume that is not enabled won't be + searchable at all. See also dbus daemon + option. + + + + + spotlight attributes = + COMMA SEPERATED STRING (default: + EMPTY) (G) + + + A list of attributes that are allowed to be used in + Spotlight searches. By default all attributes can be + searched, passing a string limits attributes to elements + of the string. Example: spotlight + attributes = *,kMDItemTextContent + + + + + + spotlight expr = + BOOLEAN (default: + yes) (G) + + + Whether to allow the use of logic expression in + searches. + + + + + start dbus = + BOOLEAN (default: + yes) (G) + + + Whether to start a dbus instance for use with Tracker. + + + + + start tracker = + BOOLEAN (default: + yes) (G) + + + Whether to start Tracker with + tracker-control -s. + + + + + veto message = BOOLEAN (default: + no) (G) + + + Send optional AFP messages for vetoed files. Then whenever a + client tries to access any file or directory with a vetoed name, + it will be sent an AFP message indicating the name and the + directory. + + + + + vol dbpath = path + (G)/(V) + + + Sets the database information to be stored in path. You have + to specify a writable location, even if the volume is read only. + The default is + @localstatedir@/netatalk/CNID/$v/. + + + + + vol dbnest = BOOLEAN (default: + no) (G) + + + Setting this option to true brings back Netatalk 2 + behaviour of storing the CNID database in a folder called + .AppleDB inside the volume root of each share. + + + + + volnamelen = number + (G) + + + Max length of UTF8-MAC volume name for Mac OS X. Note that + Hangul is especially sensitive to this. + + 73: limit of Mac OS X 10.1 80: limit of Mac + OS X 10.4/10.5 (default) 255: limit of recent Mac OS + X Mac OS 9 and earlier are not influenced by + this, because Maccharset volume name is always limited to 27 + bytes. + + + + + vol preset = name + (G)/(V) + + + Use section as option preset for all + volumes (when set in the [Global] section) or for one volume (when + set in that volume's section). + + + + + + + Logging Options + + + + log file = logfile + (G) + + + If not specified Netatalk logs to syslogs daemon facility. + Otherwise it logs to . + + + + + log level = type:level [type:level + ...] (G) + + log level = type:level,[type:level, + ...] (G) + + + Specify that any message of a loglevel up to the given + should be logged. + + By default afpd logs to syslog with a default logging setup + equivalent to + + logtypes: default, afpdaemon, logger, uamsdaemon + + loglevels: severe, error, warn, note, info, debug, debug6, + debug7, debug8, debug9, maxdebug + + + Both logtype and loglevels are case insensitive. + + + + + + + + Filesystem Change Events (FCE<indexterm> + <primary>FCE</primary> + </indexterm>) + + Netatalk includes a nifty filesystem change event mechanism where + afpd processes notify interested listeners about certain filesystem + event by UDP network datagrams. + + The following FCE events are defined: + + + file modification () + file deletion () + directory deletion () + file creation () + directory creation () + file move or rename () + directory move or rename () + login () + logout () + + + + + fce listener = host[:port] + (G) + + + Enables sending FCE events to the specified + host, default port + is 12250 if not specified. Specifying multiple listeners is done + by having this option once for each of them. + + + + + fce version = 1|2 + (G) + + + FCE protocol version, default is 1. You need version + 2 for the fmov, dmov, login or logout events. + + + + + fce events = + fmod,fdel,ddel,fcre,dcre,fmov,dmov,login,logout + (G) + + + Specifies which FCE events are active, default is + fmod,fdel,ddel,fcre,dcre. + + + + + fce coalesce = all|delete|create + (G) + + + Coalesce FCE events. + + + + + fce holdfmod = seconds + (G) + + + This determines the time delay in seconds which is always + waited if another file modification for the same file is done by a + client before sending an FCE file modification event (fmod). For + example saving a file in Photoshop would generate multiple events + by itself because the application is opening, modifying and + closing a file multiple times for every "save". Default: 60 + seconds. + + + + + fce ignore names = NAME[/NAME2/...] + (G) + + + Slash delimited list of filenames for which FCE + events shall not be generated. Default: .DS_Store. + + + + + fce notify script = PATH + (G) + + + Script which will be executed for every FCE event, + see contrib/shell_utils/fce_ev_script.shfrom the Netatalk + sources for an example script. + + + + + + + + Debug Parameters + + These options are useful for debugging only. + + + + tickleval = number + (G) + + + Sets the tickle timeout interval (in seconds). Defaults to + 30. + + + + + timeout = number + (G) + + + Specify the number of tickles to send before timing out a + connection. The default is 4, therefore a connection will timeout + after 2 minutes. + + + + + client polling = BOOLEAN (default: + no) (G) + + + With this option enabled, afpd won't advertise that it is + capable of server notifications, so that connected clients poll + the server every 10 seconds to detect changes in opened server + windows. Note: Depending on the number of + simultaneously connected clients and the network's speed, this can + lead to a significant higher load on your network! + + Do not use this option any longer as present Netatalk + correctly supports server notifications, allowing connected + clients to update folder listings in case another client changed + the contents. + + + + + + + Options for ACL handling + + By default, the effective permission of the authenticated user are + only mapped to the mentioned UARights permission structure, not the UNIX + mode. You can adjust this behaviour with the configuration option + : + + + + map acls = none|rights|mode + (G) + + + + + none + + + no mapping of ACLs + + + + + rights + + + effective permissions are mapped to UARights + structure. This is the default. + + + + + mode + + + ACLs are additionally mapped to the UNIX mode of the + filesystem object. + + + + + + + + If you want to be able to display ACLs on the client, you must + setup both client and server as part on a authentication domain + (directory service, eg LDAP, Open Directory, Active Directory). The + reason is, in OS X ACLs are bound to UUIDs, not just uid's or gid's. + Therefor Netatalk must be able to map every filesystem uid and gid to a + UUID so that it can return the server side ACLs which are bound to UNIX + uid and gid mapped to OS X UUIDs. + + Netatalk can query a directory server using LDAP queries. Either + the directory server already provides an UUID attribute for user and + groups (Active Directory, Open Directory) or you reuse an unused + attribute (or add a new one) to you directory server (eg + OpenLDAP). + + The following LDAP options must be configured for Netatalk: + + + + ldap auth method = none|simple|sasl + (G) + + + Authentication method: + + + + none + + + anonymous LDAP bind + + + + + simple + + + simple LDAP bind + + + + + sasl + + + SASL. Not yet supported ! + + + + + + + + ldap auth dn = dn + (G) + + + Distinguished Name of the user for simple bind. + + + + + ldap auth pw = password + (G) + + + Distinguished Name of the user for simple bind. + + + + + ldap server = host + (G) + + + Name or IP address of your LDAP Server. This is only needed + for explicit ACL support in order to be able to query LDAP for + UUIDs. + + You can use + afpldaptest + + 1 + to syntactically check your config. + + + + + ldap userbase = base dn + (G) + + + DN of the user container in LDAP. + + + + + ldap userscope = scope + (G) + + + Search scope for user search: + + + + + ldap groupbase = base dn + (G) + + + DN of the group container in LDAP. + + + + + ldap groupscope = scope + (G) + + + Search scope for user search: + + + + + ldap uuid attr = dn + (G) + + + Name of the LDAP attribute with the UUIDs. + + Note: this is used both for users and groups. + + + + + ldap name attr = dn + (G) + + + Name of the LDAP attribute with the users short name. + + + + + ldap group attr = dn + (G) + + + Name of the LDAP attribute with the groups short + name. + + + + + ldap uuid string = STRING + (G) + + + Format of the uuid string in the directory. A series of x + and -, where every x denotes a value 0-9a-f and every - is a + separator. + + Default: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + + + + ldap uuid encoding = string | ms-guid (default: + string) (G) + + + Format of the UUID of the LDAP attribute, allows usage of + the binary objectGUID fields from Active Directory. If left + unspecified, string is the default, which passes through the ASCII + UUID returned by most other LDAP stores. If set to ms-guid, the + internal UUID representation is converted to and from the binary + format used in the objectGUID attribute found on objects in Active + Directory when interacting with the server. + See also the options and + . + + + string + + + UUID is a string, use with eg OpenDirectory. + + + + + ms-guid + + + Binary objectGUID from Active Directory + + + + + + + + ldap user filter = STRING (default: unused) + (G) + + + Optional LDAP filter that matches user objects. This is necessary for Active Directory + environments where users and groups are stored in the same directory subtree. + Recommended setting for Active Directory: objectClass=user. + + + + + ldap group filter = STRING (default: unused) + (G) + + + Optional LDAP filter that matches group objects. This is necessary for Active Directory + environments where users and groups are stored in the same directory subtree. + Recommended setting for Active Directory: objectClass=group. + + + + + + + + + EXPLANATION OF VOLUME PARAMETERS + + + Parameters + + The section name defines the volume name. + No two volumes may have the same + name. The volume name cannot contain the ':' + character. The volume name is mangled if it is very long. Mac charset + volume name is limited to 27 characters. UTF8-MAC volume name is limited + to volnamelen parameter. + + + + path = PATH (V) + + + The path name must be a fully qualified path name. + + + + + appledouble = ea|v2 + (V) + + + Specify the format of the metadata files, which are used for + saving Mac resource fork as well. Earlier versions used + AppleDouble v2, the new default format is ea. + + + + + vol size limit = size in MiB + (V) + + + Useful for Time Machine: limits the reported volume size, + thus preventing Time Machine from using the whole real disk space + for backup. Example: "vol size limit = 1000" would limit the + reported disk space to 1 GB. IMPORTANT: + This is an approximated calculation taking into + account the contents of Time Machine sparsebundle images. Therefor + you MUST NOT use this volume to store other content when using + this option, because it would NOT be accounted. The calculation + works by reading the band size from the Info.plist XML file of the + sparsebundle, reading the bands/ directory counting the number of + band files, and then multiplying one with the other. + + + + + valid users = user @group + (V) + + + The allow option allows the users and groups that access a + share to be specified. Users and groups are specified, delimited + by spaces or commas. Groups are designated by a @ prefix. Names + may be quoted in order to allow for spaces in names. Example: + valid users = user "user 2" @group “@group 2" + + + + + invalid users = users/groups + (V) + + + The deny option specifies users and groups who are not + allowed access to the share. It follows the same format as the + "valid users" option. + + + + + hosts allow = IP host address/IP netmask bits [ + ... ] (V) + + + Only listed hosts and networks are allowed, all others are + rejected. The network address may be specified either in + dotted-decimal format for IPv4 or in hexadecimal format for + IPv6. + + Example: hosts allow = 10.1.0.0/16 10.2.1.100 + 2001:0db8:1234::/48 + + + + + hosts deny = IP host address/IP netmask bits [ + ... ] (V) + + + Listed hosts and nets are rejected, all others are + allowed. + + Example: hosts deny = 192.168.100/24 10.1.1.1 + 2001:db8::1428:57ab + + + + + cnid scheme = backend + (V) + + + set the CNID backend to be used for the volume, default is + [@DEFAULT_CNID_SCHEME@] available schemes: + [@compiled_backends@] + + + + + ea = none|auto|sys|ad + (V) + + + Specify how Extended Attributes + Extended Attributes + are stored. is the + default. + + + + auto + + + Try (by setting an EA on the + shared directory itself), fallback to . + Requires writable volume for performing test. "" overwrites with + . Use explicit "" for read-only volumes where + appropriate. + + + + + sys + + + Use filesystem Extended Attributes. + + + + + ad + + + Use files in .AppleDouble + directories. + + + + + none + + + No Extended Attributes support. + + + + + + + + mac charset = CHARSET + (V) + + + specifies the Mac client charset for this Volume, e.g. + MAC_ROMAN, MAC_CYRILLIC. + If not specified the global setting is applied. This setting is + only required if you need volumes, where the Mac charset differs + from the one globally set in the [Global] section. + + + + + casefold = (V) + + + The casefold option handles, if the case of filenames should + be changed. The available options are: + + - Lowercases names in both + directions. + + - Uppercases names in both + directions. + + - Client sees lowercase, server + sees uppercase. + + - Client sees uppercase, server + sees lowercase. + + + + + password = password + (V) + + + This option allows you to set a volume password, which can + be a maximum of 8 characters long (using ASCII strongly + recommended at the time of this writing). + + + + + file perm = mode + (V) + + directory perm = mode + (V) + + + Add(or) with the client requested permissions: is for files only, + is for directories only. Don't use with "". + + + Volume for a collaborative workgroup + + file perm = 0660 directory perm = + 0770 + + + + + + umask = mode + (V) + + + set perm mask. Don't use with "". + + + + + preexec = command + (V) + + + command to be run when the volume is mounted, ignored for + user defined volumes + + + + + postexec = command + (V) + + + command to be run when the volume is closed, ignored for + user defined volumes + + + + + root preexec = command + (V) + + + command to be run as root when the volume is mounted, + ignored for user defined volumes + + + + + root postexec = command + (V) + + + command to be run as root when the volume is closed, ignored + for user defined volumes + + + + + rolist = (V) + + + Allows certain users and groups to have read-only access to + a share. This follows the allow option format. + + + + + rwlist = users/groups + (V) + + + Allows certain users and groups to have read/write access to + a share. This follows the allow option format. + + + + + veto files = vetoed names + (V) + + + hide files and directories,where the path matches one of the + '/' delimited vetoed names. The veto string must always be + terminated with a '/', eg. "veto files = veto1/", "veto files = + veto1/veto2/". + + + + + + + Volume options + + Boolean volume options. + + + + acls = BOOLEAN (default: + yes) (V) + + + Whether to flag volumes as supporting ACLs. If ACL support + is compiled in, this is yes by default. + + + + + case sensitive = BOOLEAN (default: + yes) (V) + + + Whether to flag volumes as supporting case-sensitive + filenames. If the filesystem is case-insensitive, set to no. + However, it is not fully verified. + + In spite of being case sensitive as a matter of fact, + netatalk 3.1.3 and earlier did not notify kCaseSensitive flag + to the client. Starting with 3.1.4, it is notified correctly by + default. + + + + + + cnid dev = BOOLEAN (default: + yes) (V) + + + Whether to use the device number in the CNID backends. Helps + when the device number is not constant across a reboot, eg + cluster, ... + + + + + convert appledouble = BOOLEAN + (default: yes) (V) + + + Whether automatic conversion from to is performed when + accessing filesystems from clients. This is generally useful, but + costs some performance. It's recommendable to run + dbd on volumes and do the conversion with that. + Then this option can be set to no. + + + + + delete veto files = BOOLEAN + (default: no) (V) + + + This option is used when Netatalk is attempting to delete a + directory that contains one or more vetoed files or directories + (see the veto files option). If this option is set to no (the + default) then if a directory contains any non-vetoed files or + directories then the directory delete will fail. This is usually + what you want. + If this option is set to yes, then Netatalk will attempt to + recursively delete any files and directories within the vetoed + directory. + + + + + follow symlinks = BOOLEAN (default: + no) (V) + + + The default setting is false thus symlinks are not followed + on the server. This is the same behaviour as OS X's AFP server. + Setting the option to true causes afpd to follow symlinks on the + server. symlinks may point outside of the AFP volume, currently + afpd doesn't do any checks for "wide symlinks". + + This option will subtly break when the symlinks point + across filesystem boundaries. + + + + + + invisible dots = BOOLEAN (default: + no) (V) + + + make dot files invisible. WARNING: enabling this option will + lead to unwanted sideeffects were OS X applications when saving + files to a temporary file starting with a dot first, then renaming + the temp file to its final name, result in the saved file being + invisible. The only thing this option is useful for is making + files that start with a dot invisible on Mac OS 9. It's + completely useless on Mac OS X, as both in Finder and in Terminal + files starting with a dot are hidden anyway. + + + + + network ids = BOOLEAN (default: + yes) (V) + + + Whether the server support network ids. Setting this to + no will result in the client not using ACL + AFP functions. + + + + + preexec close = BOOLEAN (default: + no) (V) + + + A non-zero return code from preexec close the volume being + immediately, preventing clients to mount/see the volume in + question. + + + + + read only = BOOLEAN (default: + no) (V) + + + Specifies the share as being read only for all users. + Overwrites with + + + + + root preexec close= BOOLEAN + (default: no) (V) + + + A non-zero return code from root_preexec closes the volume + immediately, preventing clients to mount/see the volume in + question. + + + + + search db = BOOLEAN (default: + no) (V) + + + Use fast CNID database namesearch instead of slow recursive + filesystem search. Relies on a consistent CNID database, ie Samba + or local filesystem access lead to inaccurate or wrong results. + Works only for "dbd" CNID db volumes. + + + + + stat vol = BOOLEAN (default: + yes) (V) + + + Whether to stat volume path when enumerating volumes list, + useful for automounting or volumes created by a preexec + script. + + + + + time machine = BOOLEAN (default: + no) (V) + + + Whether to enable Time Machine support for this + volume. + + + + + unix priv = BOOLEAN (default: + yes) (V) + + + Whether to use AFP3 UNIX privileges. This should be set for + OS X clients. See also: , + and . + + + + + + + + CNID backends + + The AFP protocol mostly refers to files and directories by ID and + not by name. Netatalk needs a way to store these ID's in a persistent way, + to achieve this several different CNID backends are available. The CNID + Databases are by default located in the + @localstatedir@/netatalk/CNID/(volumename)/.AppleDB/ + directory. + + + + cdb + + + "Concurrent database", backend is based on Oracle Berkley DB. + With this backend several afpd daemons access the + CNID database directly. Berkeley DB locking is used to synchronize + access, if more than one afpd process is active + for a volume. The drawback is, that the crash of a single + afpd process might corrupt the database. + + + + + dbd + + + Access to the CNID database is restricted to the + cnid_metad daemon process. + afpd processes communicate with the daemon for + database reads and updates. If built with Berkeley DB transactions + the probability for database corruption is practically zero, but + performance can be slower than with + + + + + last + + + This backend is an exception, in terms of ID persistency. ID's + are only valid for the current session. This is basically what + afpd did in the 1.5 (and 1.6) versions. This + backend is still available, as it is useful for e.g. sharing cdroms. + Starting with Netatalk 3.0, it becomes the read only + mode automatically. + + Warning: It is + NOT recommended to use this backend for volumes + anymore, as afpd now relies heavily on a + persistent ID database. Aliases will likely not work and filename + mangling is not supported. + + + + + Even though ./configure --help might show that + there are other CNID backends available, be warned those are likely broken + or mainly used for testing. Don't use them unless you know what you're + doing, they may be removed without further notice from future + versions. + + + + Charset options + + With OS X Apple introduced the AFP3 protocol. One of the most + important changes was that AFP3 uses unicode names encoded as UTF-8 + decomposed. Previous AFP/OS versions used codepages, like MacRoman, + MacCentralEurope, etc. + + afpd needs a way to preserve extended Macintosh + characters, or characters illegal in unix filenames, when saving files on + a unix filesystem. Earlier versions used the the so called CAP encoding. + An extended character (>0x7F) would be converted to a :xx sequence, + e.g. the Apple Logo (MacRoman: 0xF0) was saved as :f0. + Some special characters will be converted as to :xx notation as well. + '/' will be encoded to :2f, if + is not specified, a leading dot + '.' will be encoded as :2e. + + This version now uses UTF-8 as the default encoding for names. + '/' will be converted to ':'. + + The option will allow you to select + another volume encoding. E.g. for western users another useful setting + could be vol charset ISO-8859-15. afpd will accept any + + iconv + + 1 + provided charset. If a character cannot be converted + from the to the selected , afpd will save it as a CAP encoded character. For AFP3 + clients, afpd will convert the UTF-8 + UTF8 + + afpd's vol charset setting + + UTF8-MAC + + afpd's vol charset setting + + ISO-8859-15 + + afpd's vol charset setting + + ISO-8859-1 + + afpd's vol charset setting + character to first. If this + conversion fails, you'll receive a -50 error on the mac. + + Note: Whenever you can, please stick with the + default UTF-8 volume format. + + + + SEE ALSO + + + afpd + + 8 + , + afppasswd + + 5 + , + afp_signature.conf + + 5 + , + extmap.conf + + 5 + , + cnid_metad + + 8 + + + diff --git a/doc/manpages/man5/afp_signature.conf.5.xml b/doc/manpages/man5/afp_signature.conf.5.xml new file mode 100644 index 0000000..287b6d7 --- /dev/null +++ b/doc/manpages/man5/afp_signature.conf.5.xml @@ -0,0 +1,87 @@ + + + + + afp_signature.conf + + 5 + + 23 Mar 2012 + + @NETATALK_VERSION@ + + + + afp_signature.conf + + Configuration file used by afpd(8) to specify server + signature + afp_signature.conf + + + + + Description + + @localstatedir@/netatalk/afp_signature.conf is the + configuration file used by afpd to specify + server signature automagically. The configuration lines are + composed like: + + "server name" + hexa-string + + The first field is server name. Server names must be quoted + if they contain spaces. The second field is the hexadecimal string + of 32 characters for 16-bytes server signature. + The leading spaces and tabs are ignored. Blank lines are ignored. + The lines prefixed with # are ignored. The illegal lines are ignored. + + + + Server Signature is unique 16-bytes identifier used to + prevent logging on to the same server twice. + Netatalk 2.0 and earlier generated server signature by using + gethostid(). There was a problem that another servers have the same + signature because the hostid is not unique enough. + Current netatalk generates the signature from random numbers and + saves it into afp_signature.conf. When starting next time, it + is read from this file. + This file should not be thoughtlessly edited and be copied + onto another server. If it wants to set the signature intentionally, + use the option "signature =" in afp.conf. In this case, + afp_signature.conf is not used. + + + + + + + Examples + + + afp_signature.conf + + # This is a comment. +"My Server" 74A0BB94EC8C13988B2E75042347E528 + + + + + See also + + + afpd + + 8 + , + afp.conf + + 5 + , + asip-status.pl + + 1 + + + diff --git a/doc/manpages/man5/afp_voluuid.conf.5.xml b/doc/manpages/man5/afp_voluuid.conf.5.xml new file mode 100644 index 0000000..0956b47 --- /dev/null +++ b/doc/manpages/man5/afp_voluuid.conf.5.xml @@ -0,0 +1,88 @@ + + + + + afp_voluuid.conf + + 5 + + 23 Mar 2012 + + @NETATALK_VERSION@ + + + + afp_voluuid.conf + + Configuration file used by afpd(8) to specify UUID + for Time Machine volume + afp_voluuid.conf + + + + + Description + + @localstatedir@/netatalk/afp_voluuid.conf is the + configuration file used by afpd to specify + UUID of Time Machine volume automagically. The configuration + lines are composed like: + + "volume name" + uuid-string + + The first field is volume name. Volume names must be quoted + if they contain spaces. The second field is the 36 character + hexadecimal ASCII string representation of a UUID. + The leading spaces and tabs are ignored. Blank lines are ignored. + The lines prefixed with # are ignored. The illegal lines are ignored. + + + + This UUID is advertised by Zeroconf in order to provide + robust disambiguation of Time Machine volume. + The afpd generates the UUID from random numbers and saves it + into afp_voluuid.conf, only when setting "time machine = yes" option + in afp.conf. + This file should not be thoughtlessly edited and be copied + onto another server. + + + + + + + Examples + + + afp_voluuid.conf three TM volumes on one netatalk + + # This is a comment. +"Backup for John Smith" 1573974F-0ABD-69CC-C40A-8519B681A0E1 +"bob" 39A487F4-55AA-8240-E584-69AA01800FE9 +mary 6331E2D1-446C-B68C-3066-D685AADBE911 + + + + + See also + + + afpd + + 8 + , + afp.conf + + 5 + , + avahi-daemon + + 8 + , + mDNSResponder + + 8 + + + diff --git a/doc/manpages/man5/extmap.conf.5.xml b/doc/manpages/man5/extmap.conf.5.xml new file mode 100644 index 0000000..4265928 --- /dev/null +++ b/doc/manpages/man5/extmap.conf.5.xml @@ -0,0 +1,79 @@ + + + + extmap.conf + + 5 + + 19 Jan 2013 + + @NETATALK_VERSION@ + + + + extmap.conf + + Configuration file used by afpd(8) to + specify file name extension mappings. + extmap.conf + + + + + + + @pkgconfdir@/extmap.confextmap.conf + + + + + Description + + + @pkgconfdir@/extmap.conf is the + configuration file used by afpd to + specify file name extension mappings. + + The configuration lines are composed like: + + .extension [ type [ + creator ] ] + + Any line beginning with a hash (“#”) character is ignored. + The leading-dot lines specify file name extension mappings. + The extension '.' sets the default creator and type for otherwise + untyped Unix files. + + + + + Examples + + + Extension is jpg. Type is "JPEG". Creator is "ogle". + + .jpg "JPEG" "ogle" + + + + Extension is lzh. Type is "LHA ". Creator is not defined. + + .lzh "LHA " + + + + + + See Also + + + afp.conf + + 5 + , + afpd + + 8 + + + diff --git a/doc/manpages/man8/Makefile.am b/doc/manpages/man8/Makefile.am new file mode 100644 index 0000000..465977c --- /dev/null +++ b/doc/manpages/man8/Makefile.am @@ -0,0 +1,26 @@ +XSLTPROC=@XSLTPROC@ +XSLTPROC_FLAGS=@XSLTPROC_FLAGS@ +MAN_STYLESHEET=$(top_srcdir)/doc/man.xsl +CLEANFILES = + +MAN_MANPAGES = \ + afpd.8 \ + cnid_dbd.8 \ + cnid_metad.8 \ + netatalk.8 + +EXTRA_DIST = \ + afpd.8.xml \ + cnid_dbd.8.xml \ + cnid_metad.8.xml \ + netatalk.8.xml + +if HAVE_XSLTPROC +CLEANFILES += $(MAN_MANPAGES) + +%.8 : %.8.xml + @xsltproc $(MAN_STYLESHEET) $< + @cp $@ $(top_builddir)/man/man8/$@.in + +html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET) +endif \ No newline at end of file diff --git a/doc/manpages/man8/Makefile.in b/doc/manpages/man8/Makefile.in new file mode 100644 index 0000000..6eb74cc --- /dev/null +++ b/doc/manpages/man8/Makefile.in @@ -0,0 +1,537 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_XSLTPROC_TRUE@am__append_1 = $(MAN_MANPAGES) +subdir = doc/manpages/man8 +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAN_STYLESHEET = $(top_srcdir)/doc/man.xsl +CLEANFILES = $(am__append_1) +MAN_MANPAGES = \ + afpd.8 \ + cnid_dbd.8 \ + cnid_metad.8 \ + netatalk.8 + +EXTRA_DIST = \ + afpd.8.xml \ + cnid_dbd.8.xml \ + cnid_metad.8.xml \ + netatalk.8.xml + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/manpages/man8/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/manpages/man8/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@HAVE_XSLTPROC_FALSE@html-local: +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: html-local + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am html-local info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +@HAVE_XSLTPROC_TRUE@%.8 : %.8.xml +@HAVE_XSLTPROC_TRUE@ @xsltproc $(MAN_STYLESHEET) $< +@HAVE_XSLTPROC_TRUE@ @cp $@ $(top_builddir)/man/man8/$@.in + +@HAVE_XSLTPROC_TRUE@html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET) + +# 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/doc/manpages/man8/afpd.8.xml b/doc/manpages/man8/afpd.8.xml new file mode 100644 index 0000000..fff2758 --- /dev/null +++ b/doc/manpages/man8/afpd.8.xml @@ -0,0 +1,259 @@ + + + + afpd + + 8 + + 19 Jan 2013 + + @NETATALK_VERSION@ + + + + afpd + + Apple Filing Protocol daemon + + + + + afpd + afpd + + + -d + + -F configfile + + + + afpd + afpd + + + + -v + -V + -h + + + + + + + Description + + afpd provides an Apple Filing Protocol (AFP) + interface to the Unix file system. It is normally started at boot time + by netatalk(8). + + @pkgconfdir@/afp.conf is the configuration file + used by afpd to determine the behavior and + configuration of a file server. + + + + + Options + + + + -d + + + Specifies that the daemon should not fork. + + + + + + -v + + + Print version information and exit. + + + + + -V + + + Print verbose information and exit. + + + + + -h + + + Print help and exit. + + + + + -F configfile + + + Specifies the configuration file to use. (Defaults to + @pkgconfdir@/afp.conf.) + + + + + + + + SIGNALS + + To shut down a user's afpd process it is + recommended that SIGKILL (-9) + NOT be used, except as a last resort, as this + may leave the CNID database in an inconsistent state. The safe way + to terminate an afpd is to send it a + SIGTERM (-15) signal and wait for it to die on + its own. + SIGTERM and SIGUSR1 signals that are sent to the main afpd process + are propagated to the children, so all will be affected. + + + + SIGTERM + + Clean exit. Propagates from master to childs. + + + + + SIGQUIT + + Send this to the master afpd, it will + exit leaving all children running! Can be used to implement + AFP service without downtime. + + + + + SIGHUP + + Sending a SIGHUP to afpd will cause it to + reload its configuration files. + + + + + SIGINT + + Sending a SIGINT to a child + afpd enables max_debug + logging for this process. The log is sent to the file + /tmp/afpd.PID.XXXXXX. Sending another + SIGINT will revert to the original log settings. + + + + + SIGUSR1 + + The afpd process will send the message "The + server is going down for maintenance." to the client and shut itself + down in 5 minutes. New connections are not allowed. If this is sent + to a child afpd, the other children are not affected. However, the + main process will still exit, disabling all new connections. + + + + + SIGUSR2 + + The afpd process will look in the message + directory configured at build time for a file named message.pid. For + each one found, a the contents will be sent as a message to the + associated AFP client. The file is removed after the message is + sent. This should only be sent to a child + afpd. + + + + + + + FILES + + + + @pkgconfdir@/afp.conf + + + configuration file used by afpd + + + + + @localstatedir@/netatalk/afp_signature.conf + + + list of server signature + + + + + @localstatedir@/netatalk/afp_voluuid.conf + + + list of UUID for Time Machine volume + + + + + @pkgconfdir@/extmap.conf + + + file name extension mapping + + + + + @pkgconfdir@/msg/message.pid + + + contains messages to be sent to users. + + + + + + + SEE ALSO + + + netatalk + + 8 + , + hosts_access + + 5 + , + afp.conf + + 5 + , + afp_signature.conf + + 5 + , + afp_voluuid.conf + + 5 + , + extmap.conf + + 5 + , + dbd + + 1 + . + + diff --git a/doc/manpages/man8/cnid_dbd.8.xml b/doc/manpages/man8/cnid_dbd.8.xml new file mode 100644 index 0000000..9162047 --- /dev/null +++ b/doc/manpages/man8/cnid_dbd.8.xml @@ -0,0 +1,270 @@ + + + + cnid_dbd + + 8 + + 01 Jan 2012 + + @NETATALK_VERSION@ + + + + cnid_dbd + + implement access to CNID databases through a dedicated daemon + process + + + + + cnid_dbd + cnid_dbd + + CNID backend + + NFS + + Network File System + + + + + cnid_dbd + cnid_dbd + + + + -v + -V + + + + + + DESCRIPTION + + cnid_dbd provides an interface for storage and + retrieval of catalog node IDs (CNIDs) and related information to the + afpd daemon. CNIDs are a component of + Macintosh based file systems with semantics that map not easily onto Unix + file systems. This makes separate storage in a database necessary. + cnid_dbd is part of the CNID + backend framework of afpd and + implements the dbd backend. + + cnid_dbd is never started via the command line or + system startup scripts but only by the cnid_metad daemon. There is one instance of + cnid_dbd per netatalk volume. + + cnid_dbd uses the Berkeley + DB database library and uses transactionally protected updates. + The dbd backend with transactions will + avoid corruption of the CNID database even if the system crashes + unexpectedly. + + cnid_dbd inherits the effective userid and + groupid from cnid_metad on startup, which + is normally caused by afpd serving a + netatalk volume to a client. It changes to the Berkeley DB database home directory dbdir that is associated with the volume. If the + userid inherited from cnid_metad is 0 + (root), cnid_dbd will change userid and groupid to the + owner and group of the database home directory. Otherwise, it will + continue to use the inherited values. cnid_dbd will + then attempt to open the database and start serving requests using + filedescriptor clntfd. Subsequent instances + of afpd that want to access the same volume + are redirected to the running cnid_dbd process by + cnid_metad via the filedescriptor ctrlfd. + + cnid_dbd can be configured to run forever or to + exit after a period of inactivity. If cnid_dbd receives + a TERM or an INT signal it will exit cleanly after flushing dirty database + buffers to disk and closing Berkeley DB + database environments. It is safe to terminate cnid_dbd + this way, it will be restarted when necessary. Other signals are not + handled and will cause an immediate exit, possibly leaving the CNID + database in an inconsistent state (no transactions) or losing recent + updates during recovery (transactions). + + The Berkeley DB database subsystem + will create files named log.xxxxxxxxxx in the database home directory + dbdir, where xxxxxxxxxx is a monotonically + increasing integer. These files contain the transactional database + changes. They will be removed regularly, unless the logfile_autoremove option is specified in the + db_param configuration file (see + below) with a value of 0 (default 1). + + + + OPTIONS + + + + + + + Show version and exit. + + + + + + + CONFIGURATION + + cnid_dbd reads configuration information from the + file db_param in the database directory + dbdir on startup. If the file does not + exist or a parameter is not listed, suitable default values are used. The + format for a single parameter is the parameter name, followed by one or + more spaces, followed by the parameter value, followed by a newline. The + following parameters are currently recognized: + + + + logfile_autoremove + + + If set to 0, unused Berkeley DB transactional logfiles + (log.xxxxxxxxxx in the database home directory) are not removed on + startup of cnid_dbd and on a regular basis. + Default: 1. + + + + + cachesize + + + Determines the size of the Berkeley DB cache in kilobytes. + Default: 8192. Each cnid_dbd process grabs that + much memory on top of its normal memory footprint. It can be used to + tune database performance. The db_stat utility with the + option that comes with Berkley DB can help you determine ether you + need to change this value. The default is pretty conservative so + that a large percentage of requests should be satisfied from the + cache directly. If memory is not a bottleneck on your system you + might want to leave it at that value. The Berkeley DB Tutorial and Reference Guide has a + section Selecting a cache size that + gives more detailed information. + + + + + flush_frequency + + flush_interval + + + flush_frequency (Default: 1000) + and flush_interval (Default: 1800) + control how often changes to the database are checkpointed. Both of + these operations are performed if either i) more than flush_frequency requests have been received or + ii) more than flush_interval seconds + have elapsed since the last save/checkpoint. Be careful to check + your harddisk configuration for on disk cache settings. Many IDE + disks just cache writes as the default behaviour, so even flushing + database files to disk will not have the desired effect. + + + + + fd_table_size + + + is the maximum number of connections (filedescriptors) that + can be open for afpd client processes + in cnid_dbd. Default: 512. If this + number is exceeded, one of the existing connections is closed and + reused. The affected afpd process + will transparently reconnect later, which causes slight overhead. On + the other hand, setting this parameter too high could affect + performance in cnid_dbd since all descriptors + have to be checked in a select() system call, + or worse, you might exceed the per process limit of open file + descriptors on your system. It is safe to set the value to 1 on + volumes where only one afpd client + process is expected to run, e.g. home directories. + + + + + idle_timeout + + + is the number of seconds of inactivity before an idle + cnid_dbd exits. Default: 600. Set this to 0 to + disable the timeout. + + + + + + + UPDATING + + Note that the first version to appear after + Netatalk 2.1 ie Netatalk 2.1.1, will support BerkeleyDB updates on the fly + without manual intervention. In other words Netatalk 2.1 does contain code + to prepare the BerkeleyDB database for upgrades and to upgrade it in case + it has been prepared before. That means it can't upgrade a 2.0.x version + because that one didn't prepare the database. + + In order to update between older Netatalk releases using different + BerkeleyDB library versions, follow this steps: + + + + Stop the to be upgraded old version of Netatalk + + + + Using the old BerkeleyDB utilities run db_recover -h + <path to .AppleDB> + + + + Using the new BerkeleyDB utilities run db_upgrade -v -h + <path to .AppleDB> -f cnid2.db + + + + Again using the new BerkeleyDB utilities run + db_checkpoint -1 -h <path to .AppleDB> + + + + Start the the new version of Netatalk + + + + + + + SEE ALSO + + + cnid_metad + + 8 + , + afpd + + 8 + , + dbd + + 1 + + + diff --git a/doc/manpages/man8/cnid_metad.8.xml b/doc/manpages/man8/cnid_metad.8.xml new file mode 100644 index 0000000..3bd833b --- /dev/null +++ b/doc/manpages/man8/cnid_metad.8.xml @@ -0,0 +1,129 @@ + + + + cnid_metad + + 8 + + 23 Mar 2012 + + @NETATALK_VERSION@ + + + + cnid_metad + + start cnid_dbd daemons on request + + + + + cnid_metad + cnid_metad + + + -d + + -F configuration file + + + + cnid_metad + cnid_metad + + + + -v + -V + + + + + + DESCRIPTION + + cnid_metad waits for requests from afpd to start up instances of the cnid_dbd daemon. It keeps track of the status of a + cnid_dbd instance once started and will + restart it if necessary. cnid_metad is normally started + at boot time by netatalk(8) and runs + until shutdown. + + + + OPTIONS + + + + + + + + cnid_metad will remain in the foreground + and will also leave the standard input, standard output + and standard error file descriptors open. Useful for + debugging. + + + + + configuration file + + + Use configuration file as the + configuration file. The default is + @pkgconfdir@/afp.conf. + + + + + + + + Show version and exit. + + + + + + + CAVEATS + + cnid_metad does not block or catch any signals + apart from SIGPIPE. It will therefore exit on most signals received. This + will also cause all instances of cnid_dbd's + started by that cnid_metad to exit gracefully. Since + state about and IPC access to the subprocesses is only maintained in + memory by cnid_metad this is desired behaviour. As soon + as cnid_metad is restarted afpd processes will transparently reconnect. + + + + SEE ALSO + + + netatalk + + 8 + , + cnid_dbd + + 8 + , + afpd + + 8 + , + dbd + + 1 + , + afp.conf + + 5 + + + diff --git a/doc/manpages/man8/netatalk.8.xml b/doc/manpages/man8/netatalk.8.xml new file mode 100644 index 0000000..8c98011 --- /dev/null +++ b/doc/manpages/man8/netatalk.8.xml @@ -0,0 +1,96 @@ + + + + netatalk + + 8 + + 22 Mar 2012 + + @NETATALK_VERSION@ + + + + netatalk + + Netatalk AFP server service controller daemon + + + + + netatalk + netatalk + + + + + netatalk + netatalk + + + + + + Description + + netatalk is the service controller daemon + responsible for starting and restarting the AFP daemon + afpd and the CNID daemon cnid_metad. + It is normally started at boot time from /etc/rc. + + + + SIGNALS + + + + SIGTERM + + + Stop Netatalk service, AFP and CNID daemons + + + + + SIGHUP + + + Sending a SIGHUP will cause the AFP daemon + reload its configuration file. + + + + + + + FILES + + + + @pkgconfdir@/afp.conf + + + configuration file used by afpd and cnid_metad + + + + + + + SEE ALSO + + + afpd + + 8 + , + cnid_metad + + 8 + , + afp.conf + + 5 + . + + diff --git a/doc/manual/Makefile.am b/doc/manual/Makefile.am new file mode 100644 index 0000000..64870a5 --- /dev/null +++ b/doc/manual/Makefile.am @@ -0,0 +1,63 @@ +XSLTPROC=@XSLTPROC@ +XSLTPROC_FLAGS=@XSLTPROC_FLAGS@ +HTML_STYLESHEET=$(top_srcdir)/doc/html.xsl +CLEANFILES = + +XML_PAGES = \ + manual.xml \ + configuration.xml \ + install.xml \ + intro.xml \ + upgrade.xml + +EXTRA_DIST = \ + manual.xml.in \ + configuration.xml \ + install.xml \ + intro.xml \ + upgrade.xml \ + netatalk.html + +HTML_PAGES = \ + ad.1.html \ + afp.conf.5.html \ + afpd.8.html \ + afpldaptest.1.html \ + afppasswd.1.html \ + afp_signature.conf.5.html \ + afpstats.1.html \ + afp_voluuid.conf.5.html \ + apple_dump.1.html \ + asip-status.pl.1.html \ + cnid_dbd.8.html \ + cnid_metad.8.html \ + configuration.html \ + dbd.1.html \ + example-toc.html \ + extmap.conf.5.html \ + index.html \ + installation.html \ + intro.html \ + macusers.1.html \ + man-pages.html \ + manual-index.html \ + megatron.1.html \ + netatalk.8.html \ + netatalkconfig.1.html \ + pr01.html \ + table-toc.html \ + uniconv.1.html \ + upgrade.html + +DISTCLEANFILES = manual.xml + +if HAVE_XSLTPROC +CLEANFILES += $(HTML_PAGES) + +html-local: $(XML_PAGES) + @xsltproc $(HTML_STYLESHEET) manual.xml + +html-upload: html-local + scp $(HTML_PAGES) $$USER,netatalk@web.sourceforge.net:/home/project-web/netatalk/htdocs/3.1/htmldocs/ + +endif diff --git a/doc/manual/Makefile.in b/doc/manual/Makefile.in new file mode 100644 index 0000000..98f850c --- /dev/null +++ b/doc/manual/Makefile.in @@ -0,0 +1,576 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_XSLTPROC_TRUE@am__append_1 = $(HTML_PAGES) +subdir = doc/manual +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/manual.xml.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = manual.xml +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +HTML_STYLESHEET = $(top_srcdir)/doc/html.xsl +CLEANFILES = $(am__append_1) +XML_PAGES = \ + manual.xml \ + configuration.xml \ + install.xml \ + intro.xml \ + upgrade.xml + +EXTRA_DIST = \ + manual.xml.in \ + configuration.xml \ + install.xml \ + intro.xml \ + upgrade.xml \ + netatalk.html + +HTML_PAGES = \ + ad.1.html \ + afp.conf.5.html \ + afpd.8.html \ + afpldaptest.1.html \ + afppasswd.1.html \ + afp_signature.conf.5.html \ + afpstats.1.html \ + afp_voluuid.conf.5.html \ + apple_dump.1.html \ + asip-status.pl.1.html \ + cnid_dbd.8.html \ + cnid_metad.8.html \ + configuration.html \ + dbd.1.html \ + example-toc.html \ + extmap.conf.5.html \ + index.html \ + installation.html \ + intro.html \ + macusers.1.html \ + man-pages.html \ + manual-index.html \ + megatron.1.html \ + netatalk.8.html \ + netatalkconfig.1.html \ + pr01.html \ + table-toc.html \ + uniconv.1.html \ + upgrade.html + +DISTCLEANFILES = manual.xml +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/manual/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/manual/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +manual.xml: $(top_builddir)/config.status $(srcdir)/manual.xml.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@HAVE_XSLTPROC_FALSE@html-local: +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: html-local + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am html-local info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +@HAVE_XSLTPROC_TRUE@html-local: $(XML_PAGES) +@HAVE_XSLTPROC_TRUE@ @xsltproc $(HTML_STYLESHEET) manual.xml + +@HAVE_XSLTPROC_TRUE@html-upload: html-local +@HAVE_XSLTPROC_TRUE@ scp $(HTML_PAGES) $$USER,netatalk@web.sourceforge.net:/home/project-web/netatalk/htdocs/3.1/htmldocs/ + +# 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/doc/manual/configuration.xml b/doc/manual/configuration.xml new file mode 100644 index 0000000..535dd5f --- /dev/null +++ b/doc/manual/configuration.xml @@ -0,0 +1,1931 @@ + + + Setting up Netatalk + + + File Services<indexterm> + <primary>File Services</primary> + + <secondary>Netatalk's File Services</secondary> + </indexterm> + + Netatalk supplies AFP + AFP + + Apple Filing Protocol + services. + + + Setting up the AFP file server + + AFP (the Apple Filing Protocol) is the protocol Apple Macintoshes + use for file services. The protocol has evolved over the years. The + latest changes to the protocol, called "AFP 3.3", were added with the + release of Snow Leopard + Snow Leopard + + Mac OS X 10.6 + (Mac OS X 10.6). + + The afpd daemon offers the fileservices to Apple clients. The only + configuration file is afp.conf. It uses a ini style + configuration syntax. + + Support for Spotlight + Spotlight + has been added in Netatalk 3.1. See this section for information on how to + compile Netatalk with Spotlight support. + + Mac OS X 10.5 (Leopard) added support for Time Machine backups + over AFP. Two new functions ensure that backups are written to spinning + disk, not just in the server's cache. Different host operating systems + honour this cache flushing differently. To make a volume a Time Machine + target use the volume option "". + + Starting with Netatalk 2.1 UNIX symlinks + symlink + + UNIX symlink + can be used on the server. Semantics are the same as for + eg NFS, ie they are not resolved on the server side but instead it's + completely up to the client to resolve them, resulting in links that + point somewhere inside the clients filesystem view. + + + afp.conf + + afp.conf is the configuration file used by + afpd to determine the behaviour and configuration of the AFP file + serverand the AFP volume that it provides. + + The afp.conf is divided into several + sections: + + [Global] + + + The global section defines general server options + + + + + [Homes] + + + The homes section defines user home volumes + + + Any section not called or + is interpreted as an AFP volume. + + For sharing user homes by defining a + section you must specify the option + which can be a simple string with the path to the parent directory of + all user homes or a regular expression. + + Example: + + [Homes] +basedir regex = /home + + + Now any user logging into the AFP server will have a user volume + available whos path is /home/NAME. + + A more complex setup would be a server with a large amount of + user homes which are split across eg two different + filesystems: + + /RAID1/homes + + + + /RAID2/morehomes + + The following configuration is + required:[Homes] +basedir regex = /RAID./.*homes + + + If contains symlink, set the + canonicalized absolute path. When /home links to + /usr/home: [Homes] +basedir regex = /usr/home + + For a more detailed explanation of the available options, please + refer to the + afp.conf + + 5 + man page. + + + + + CNID<indexterm> + <primary>CNID</primary> + + <secondary>Catalog Node ID</secondary> + </indexterm> backends<indexterm> + <primary>Backend</primary> + + <secondary>CNID backend</secondary> + </indexterm> + + Unlike other protocols like SMB or NFS, the AFP protocol mostly + refers to files and directories by ID and not by a path (the IDs are + also called CNID, that means Catalog Node ID). A typical AFP request + uses a directory ID + DID + + Directory ID + and a filename, something like "server, please + open the file named 'Test' in the directory with id 167". For + example "Aliases" on the Mac basically work by ID (with a fallback to + the absolute path in more recent AFP clients. But this applies only to + Finder, not to applications). + + Every file in an AFP volume has to have a unique file ID + FID + + File ID + , IDs must, according to the specs, never be reused, and + IDs are 32 bit numbers (Directory IDs use the same ID pool). So, after + ~4 billion files/folders have been written to an AFP volume, the ID pool + is depleted and no new file can be written to the volume. No whining + please :-) + + Netatalk needs to map IDs to files and folders in the host + filesystem. To achieve this, several different CNID backends + CNID backend + are available and can be choosed by the + cnidscheme + + specifying a CNID backend + option in the + afp.conf + + 5 + configuration file. A CNID backend is basically a + database storing ID <-> name mappings. + + The CNID Databases are by default located in + /var/netatalk/CNID. + + There is a command line utility called dbd + available which can be used to verify, repair and rebuild the CNID + database. + + + There are some CNID related things you should keep in mind when + working with netatalk: + + + + Don't nest volumes + Nested volumes + . + + + + CNID backends are databases, so they turn afpd into a file + server/database mix. + + + + If there's no more space on the filesystem left, the + database will get corrupted. You can work around this by either + using the option and put the database + files into another location or, if you use quotas, make sure the + CNID database folder is owned by a user/group without a + quota + Quotas + + Disk usage quotas + . + + + + Be careful with CNID databases for volumes that are mounted + via NFS. That is a pretty audacious decision to make anyway, but + putting a database there as well is really asking for trouble, + i.e. database corruption. Use the + directive to put the databases onto a local disk if you must use + NFS + NFS + + Network File System + mounted volumes. + + + + + + cdb<indexterm> + <primary>CDB</primary> + + <secondary>"cdb" CNID backend</secondary> + </indexterm> + + The "concurrent database" backend is based on Berkeley DB. With + this backend, several afpd daemons access the CNID database directly. + Berkeley DB locking is used to synchronize access, if more than one + afpd process is active for a volume. The drawback is, that the crash + of a single afpd process might corrupt the database. cdb should only + be used when sharing home directories for a larger number of users + and it has been determined that a large number of + cnid_dbd processes is problematic. + + + + dbd<indexterm> + <primary>DBD</primary> + + <secondary>"dbd" CNID backend</secondary> + </indexterm> + + Access to the CNID database is restricted to the cnid_dbd daemon + process. afpd processes communicate with the daemon for database reads + and updates. The probability for database corruption is practically + zero. + + This is the default backend since Netatalk 2.1. + + + + tdb<indexterm> + <primary>tdb</primary> + + <secondary>"tdb" CNID backend</secondary> + </indexterm> + + tdb is another persistent CNID database, it's + Samba's Trivial Database. It could be used + instead of cdb for user volumes. + Only ever use it for volumes that are + not shared and accessed by multiple clients + at once ! + This backend is also used internally (as in-memory CNID + database) as a fallback in case opening the primary database can't be + opened, because tdb can work as in-memory database. + This of course means upon restart the CNIDs are gone. + + + + last<indexterm> + <primary>Last</primary> + + <secondary>"last" CNID backend</secondary> + </indexterm> + + The last backend is a in-memory tdb database. It is not + persistent. Starting with netatalk 3.0, it becomes the read + only mode automatically. This is useful e.g. for + CD-ROMs. + + + + mysql<indexterm> + <primary>MySQL</primary> + + <secondary>"mysql" CNID backend</secondary> + </indexterm> + + CNID backend using a MySQL server. + + + + + Charsets<indexterm> + <primary>Charset</primary> + + <secondary>character set</secondary> + </indexterm>/Unicode<indexterm> + <primary>Unicode</primary> + </indexterm> + + + + + Why Unicode? + + Internally, computers don't know anything about characters and + texts, they only know numbers. Therefore, each letter is assigned a + number. A character set, often referred to as + charset or + codepage + Codepage + , defines the mappings between numbers and + letters. + + If two or more computer systems need to communicate with each + other, the have to use the same character set. In the 1960s the + ASCII + ASCII + + American Standard Code for Information + Interchange + (American Standard Code for Information Interchange) + character set was defined by the American Standards Association. The + original form of ASCII represented 128 characters, more than enough to + cover the English alphabet and numerals. Up to date, ASCII has been + the normative character scheme used by computers. + + Later versions defined 256 characters to produce a more + international fluency and to include some slightly esoteric graphical + characters. Using this mode of encoding each character takes exactly + one byte. Obviously, 256 characters still wasn't enough to map all the + characters used in the various languages into one character + set. + + As a result localized character sets were defined later, e.g the + ISO-8859 character sets. Most operating system vendors introduced + their own characters sets to satisfy their needs, e.g. IBM defined the + codepage 437 (DOSLatinUS), Apple introduced the + MacRoman + MacRoman + + MacRoman charset + codepage and so on. The characters that were assigned + number larger than 127 were referred to as + extended characters. These character sets + conflict with another, as they use the same number for different + characters, or vice versa. + + Almost all of those characters sets defined 256 characters, + where the first 128 (0-127) character mappings are identical to ASCII. + As a result, communication between systems using different codepages + was effectively limited to the ASCII charset. + + To solve this problem new, larger character sets were defined. + To make room for more character mappings, these character sets use at + least 2 bytes to store a character. They are therefore referred to as + multibyte character sets. + + One standardized multibyte charset encoding scheme is known as + unicode. A big advantage + of using a multibyte charset is that you only need one. There is no + need to make sure two computers use the same charset when they are + communicating. + + + + character sets used by Apple + + In the past, Apple clients used single-byte charsets to + communicate over the network. Over the years Apple defined a number of + codepages, western users will most likely be using the + MacRoman codepage. + + Codepages defined by Apple include: + + + + MacArabic, MacFarsi + + + + MacCentralEurope + + + + MacChineseSimple + + + + MacChineseTraditional + + + + MacCroation + + + + MacCyrillic + + + + MacDevanagari + + + + MacGreek + + + + MacHebrew + + + + MacIcelandic + + + + MacJapanese + + + + MacKorean + + + + MacRoman + + + + MacRomanian + + + + MacThai + + + + MacTurkish + + + + Starting with Mac OS X and AFP3, UTF-8 is used. UTF-8 encodes + Unicode characters in an ASCII compatible way, each Unicode character + is encoded into 1-6 ASCII characters. UTF-8 is therefore not really a + charset itself, it's an encoding of the Unicode charset. + + To complicate things, Unicode defines several normalization + forms. While samba + Samba + uses precomposed + Precomposed + + Precomposed Unicode normalization + Unicode, which most Unix tools prefer as well, Apple + decided to use the decomposed + Decomposed + + Decomposed Unicode normalization + normalization. + + For example lets take the German character + 'ä'. Using the precomposed normalization, Unicode + maps this character to 0xE4. In decomposed normalization, 'ä' is + actually mapped to two characters, 0x61 and 0x308. 0x61 is the mapping + for an 'a', 0x308 is the mapping for a COMBINING + DIAERESIS. + + Netatalk refers to precomposed UTF-8 as + UTF8 + UTF8 + + Netatalk's precomposed UTF-8 encoding + and to decomposed UTF-8 as + UTF8-MAC + UTF8-MAC + + Netatalk's decomposed UTF-8 encoding + . + + + + afpd and character sets + + To support new AFP 3.x and older AFP 2.x clients at the same + time, afpd needs to be able to convert between the various charsets + used. AFP 3.x clients always use UTF8-MAC, AFP 2.x clients use one of + the Apple codepages. + + At the time of this writing, netatalk supports the following + Apple codepages: + + + + MAC_CENTRALEUROPE + + + + MAC_CHINESE_SIMP + + + + MAC_CHINESE_TRAD + + + + MAC_CYRILLIC + + + + MAC_GREEK + + + + MAC_HEBREW + + + + MAC_JAPANESE + + + + MAC_KOREAN + + + + MAC_ROMAN + + + + MAC_TURKISH + + + + afpd handles three different character set options: + + + + unix charset + unix charset + + afpd's unix charset setting + + + + This is the codepage used internally by your operating + system. If not specified, it defaults to . + If is specified and your system support + Unix locales, afpd tries to detect the codepage. afpd uses this + codepage to read its configuration files, so you can use + extended characters for volume names, login messages, etc. see + + afp.conf + + 5 + . + + + + + mac charset + mac charset + + afpd's mac charset setting + + + + As already mentioned, older Mac OS clients (up to AFP 2.2) + use codepages to communicate with afpd. However, there is no + support for negotiating the codepage used by the client in the + AFP protocol. If not specified otherwise, afpd assumes the + MacRoman codepage is used. In case you're + clients use another codepage, e.g. + MacCyrillic, you'll have to explicitly configure this. see + + afp.conf + + 5 + . + + + + + vol charset + vol charset + + afpd's vol charset setting + + + + This defines the charset afpd should use for filenames on + disk. By default, it is the same as . If you have iconv + Iconv + + iconv encoding conversion engine + installed, you can use any iconv provided charset + as well. + + afpd needs a way to preserve extended macintosh + characters, or characters illegal in unix filenames, when saving + files on a unix filesystem. Earlier versions used the the so + called CAP encoding + CAP encoding + + CAP style character encoding + . An extended character (>0x7F) would be + converted to a :xx hex sequence, e.g. the Apple Logo (MacRoman: + 0xF0) was saved as :f0. Some special characters will be + converted as to :xx notation as well. '/' will be encoded to + :2f, if was not specified, a leading + dot '.' will be encoded as :2e. + + Even though this version now uses as + the default encoding for filenames, '/' will be converted to + ':'. For western users another useful setting could be + . + + If a character cannot be converted from the to the selected , + afpd will save it as a CAP encoded character. For AFP3 clients, + afpd will convert the UTF8 character to first. If this conversion fails, you'll receive + a -50 error on the mac. Note: Whenever you + can, please stick with the default UTF8 volume format. see + + afp.conf + + 5 + . + + + + + + + + Authentication<indexterm> + <primary>Authentication</primary> + + <secondary>between AFP client and server</secondary> + </indexterm> + + + AFP authentication basics + + Apple chose a flexible model called "User Authentication + Modules" + UAM + + User Authentication Module + (UAMs) for authentication purposes between AFP client + and server. An AFP client initially connecting to an AFP server will + ask for the list of UAMs which the server provides, and will choose + the one with strongest encryption that the client supports. + + Several UAMs have been developed by Apple over the time, some by + 3rd-party developers. + + + + UAMs supported by Netatalk + + Netatalk supports the following ones by default: + + + + "No User Authent" + No User Authent + + "No User Authent" UAM (guest access) + UAM (guest access without authentication) + + + + "Cleartxt Passwrd" + Cleartxt Passwrd + + "Cleartxt Passwrd" UAM + UAM (no password encryption) + + + + "Randnum exchange" + Randnum exchange + + "Randnum exchange" UAM + /"2-Way Randnum exchange" + 2-Way Randnum exchange + + "2-Way Randnum exchange" UAM + UAMs (weak password encryption, separate password + storage) + + + + "DHCAST128" + DHCAST128 + + "DHCAST128" UAM + UAM (stronger password encryption) + + + + "DHX2" + DHX2 + + "DHX2" UAM + UAM (successor of DHCAST128) + + + + There exist other optional UAMs as well: + + + + "PGPuam 1.0" + PGPuam 1.0 + + "PGPuam 1.0" UAM + + uams_pgp.so + + "PGPuam 1.0" UAM + UAM (PGP-based authentication for pre-Mac OS X + clients. You'll also need the PGPuam + client to let this work) + + You'll have to add "--enable-pgp-uam" + to your configure switches to have this UAM available. + + + + "Kerberos IV" + Kerberos IV + + "Kerberos IV" UAM + + uams_krb4.so + + "Kerberos IV" UAM + /"AFS Kerberos" + AFS Kerberos + + "AFS Kerberos" UAM (Kerberos IV) + UAMs (suitable to use Kerberos + v4 based authentication and AFS file servers) + + Use "--enable-krb4-uam" at compile time + to activate the build of this UAM. + + + + "Client Krb v2" + Client Krb v2 + + "Client Krb v2" UAM (Kerberos V) + UAM (Kerberos V, suitable for "Single Sign On" + Scenarios with OS X clients -- see below) + + "--enable-krbV-uam" will provide you + with the ability to use this UAM. + + + + You can configure which UAMs should be activated by defining + "" in section. + afpd will log which UAMs it's using and if problems + occur while activating them in either + netatalk.log or syslog at startup time. + + asip-status.pl + + 1 + can be used to query the available UAMs of AFP + servers as well. + + Having a specific UAM available at the server does not + automatically mean that a client can use it. Client-side support is + also necessary. For older Macintoshes running Mac OS < X DHCAST128 + support exists since AppleShare client 3.8.x. + + On OS X, there exist some client-side techniques to make the + AFP-client more verbose, so one can have a look what's happening while + negotiating the UAMs to use. Compare with this hint. + + + + Which UAMs to activate? + + It depends primarily on your needs and on the kind of Mac OS + versions you have to support. Basically one should try to use + DHCAST128 and DHX2 where possible because of its strength of password + encryption. + + + + Unless you really have to supply guest access to your + server's volumes ensure that you disable "No User Authent" since + it might lead accidentally to unauthorized access. In case you + must enable guest access take care that you enforce this on a per + volume base using the access controls. + + + + The "ClearTxt Passwrd" UAM is as bad as it sounds since + passwords go unencrypted over the wire. Try to avoid it at both + the server's side as well as on the client's. Note: If you want to + provide Mac OS 8/9 clients with NetBoot-services then you need + uams_cleartext.so since the AFP-client integrated into the Mac's + firmware can only deal with this basic form of + authentication. + + + + Since "Randnum exchange"/"2-Way Randnum exchange" uses only + 56 bit DES for encryption it should be avoided as well. Another + disadvantage is the fact that the passwords have to be stored in + cleartext on the server and that it doesn't integrate into both + PAM scenarios or classic /etc/shadow (you have to administrate + passwords separately by using the + afppasswd + + 1 + utility, if clients should use these + UAMs) + + + + "DHCAST128" or "DHX2" should be a good compromise for most + people since it combines stronger encryption with PAM + integration. + + + + Using the Kerberos V + Kerberos V + + "Client Krb v2" UAM + ("Client Krb v2") UAM, it's possible to implement + real single sign on scenarios using Kerberos tickets. The password + is not sent over the network. Instead, the user password is used + to decrypt a service ticket for the appleshare server. The service + ticket contains an encryption key for the client and some + encrypted data (which only the appleshare server can decrypt). The + encrypted portion of the service ticket is sent to the server and + used to authenticate the user. Because of the way that the afpd + service principal detection is implemented, this authentication + method is vulnerable to man-in-the-middle attacks. + + + + For a more detailed overview over the technical implications of + the different UAMs, please have a look at Apple's File + Server Security pages. + + + + Using different authentication sources with specific + UAMs + + Some UAMs provide the ability to use different authentication + "backends", namely uams_cleartext.so, + uams_dhx.so and + uams_dhx2.so. They can use either classic Unix + passwords from /etc/passwd + (/etc/shadow) or PAM if the system supports that. + uams_cleartext.so can be symlinked to either + uams_passwd.so or + uams_pam.so, uams_dhx.so to + uams_dhx_passwd.so or + uams_dhx_pam.so and + uams_dhx2.so to + uams_dhx2_passwd.so or + uams_dhx2_pam.so. + + So, if it looks like this in Netatalk's UAMs folder (per default + /etc/netatalk/uams/):uams_clrtxt.so -> uams_pam.so +uams_dhx.so -> uams_dhx_pam.so +uams_dhx2.so -> uams_dhx2_pam.so then you're using PAM, + otherwise classic Unix passwords. The main advantage of using PAM is + that one can integrate Netatalk in centralized authentication + scenarios, eg. via LDAP, NIS and the like. Please always keep in mind + that the protection of your user's login credentials in such scenarios + also depends on the strength of encryption that the UAM in question + supplies. So think about eliminating weak UAMs like "ClearTxt Passwrd" + and "Randnum exchange" completely from your network. + + + + Netatalk UAM overview table + + A small overview of the most common used UAMs. + + + Netatalk UAM overview + + + + + + + + + + + + + + + + + + + UAM + + No User Authent + uams_guest.so + + "No User Authent" UAM (guest + access) + + + Cleartxt Passwrd + uams_cleartxt.so + + "Cleartxt Passwrd" UAM + + + (2-Way) Randnum exchange + uams_randnum.so + + "(2-Way) Randnum exchange" UAM + + + DHCAST128 + uams_dhx.so + + "DHCAST128" UAM + + + DHX2 + uams_dhx2.so + + "DHX2" UAM + + + Client Krb v2 + uams_gss.so + + "Client Krb v2" UAM (Kerberos V) + + + + + pssword + length + + guest access + + max. 8 characters + + max. 8 characters + + max. 64 characters + + max. 256 characters + + Kerberos tickets + + + + Client + support + + built-in into all Mac OS versions + + built-in in all Mac OS versions except 10.0. Has to be + activated explicitly in recent Mac OS X versions + + built-in into almost all Mac OS versions + + built-in since AppleShare client 3.8.4, available as a + plug-in for 3.8.3, integrated in Mac OS X' AFP client + + built-in since Mac OS X 10.2 + + built-in since Mac OS X 10.2 + + + + Encryption + + Enables guest access without authentication between + client and server. + + Password will be sent in cleartext over the wire. Just + as bad as it sounds, therefore avoid at all if possible (note: + providing NetBoot services requires the ClearTxt UAM) + + 8-byte random numbers are sent over the wire, + comparable with DES, 56 bits. Vulnerable to offline dictionary + attack. Requires passwords in clear on the server. + + Password will be encrypted with 128 bit SSL, user will + be authenticated against the server but not vice versa. + Therefor weak against man-in-the-middle attacks. + + Password will be encrypted using libgcrypt with CAST + 128 in CBC mode. User will be authenticated against the server + but not vice versa. Therefor weak against man-in-the-middle + attacks. + + Password is not sent over the network. Due to the + service principal detection method, this authentication method + is vulnerable to man-in-the-middle attacks. + + + + Server + support + + uams_guest.so + + uams_cleartxt.so + + uams_randnum.so + + uams_dhx.so + + uams_dhx2.so + + uams_gss.so + + + + Password + storage method + + None + + Either /etc/passwd + (/etc/shadow) or PAM + + Passwords stored in + clear text in a separate text file + + Either /etc/passwd + (/etc/shadow) or PAM + + Either /etc/passwd + (/etc/shadow) or PAM + + At the Kerberos Key + Distribution Center* + + + +
+ + * Have a look at this Kerberos + overview +
+ + + SSH tunneling + + Tunneling and all sort of VPN stuff has nothing to do with AFP + authentication and UAMs in general. But since Apple introduced an + option called "Allow Secure Connections Using SSH" and many people + tend to confuse both things, we'll speak about that here too. + + + Manually tunneling an AFP session + + This works since the first AFP servers that spoke "AFP over + TCP" appeared in networks. One simply tunnels the remote server's + AFP port to a local port different than 548 and connects locally to + this port afterwards. On OS X this can be done by + + ssh -l $USER $SERVER -L 10548:127.0.0.1:548 sleep 3000 + + After establishing the tunnel one will use + "afp://127.0.0.1:10548" in the "Connect to + server" dialog. All AFP traffic including the initial connection + attempts will be sent encrypted over the wire since the local AFP + client will connect to the Mac's local port 10548 which will be + forwarded to the remote server's AFP port (we used the default 548) + over SSH. + + These sorts of tunnels are an ideal solution if you've to + access an AFP server providing weak authentications mechanisms + through the Internet without having the ability to use a "real" VPN. + Note that you can let ssh compress the data by + using its "-C" switch and that the tunnel endpoints can be different + from both AFP client and server (compare with the SSH documentation + for details). + + + + Automatically establishing a tunneled AFP connection + + From Mac OS X 10.2 to 10.4, Apple added an "Allow Secure + Connections Using SSH" checkbox to the "Connect to Server" dialog. + The idea behind: When the server signals that it can be contacted by + SSH then Mac OS X' AFP client tries to establish the tunnel and + automagically sends all AFP traffic through it. + + But it took until the release of Mac OS X 10.3 that this + feature worked the first time... partly. In case, the SSH tunnel + can't be established the AFP client silently fell back to an unencrypted AFP + connection attempt. + + Netatalk's afpd will report that it is capable of handling SSH + tunneled AFP requests, when both "" + and "" options are set in + section (double check with + asip-status.pl + + 1 + after you restarted afpd when you made changes to + the settings). But there are a couple of reasons why you don't want + to use this option at all: + + + + Tunneling TCP over TCP (as SSH does) is not the best idea. + There exist better solutions like VPNs based on the IP + layer. + + + + Since this SSH kludge isn't a normal UAM that integrates + directly into the AFP authentication mechanisms but instead uses + a single flag signalling clients whether they can try to establish a tunnel or not, it + makes life harder to see what's happening when things go + wrong. + + + + You cannot control which machines are logged on by + Netatalk tools like a macusers since all + connection attempts seem to be made from localhost. + + + + On the other side you've to limit access to afpd to + localhost only (TCP wrappers) when you want to ensure that all + AFP sessions are SSH encrypted or... + + + + ...when you're using 10.2 - 10.3.3 then you get the + opposite of what you'd expect: potentially unencrypted AFP + communication (including logon credentials) on the network + without a single notification that establishing the tunnel + failed. Apple fixed that not until Mac OS X 10.3.4. + + + + Encrypting all AFP sessions via SSH can lead to a + significantly higher load on the Netatalk server + + + + +
+ + + ACL Support<indexterm> + <primary>ACLs</primary> + </indexterm> + + ACL support for AFP is implemented for ZFS ACLs on Solaris and + derived platforms and for POSIX 1e ACLs on Linux. + + + Configuration + + For a basic mode of operation there's nothing to configure. + Netatalk reads ACLs on the fly and calculates effective permissions + which are then send to the AFP client via the so called + UARights + UARights + permission bits. On a Mac, the Finder uses these bits + to adjust permission in Finder windows. For example folder whos UNIX + mode would only result in in read-only permissions for a user will not + be displayed with a read-only icon and the user will be able to write + to the folder given the folder has an ACL giving the user write + access. + + By default, the effective permission of the authenticated user + are only mapped to the mentioned UARights + UARights + permission structure, not the UNIX mode. You can adjust + this behaviour with the configuration option map acls. + + However, neither in Finder "Get Info" windows nor in Terminal + will you be able to see the ACLs, that's a result of how ACLs in OS X + are designed. If you want to be able to display ACLs on the client, + things get more involved as you must then setup both client and server + to be part on a authentication domain (directory service, eg LDAP, + OpenDirectory). The reason is, that in OS X ACLs are bound to UUIDs, + not just uid's or gid's. Therefor afpd must be able to map every + filesystem uid and gid to a UUID so that it can return the server side + ACLs which are bound to UNIX uid and gid mapped to OS X UUIDs. + + Netatalk can query a directory server using LDAP queries. Either + the directory server already provides an UUID attribute for user and + groups (Active Directory, Open Directory) or you reuse an unused + attribute (or add a new one) to you directory server (eg + OpenLDAP). + + In detail: + + + + For Solaris/ZFS: ZFS Volumes + + You should configure a ZFS ACL know for any volume you want + to use with Netatalk: + + aclinherit = passthrough +aclmode = passthrough + + For an explanation of what this knob does and how to apply + it, check your hosts ZFS documentation (eg man zfs). + + + + Authentication Domain + + Your server and the clients must be part of a security + association where identity data is coming from a common source. + ACLs in Darwin are based on UUIDs and so is the ACL specification + in AFP 3.2. Therefor your source of identity data has to provide + an attribute for every user and group where a UUID is stored as a + ASCII string. In other words: + + + + you need an Open Directory Server or an LDAP server + where you store UUIDs in some attribute + + + + your clients must be configured to use this + server + + + + your server should be configured to use this server via + nsswitch and PAM + + + + configure Netatalk via the special LDAP options for ACLs in afp.conf so that Netatalk is able + to retrieve the UUID for users and groups via LDAP search + queries + + + + + + + + OS X ACLs + + With Access Control Lists (ACLs) Mac OS X offers a powerful + extension of the traditional UNIX permissions model. An ACL is an + ordered list of Access Control Entries (ACEs) explicitly granting or + denying a set of permissions to a given user or group. + + Unlike UNIX permissions, which are bound to user or group IDs, + ACLs are tied to UUIDs. For this reason accessing an object's ACL + requires server and client to use a common directory service which + translates between UUIDs and user/group IDs. + + ACLs and UNIX permissions interact in a rather simple way. As + ACLs are optional UNIX permissions act as a default mechanism for + access control. Changing an objects's UNIX permissions will leave it's + ACL intact and modifying an ACL will never change the object's UNIX + permissions. While doing access checks, OS X first examines an + object's ACL evaluating ACEs in order until all requested rights have + been granted, a requested right has been explicitly denied by an ACE + or the end of the list has been reached. In case there is no ACL or + the permissions granted by the ACL are not sufficient to fulfill the + request, OS X next evaluates the object's UNIX permissions. Therefore + ACLs always have precedence over UNIX permissions. + + + + ZFS ACLs + + ZFS ACLs closely match OS X ACLs. Both offer mostly identical + fine grained permissions and inheritance settings. + + + + POSIX ACLs + + + Overview + + Compared to OS X or NFSv4 ACLs, Posix ACLs represent a + different, less versatile approach to overcome the limitations of + the traditional UNIX permissions. Implementations are based on the + withdrawn Posix 1003.1e standard. + + The standard defines two types of ACLs. Files and directories + can have access ACLs which are consulted for access checks. + Directories can also have default ACLs irrelevant to access checks. + When a new object is created inside a directory with a default ACL, + the default ACL is applied to the new object as it's access ACL. + Subdirectories inherit default ACLs from their parent. There are no + further mechanisms of inheritance control. + + Architectural differences between Posix ACLs and OS X ACLs + especially involve: + + + + No fine-granular permissions model. Like UNIX + permissions Posix ACLs only differentiate between read, write + and execute permissions. + + + + Entries within an ACL are unordered. + + + + Posix ACLs can only grant rights. There is no way to + explicitly deny rights by an entry. + + + + UNIX permissions are integrated into an ACL as special + entries. + + + + Posix 1003.1e defines 6 different types of ACL entries. The + first three types are used to integrate standard UNIX permissions. + They form a minimal ACL, their presence is mandatory and only one + entry of each type is allowed within an ACL. + + + + ACL_USER_OBJ: the owner's access rights. + + + + ACL_GROUP_OBJ: the owning group's access rights. + + + + ACL_OTHER: everybody's access rights. + + + + The remaining entry types expand the traditional permissions + model: + + + + ACL_USER: grants access rights to a certain user. + + + + ACL_GROUP: grants access rights to a certain + group. + + + + ACL_MASK: limits the maximum access rights which can be + granted by entries of type ACL_GROUP_OBJ, ACL_USER and + ACL_GROUP. As the name suggests, this entry acts as a mask. + Only one ACL_MASK entry is allowed per ACL. If an ACL contains + ACL_USER or ACL_GROUP entries, an ACL_MASK entry must be + present too, otherwise it is optional. + + + + In order to maintain compatibility with applications not aware + of ACLs, Posix 1003.1e changes the semantics of system calls and + utilities which retrieve or manipulate an objects UNIX permissions. + In case an object only has a minimal ACL, the group permissions bits + of the UNIX permissions correspond to the value of the ACL_GROUP_OBJ + entry. + + However, if the ACL also contains an ACL_MASK entry, the + behavior of those system calls and utilities is different. The group + permissions bits of the UNIX permissions correspond to the value of + the ACL_MASK entry, i. e. calling "chmod g-w" will not only revoke + write access for the group, but for all entities which have been + granted write access by ACL_USER or ACL_GROUP entries. + + + + Mapping POSIX ACLs to OS X ACLs + + When a client wants to read an object's ACL, afpd maps it's + Posix ACL onto an equivalent OS X ACL. Writing an object's ACL + requires afpd to map an OS X ACL onto a Posix ACL. Due to + architectural restrictions of Posix ACLs, it is usually impossible + to find an exact mapping so that the result of the mapping process + will be an approximation of the original ACL's semantic. + + + + afpd silently discard entries which deny a set of + permissions because they they can't be represented within the + Posix architecture. + + + + As entries within Posix ACLs are unordered, it is + impossible to preserve order. + + + + Inheritance control is subject to severe limitations as + well: + + Entries with the only_inherit flag set will only + become part of the directory's default ACL. + + + + Entries with at least one of the flags + file_inherit, directory_inherit or limit_inherit set, + will become part of the directory's access and default + ACL, but the restrictions they impose on inheritance + will be ignored. + + + + + + The lack of a fine-granular permission model on the + Posix side will normally result in an increase of granted + permissions. + + + + As OS X clients aren't aware of the Posix 1003.1e specific + relationship between UNIX permissions and ACL_MASK, afpd does not + expose this feature to the client to avoid compatibility issues and + handles *unix permissions and ACLs the same way as Apple's reference + implementation of AFP does. When an object's UNIX permissions are + requested, afpd calculates proper group rights and returns the + result together with the owner's and everybody's access rights to + the caller via "permissions" and "ua_permissions" members of the + FPUnixPrivs structure (see Apple Filing Protocol Reference, page + 181). Changing an object's permissions, afpd always updates + ACL_USER_OBJ, ACL_GROUP_OBJ and ACL_OTHERS. If an ACL_MASK entry is + present too, afpd recalculates it's value so that the new group + rights become effective and existing entries of type ACL_USER or + ACL_GROUP stay intact. + + + + + + Filesystem Change Events<indexterm> + <primary>FCE</primary> + </indexterm> + + Netatalk includes a nifty filesystem change event mechanism where + afpd processes notfiy interested listeners about certain filesystem + event by UDP network datagrams. + + For the format of the UDP packets and for an example C application + that demonstrates how to use these in a listener, take a look at the + Netatalk sourcefile bin/misc/fce.c. + + The currently supported FCE events are + + file modification (fmod) + + + + file deletion (fdel) + + + + directory deletion (ddel) + + + + file creation (fcre) + + + + directory deletion (ddel) + + + + For details on the available simple configuration options take a + look at afp.conf. + +
+ + + Spotlight<indexterm> + <primary>Spotlight</primary> + </indexterm> + + Starting with version 3.1 Netatalk supports Spotlight searching. + Netatalk uses Gnome Tracker as metadata store, + indexer and search engine. + + + Configuration + + You can enable Spotlight and indexing either globally or on a per + volume basis with the option. + + + Once Spotlight is enable for a single volume, all other volumes + for which spotlight is disabled won't be searchable at all. + + + In case the dbus-daemon binary is not installed + at the path /bin/dbus-daemon, you must use the + global option to point to the path, eg for + Solaris with Tracker from OpenCSW: dbus daemon = /opt/csw/bin/dbus-daemon + + + + Limitations and notes + + + + Large filesystems + + Tracker on Linux uses the inotify Kernel filesystem change + event API for tracking filesystem changes. On large filesystems this + may be problematic since the inotify API doesn't offer recursive + directory watches but instead requires that for every subdirectoy + watches must be added individually. + + On Solaris the FEN file event notification system is used. It + is unkown which limitations and ressource consumption this Solaris + subsystem may have. + + We therefor recommend to disable live filesystem monitoring + and let Tracker periodically scan filesystems for changes instead, + see the Tracker configuration options enable-monitors and crawling-interval below. + + + + + + Using Tracker commandline tools on the server + + Netatalk must be running, commands must be executed as root and + some environent variables must be set up (adjust PREFIX to point to + the base directory Netatalk in installed to):$ su +# cat .tracker_profile +PREFIX="/" +export XDG_DATA_HOME="$PREFIX/var/netatalk/" +export XDG_CACHE_HOME="$PREFIX/var/netatalk/" +export DBUS_SESSION_BUS_ADDRESS="unix:path=$PREFIX/var/netatalk/spotlight.ipc" +# . .tracker_profile +# + + + When using Tracker from OpenCSW you must also update your + PATH:# export PATH=/opt/csw/bin:$PATH + + + Starting and stopping Tracker + + + + Querying Tracker status + + + # tracker-control -S + + + + + Stop Tracker + + + # tracker-control -t + + + + + Start Tracker status + + + # tracker-control -s + + + + + + + Reindex directory + + # tracker-control -f PATH + + + + Query Tracker for information about a file or directory + + # tracker-info PATH + + + + Search Tracker + + # tracker-search QUERY + + + + + Advanced Tracker command line configuration + + Tracker stores its configuration via Gnome dconf backend which can + be modified with the command gsettings. + + Gnome dconf settings are per-user settings, so, as Netatalk runs + the Tracker processes as root, the settings are stored in the root user + context and reading or changing these settings must be perfomed as root + and Netatalk must be running (and again the enviroment must be set up + as shown above). + + # gsettings list-recursively | grep Tracker +org.freedesktop.Tracker.Writeback verbosity 'debug' +... + + The following list describes some important Tracker options and + their default settings. + + + + org.freedesktop.Tracker.Miner.Files + index-recursive-directories + + + This option controls which directories Tracker will index. + Don't change this option manually as it is automatically set by + Netatalk reflecting the setting of the + option of Netatalk volumes. + + + + + org.freedesktop.Tracker.Miner.Files + enable-monitors true + + + The value controls whether Tracker watches all configured + paths for modification. Depending on the filesystem modification + backend (FAM on Linux, FEN on Solaris), this feature may not work + as reliable as one might wish, so it may be safer to disable it + and instead rely on periodic crawling of Tracker itself. See aslo + the option . + + + + + org.freedesktop.Tracker.Miner.Files + crawling-interval -1 + + + Interval in days to check the filesystem is up to date in + the database, maximum is 365, default is -1. -2 = crawling is + disabled entirely, -1 = crawling *may* occur on startup (if not + cleanly shutdown), 0 = crawling is forced + + + + + + + Supported metadata attributes + + The following table lists the supported Spotlight metadata + attributes + + + Supported Spotlight metadata attributes + + + + + Description + + Spotlight Key + + + + + + Name + + kMDItemDisplayName, kMDItemFSName + + + + Document content (full text search) + + kMDItemTextContent + + + + File type + + _kMDItemGroupId, kMDItemContentTypeTree + + + + File modification date + + kMDItemFSContentChangeDate, + kMDItemContentModificationDate, + kMDItemAttributeChangeDate + + + + Content Creation date + + kMDItemContentCreationDate + + + + The author, or authors, of the contents of the + file + + kMDItemAuthors, kMDItemCreator + + + + The name of the country where the item was + created + + kMDItemCountry + + + + Duration + + kMDItemDurationSeconds + + + + Number of pages + + kMDItemNumberOfPages + + + + Document title + + kMDItemTitle + + + + The width, in pixels, of the contents. For example, the + image width or the video frame width + + kMDItemPixelWidth + + + + The height, in pixels, of the contents. For example, the + image height or the video frame height + + kMDItemPixelHeight + + + + The color space model used by the document + contents + + kMDItemColorSpace + + + + The number of bits per sample + + kMDItemBitsPerSample + + + + Focal length of the lens, in millimeters + + kMDItemFocalLength + + + + ISO speed + + kMDItemISOSpeed + + + + Orientation of the document. Possible values are 0 + (landscape) and 1 (portrait) + + kMDItemOrientation + + + + Resolution width, in DPI + + kMDItemResolutionWidthDPI + + + + Resolution height, in DPI + + kMDItemResolutionHeightDPI + + + + Exposure time, in seconds + + kMDItemExposureTimeSeconds + + + + The composer of the music contained in the audio + file + + kMDItemComposer + + + + The musical genre of the song or composition + + kMDItemMusicalGenre + + + +
+ +
+ + + References + + + + MDItem + + + + Tracker + + + +
+ + + Starting and stopping Netatalk + + The Netatalk distribution comes with several operating system + specific startup script templates that are tailored according to the + options given to the "configure" script before compiling. Currently, + templates are provided for RedHat (sysv style), RedHat (systemd style), + SUSE (sysv style), SUSE (systemd style), Gentoo, NetBSD, Debian and + Solaris. You can select to install the generated startup script(s) + + Startscript + + startup script + by specifying a system type to "configure". To + automatically install startup scripts give one of the available + option to "configure". + + Since new releases of Linux distributions appear all the time and + the startup procedure for the other systems mentioned above might change + as well, it is probably a good idea to not blindly install a startup + script but to look at it first to see if it will work on your system. If + you use Netatalk as part of a fixed setup, like a Linux distribution, an + RPM or a BSD package, things will probably have been arranged properly for + you. The following therefore applies mostly for people who have compiled + Netatalk themselves. + + The following daemon need to be started by whatever startup script + mechanism is used: + + + + netatalk + netatalk + + + + + Additionally, make sure that the configuration file + afp.conf is in the right place. + +
diff --git a/doc/manual/install.xml b/doc/manual/install.xml new file mode 100644 index 0000000..1974d07 --- /dev/null +++ b/doc/manual/install.xml @@ -0,0 +1,362 @@ + + + + 22.8.2014 + + + Installation + + + If you have previously used an older version of Netatalk, please + read the chapter about upgrading first + !!! + + + + How to obtain Netatalk + + Please have a look at the netatalk page on sourceforge for the most + recent informations on this issue. + + http://sourceforge.net/projects/netatalk/ + + + Binary packages + + Binary packages of Netatalk are included in some Linux and UNIX + distributions. You might want to have a look at the usual locations, + too. + + Ubuntu package: https://launchpad.net/ubuntu + + + Debian package: http://packages.debian.org/ + + + various RPM package: http://rpmfind.net/ + + Fedora/RHEL package: http://koji.fedoraproject.org/koji/search + + + Gentoo package: http://packages.gentoo.org/ + + + openSUSE package: http://software.opensuse.org/ + + + Solaris package: http://www.opencsw.org/ + + FreeBSD ports: http://www.freebsd.org/ports/index.html + + + NetBSD pkgsrc: http://pkgsrc.se/search.php + + + OpenBSD ports:http://openports.se/search.php + + + etc. + RPM + + Red Hat Package Manager package + + Deb + + Debian package + + Ports + + FreeBSD port + + + + + Source packages + + + Tarballs + + Prepacked tarballs in .tar.gz and tar.bz2 format are available + on the netatalk page on sourceforge. + + + + Git + + Downloading the Git repository can be done quickly and + easily: + + + + Make sure you have Git installed. which + git should produce a path to git. + + $ which git +/usr/bin/git + + + + Now get the source: + + $ git clone -b develop git://git.code.sf.net/p/netatalk/code netatalk-code +Initialized empty Git repository in /path/to/new/source/dir/netatalk/.git/ +remote: Counting objects: 2503, done. +... + + + This will create a local directory called + netatalk-code containing a complete and fresh + copy of the whole Netatalk source from the Git repository. + + + + In order to keep your repository copy updated, occasionally + run: + + $ git pull + + + + Now cd to the netatalk directory and run + ./bootstrap. This will create the + configure script required in the next + step. + + $ ./bootstrap + + + + For futher information refer to this wiki + page. + + + + + + Compiling Netatalk + + + Prerequisites + + + Required third party software + + + + Berkeley DB + BDB + Berkeley DB + . + At the time of writing you need at least version 4.6. + + + + Libgcrypt + + Required for OS X 10.7 and later. Libgcrypt is needed for + DHX2. + + Libgcrypt can be downloaded from: + http://directory.fsf.org/wiki/Libgcrypt. + + + + + + Optional third party software + + Netatalk can use the following third party software to enhance + it's functionality. + + + + Tracker for Spotlight + Spotlight + support + + Netatalk uses Tracker as the + metadata backend. Recent Linux distributions will provide the + libtracker-sparql library which is available since Tracker version + 0.7. + + + + mDNSresponderPOSIX or Avahi for Bonjour (aka + Zeroconf) + + Mac OS X 10.2 and later use Bonjour (aka Zeroconf) for + service discovery. + + Avahi must be build with DBUS support ( + --enable-dbus). + + + + TCP wrappers + + Wietse Venema's network logger, also known as TCPD or + LOG_TCP. + + Security options are: access control per host, domain and/or + service; detection of host name spoofing or host address spoofing; + booby traps to implement an early-warning system. + + + + PAM + PAM + + Pluggable Authentication Modules + + + PAM provides a flexible mechanism for authenticating users. + PAM was invented by SUN + SUN + + Sun Microsystems + Microsystems. Linux-PAM is a suite of shared + libraries that enable the local system administrator to choose how + applications authenticate users. + + + + iconv + + iconv provides conversion routines for many character + encodings. Netatalk uses it to provide charsets it does not have + built in conversions for, like ISO-8859-1. On glibc systems, + Netatalk can use the glibc provided iconv implementation. + Otherwise you can use the GNU libiconv implementation. + + + + + + + Compiling<indexterm> + <primary>Compile</primary> + + <secondary>Compiling Netatalk from Source</secondary> + </indexterm> Netatalk + + + Configuring the build + + To build the binaries, first run the program + ./configure in the source directory. This should + automatically configure Netatalk for your operating system. If you + have unusual needs, then you may wish to run + + $ ./configure --help + + to see what special options you can enable. + + The most used configure options are: + + + + =redhat-sysv|redhat-systemd|suse-sysv|suse-systemd|gentoo|netbsd|debian-sysv|debian-systemd|solaris|systemd + + This option helps netatalk to determine where to install the + start scripts. + + + + =/path/to/bdb/installation/ + + In case you installed Berkeley DB in a non-standard + location, you will have to give the install + location to netatalk, using this switch. + + + + Now run configure with any options you need + + $ ./configure [arguments] + + Configure will end up in an overview showing the settings the + Netatalk Makefiles have been created with. + + + + Spotlight<indexterm> + <primary>Spotlight</primary> + </indexterm> + + Netatalk uses Gnome Tracker as the + metadata backend. The minimum required version is 0.7 as that's the + first version to support SPARQL. + + If not already installed, install the packages + tracker and tracker-devel, + on Solaris install OpenCSW and then install + the Tracker package from the OpenCSW unstable repository. + + The tracker packages are found via pkg-config, you may have to + pass the version suffix as you may have a newer version installed then + the default 0.12, eg + + $ pkg-config --list-all | grep tracker +tracker-extract-0.16 tracker-extract - Tracker : A library to develop metadata extractors for 3rd party file types. +tracker-sparql-0.16 tracker-sparql - Tracker : A library to perform SPARQL queries and updates in the Tracker Store +tracker-miner-0.16 tracker-miner - A library to develop tracker data miners + + So: + + $ ./configure --with-tracker-pkgconfig-version=0.16 ... + + If you're using Solaris and Tracker from OpenCSW, then you need + to set the PKG_CONFIG_PATH environment variable, add the + --with-tracker-prefix configure option and add + LDFLAGS="-R/opt/csw/lib" + + PKG_CONFIG_PATH=/opt/csw/lib/pkgconfig LDFLAGS="-R/opt/csw/lib" ./configure --with-tracker-prefix=/opt/csw --with-tracker-pkgconfig-version=0.16 ... + + Check the configure output whether the Tracker libs were + found: + + checking for TRACKER... yes +checking for TRACKER_MINER... yes +... +Configure summary: +... + AFP: + Spotlight: yes +... + + + + Compile and install + + Next, running + + $ make + + should produce the Netatalk binaries (this step can take several + minutes to complete). + + When the process finished you can use + + $ make install + + to install the binaries and documentation (must be done as + "root" when using default locations). + + + + diff --git a/doc/manual/intro.xml b/doc/manual/intro.xml new file mode 100644 index 0000000..0b70a9a --- /dev/null +++ b/doc/manual/intro.xml @@ -0,0 +1,15 @@ + + + Introduction to Netatalk + + Netatalk is an OpenSource software package, that can be used to turn + a *NIX machine into an extremely high-performance and + reliable file server for Macintosh computers. + + Using Netatalk's AFP 3.3 compliant file-server leads to significantly + higher transmission speeds compared with Macs accessing a server via + SaMBa/NFS while providing clients with the best possible user experience + (full support for Macintosh metadata, flawlessly supporting mixed + environments of classic Mac OS and OS X clients) + + diff --git a/doc/manual/manual.xml.in b/doc/manual/manual.xml.in new file mode 100644 index 0000000..7c067ef --- /dev/null +++ b/doc/manual/manual.xml.in @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + Netatalk 3.1 Manual + + + 07-01-2013 + @NETATALK_VERSION@ + + + + + Legal Notice + +This documentation is distributed under the GNU General Public License (GPL) version 2. +A copy of the license is included in this documentation, as well as within the Netatalk source +distribution. An on-line copy can be found at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + + + + + + + + + + &Intro; + + + &Install; + + + &Configuration; + + + &Upgrade; + + + + Manual Pages + + This is a collection of the man pages delivered with Netatalk. + + &ad.1; + + &afp.conf.5; + + &afp_signature.conf.5; + + &afp_voluuid.conf.5; + + &afpd.8; + + &afpldaptest.1; + + &afppasswd.1; + + &afpstats.1; + + &apple_dump.1; + + &asip-status.pl.1; + + &cnid_dbd.8; + + &cnid_metad.8; + + &dbd.1; + + &extmap.conf.5; + + &macusers.1; + + &megatron.1; + + &netatalk.8; + + &netatalk-config.1; + + &uniconv.1; + + + + + + + Index + diff --git a/doc/manual/netatalk.html b/doc/manual/netatalk.html new file mode 100644 index 0000000..0c7e337 --- /dev/null +++ b/doc/manual/netatalk.html @@ -0,0 +1,14 @@ + + + diff --git a/doc/manual/upgrade.xml b/doc/manual/upgrade.xml new file mode 100644 index 0000000..2d85e74 --- /dev/null +++ b/doc/manual/upgrade.xml @@ -0,0 +1,1540 @@ + + + + 9.6.2013 + + + Frank + + Lahm + + + 6 Sep, 2013 + + + Upgrading from Netatalk 2 + + + Overview + + There are two major changes in Netatalk: + + New configuration file afp.conf, obsoleting all + previous configuration files + + + + New AppleDouble backend "" + which stores Mac metadata and resource forks in extended attributes + of the filesystem + + + + + New configuration + + + + ini style syntax (like Samba’s smb.conf) + + + + one to rule them all: configure AFP settings and volumes in + one file + + + + obsoletes afpd.conf, + netatalk.conf, + AppleVolumes.default and + afp_ldap.conf + + + most option names have changed, read the full manpage afp.conf for details + + + + + New AppleDouble backend + + New AppleDouble backend "" which + stores Mac metadata and resource forks in extended attributes of the + filesystem. + + default backend (!) + + + + requires a filesystem with Extended Attributes, fallback is + "" + + + + converts filesystems from "" + to "" on the fly when accessed + (can be disabled) + + + + dbd can be + used to do conversion in one shot + + + + Implementation details: + + stores Mac Metadata (eg FinderInfo, AFP Flags, Comment, + CNID) in an Extended Attributed named + “org.netatalk.Metadata” + + + + stores Mac ResourceFork either in + + an Extended Attribute named + “org.netatalk.ResourceFork” + on Solaris w. ZFS, or in + + + + an extra AppleDouble file named “._file” for a file + named “file” + + + + + + the format of the ._ file is exactly as the Mac’s CIFS + client expects it when accessing the same filesystem via a CIFS + server (Samba), thus you can have parallel access from Macs to the + same dataset via AFP and CIFS without the risk of loosing data + (resources or metadata). Accessing the same dataset with CIFS + from Windows clients will still break the coupling of + “file” and “._file” + on non ZFS filesystems (see above), so for this we still + need an enhanced Samba VFS module (in the works). + + + + As these days the only applications making use of Resource Forks + are Adobe Photoshop (image preview) and Postscript Type 1 fonts, even on + eg Linux you’ll get rid of 99% of any extra Netatalk AppleDouble files + (and folders). + + + + Other major changes + + + + New service controller daemon netatalk which is responsible for + starting and restarting the AFP and CNID daemons. All bundled + start scripts have been updated, make sure to update yours! + + + + The CNID databases are now stored under + /var/netatalk/CNID/ + by default. You can use configure --localstatedir=PATH at + compile time to change the location. + + + + Netatalk 2.x volume options “usedots” and “upriv” now + enabled by default + + + + Removed SLP and AFP proxy support + + + + Removed type/creator extension mapping + support + + + + + + + Upgrading + + + + Stop Netatalk 2.x + + + + Install Netatalk 3 + + + + Manually recreate configuration in + and + + + + Update your Netatalk start script (SMF, systemd, whatever...) + to only start netatalk + + + + Move afp_voluuid.conf and + afp_signature.conf to the localstate directory (default + /var/netatalk/), you can use afpd -v + in order to find the correct path + + + + Start Netatalk 3 + + + + + + Table with old and new configuration file names + + old and new configuration file names + + + + + + + Old File Name + New File Name + Description + + + + + - + etc/afp.conf + new ini-style format + + + - + etc/extmap.conf + starting with netatalk 3.0.2 + + + etc/netatalk/afp_signature.conf + var/netatalk/afp_signature.conf + moved to $localstatedir + + + etc/netatalk/afp_voluuid.conf + var/netatalk/afp_voluuid.conf + moved to $localstatedir + + + etc/netatalk/netatalk.conf + (/etc/default/netatalk) + - + obsolete + + + etc/netatalk/afpd.conf + - + obsolete + + + etc/netatalk/afp_ldap.conf + - + obsolete + + + etc/netatalk/AppleVolumes.default + - + obsolete + + + etc/netatalk/AppleVolumes.system + - + obsolete + + + ~/.AppleVolumes + - + obsolete + + + +
+
+ + + Table with old and new option names + + from netatalk.conf (/etc/default/netatalk) to afp.conf + + + + + + + + + + Old netatalk.conf + New afp.conf + Old Default Value + New Default Value + Section + Description + + + + + ATALK_NAME + hostname + - + - + (G) + use gethostname() by default + + + ATALK_UNIX_CHARSET + unix charset + LOCALE + UTF8 + (G) + - + + + ATALK_MAC_CHARSET + mac charset + MAC_ROMAN + MAC_ROMAN + (G)/(V) + - + + + CNID_METAD_RUN + - + yes + - + - + controlled by netatalk(8) + + + AFPD_RUN + - + yes + - + - + controlled by netatalk(8) + + + AFPD_MAX_CLIENTS + max connections + 20 + 200 + (G) + - + + + AFPD_UAMLIST + uam list + -U uams_dhx.so,uams_dhx2.so + uams_dhx.so uams_dhx2.so + (G) + - + + + AFPD_GUEST + guest account + nobody + nobody + (G) + - + + + CNID_CONFIG + log level + -l log_note + cnid:note + (G) + - + + + CNID_CONFIG + log file + - + - + (G) + - + + + ATALKD_RUN + - + no + - + - + AppleTalk is obsoleted + + + PAPD_RUN + - + no + - + - + AppleTalk is obsoleted + + + TIMELORD_RUN + - + no + - + - + AppleTalk is obsoleted + + + A2BOOT_RUN + - + no + - + - + AppleTalk is obsoleted + + + ATALK_BGROUND + - + no + - + - + AppleTalk is obsoleted + + + ATALK_ZONE + - + no + - + - + AppleTalk is obsoleted + + + +
+ from afpd.conf to afp.conf + + + + + + + + + + Old afpd.conf + New afp.conf + Old Default Value + New Default Value + Section + Description + + + + + 1st field ("-" or "server name") + hostname + - + - + (G) + use gethostname() by default + + + -uamlist + uam list + -U uams_dhx.so,uams_dhx2.so + uams_dhx.so uams_dhx2.so + (G) + - + + + -nozeroconf + zeroconf + - + yes (if supported) + (G) + - + + + -advertise_ssh + advertise ssh + - + no + (G) + - + + + -[no]savepassword + save password + -savepassword + yes + (G) + - + + + -[no]setpassword + set password + -nosetpassword + no + (G) + - + + + -client_polling + client polling + - + no + (G) + - + + + -hostname + hostname + - + - + (G) + use gethostname() by default + + + -loginmesg + login message + - + - + (G)/(V) + - + + + -guestname + guest account + nobody + nobody + (G) + - + + + -passwdfile + passwd file + afppasswd + afppasswd + (G) + - + + + -passwdminlen + passwd minlen + - + - + (G) + - + + + -tickleval + tickleval + 30 + 30 + (G) + - + + + -timeout + timeout + 4 + 4 + (G) + - + + + -sleep + sleep time + 10 + 10 + (G) + - + + + -dsireadbuf + dsireadbuf + 12 + 12 + (G) + - + + + -server_quantum + server quantum + 303840 + 1048576 + (G) + - + + + -volnamelen + volnamelen + 80 + 80 + (G) + - + + + -setuplog + log level + default log_note + default:note + (G) + - + + + -setuplog + log file + - + - + (G) + - + + + -admingroup + admingroup + - + - + (G) + - + + + -k5service + k5 service + - + - + (G) + - + + + -k5realm + k5 realm + - + - + (G) + - + + + -k5keytab + k5 keytab + - + - + (G) + - + + + -uampath + uam path + etc/netatalk/uams/ + lib/netatalk/ + (G) + moved to $libdir + + + -ipaddr + afp listen + - + - + (G) + - + + + -cnidserver + cnid server + localhost:4700 + localhost:4700 + (G)/(V) + - + + + -port + port + 548 + 548 + (G) + - + + + -signature + signature + auto + - + (G) + - + + + -fqdn + fqdn + - + - + (G) + - + + + -unixcodepage + unix charset + LOCALE + UTF8 + (G) + - + + + -maccodepage + mac charset + MAC_ROMAN + MAC_ROMAN + (G)/(V) + - + + + -closevol + close vol + - + no + (G) + - + + + -ntdomain + nt domain + - + - + (G) + - + + + -ntseparator + nt separator + - + - + (G) + - + + + -dircachesize + dircachesize + 8192 + 8192 + (G) + - + + + -tcpsndbuf + tcpsndbuf + - + - + (G) + OS default + + + -tcprcvbuf + tcprcvbuf + - + - + (G) + OS default + + + -fcelistener + fce listener + - + - + (G) + - + + + -fcecoalesce + fce coalesce + - + - + (G) + - + + + -fceevents + fce events + - + - + (G) + - + + + -fceholdfmod + fce holdfmod + 60 + 60 + (G) + - + + + -mimicmodel + mimic model + - + - + (G) + - + + + -adminauthuser + admin auth user + - + - + (G) + - + + + -noacl2maccess + map acls + - + rights + (G) + - + + + -[no]tcp + - + -tcp + - + - + always TCP only + + + -[no]ddp + - + -noddp + - + - + AppleTalk is obsoleted + + + -[no]transall + - + -tcp -noddp + - + - + always TCP only + + + -nodebug + - + - + - + - + obsolete + + + -[no]slp + - + -noslp + - + - + SLP support is obsoleted + + + -[no]uservolfirst + - + -nouservolfirst + - + - + uservol is obsoleted + + + -[no]uservol + - + -uservol + - + - + uservol is obsoleted + + + -proxy + - + - + - + - + AppleTalk is obsoleted + + + -defaultvol + - + AppleVolumes.default + - + - + afp.conf only + + + -systemvol + - + AppleVolumes.system + - + - + afp.conf only + + + -loginmaxfail + - + - + - + - + not supported from the biginning + + + -unsetuplog + - + - + - + - + obsolete + + + -authprintdir + - + - + - + - + AppleTalk is obsoleted + + + -ddpaddr + - + - + - + - + AppleTalk is obsoleted + + + -[no]icon + - + -noicon + + - + obsolete + + + -keepsessions + - + - + - + - + obsolete. Use kill -HUP. + + + +
+ from afp_ldap.conf to afp.conf + + + + + + + + + + Old afp_ldap.conf + New afp.conf + Old Default Value + New Defalut Value + Section + Description + + + + + ldap_server + ldap server + - + - + (G) + - + + + ldap_auth_method + ldap auth method + - + - + (G) + - + + + ldap_auth_dn + ldap auth dn + - + - + (G) + - + + + ldap_auth_pw + ldap auth pw + - + - + (G) + - + + + ldap_userbase + ldap userbase + - + - + (G) + - + + + ldap_userscope + ldap userscope + - + - + (G) + - + + + ldap_groupbase + ldap groupbase + - + - + (G) + - + + + ldap_groupscope + ldap groupscope + - + - + (G) + - + + + ldap_uuid_attr + ldap uuid attr + - + - + (G) + - + + + ldap_uuid_string + ldap uuid string + - + - + (G) + - + + + ldap_name_attr + ldap name attr + - + - + (G) + - + + + ldap_group_attr + ldap group attr + - + - + (G) + - + + + +
+ from AppleVolumes.* to afp.conf + + + + + + + + + + Old AppleVolumes.* + New afp.conf + Old Default Value + New Defalut Value + Section + Description + + + + + (leading-dot lines) + - + - + - + - + move to extmap.conf + + + :DEFAULT: + - + options:upriv,usedots + - + - + use "vol preset =" + + + 1st field ("~") + - + - + - + - + use [Homes] section + + + 1st field ("/path") + path + - + - + (V) + - + + + 2nd field + - + - + - + - + use section name + + + allow: + valid users + - + - + (V) + - + + + deny: + invalid users + - + - + (V) + - + + + rwlist: + rwlist + - + - + (V) + - + + + rolist: + rolist + - + - + (V) + - + + + volcharset: + vol charset + UTF8 + (same as unix charset) + (G)/(V) + - + + + maccharset: + mac charset + MAC_ROMAN + MAC_ROMAN + (G)/(V) + - + + + veto: + veto files + - + - + (V) + - + + + cnidscheme: + cnid scheme + dbd + dbd + (V) + - + + + casefold: + casefold + - + - + (V) + - + + + adouble: + appledouble + v2 + ea + (V) + v1, osx and sfm are obsoleted + + + cnidserver: + cnid server + localhost:4700 + localhost:4700 + (G)/(V) + - + + + dbpath: + vol dbpath + (volume directory) + var/netatalk/CNID/ + (G) + moved to $localstatedir + + + umask: + umask + 0000 + 0000 + (V) + - + + + dperm: + directory perm + 0000 + 0000 + (V) + - + + + fperm: + file perm + 0000 + 0000 + (V) + - + + + password: + password + - + - + (V) + - + + + root_preexec: + root preexec + - + - + (V) + - + + + preexec: + preexec + - + - + (V) + - + + + root_postexec: + root postexec + - + - + (V) + - + + + postexec: + postexec + - + - + (V) + - + + + allowed_hosts: + hosts allow + - + - + (V) + - + + + denied_hosts: + hosts deny + - + - + (V) + - + + + ea: + ea + auto + auto + (V) + - + + + volsizelimit: + vol size limit + - + - + (V) + - + + + perm: + - + - + - + - + Use "directory perm" and "file perm" + + + forceuid: + - + - + - + - + obsolete + + + forcegid: + - + - + - + - + obsolete + + + options:ro + read only + - + no + (V) + - + + + options:invisibledots + invisible dots + - + no + (V) + - + + + options:nostat + stat vol + - + yes + (V) + - + + + options:preexec_close + preexec close + - + no + (V) + - + + + options:root_preexec_close + root preexec close + - + no + (V) + - + + + options:upriv + unix priv + - + yes + (V) + - + + + options:nodev + cnid dev + - + yes + (V) + - + + + options:illegalseq + illegal seq + - + no + (V) + - + + + options:tm + time machine + - + no + (V) + - + + + options:searchdb + search db + - + no + (V) + - + + + options:nonetids + network ids + - + yes + (V) + - + + + options:noacls + acls + - + yes + (V) + - + + + options:followsymlinks + follow symlinks + - + no + (V) + - + + + options:nohex + - + - + - + - + auto-convert from ":2f" to ":" + + + options:usedots + - + - + - + - + auto-convert from ":2e" to "." + + + options:nofileid + - + - + - + - + obsolete + + + options:prodos + - + - + - + - + obsolete + + + options:mswindows + - + - + - + - + obsolete + + + options:crlf + - + - + - + - + obsolete + + + options:noadouble + - + - + - + - + obsolete + + + options:limitsize + - + - + - + - + obsolete + + + options:dropbox + - + - + - + - + obsolete + + + options:dropkludge + - + - + - + - + obsolete + + + options:nocnidcache + - + - + - + - + obsolete + + + options:caseinsensitive + - + - + - + - + obsolete + + + +
+
+ + + To Do + + + + test ad utils with + + + +
diff --git a/etc/Makefile.am b/etc/Makefile.am new file mode 100644 index 0000000..959b864 --- /dev/null +++ b/etc/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for etc/ + +SUBDIRS = spotlight afpd cnid_dbd netatalk uams diff --git a/etc/Makefile.in b/etc/Makefile.in new file mode 100644 index 0000000..e37f681 --- /dev/null +++ b/etc/Makefile.in @@ -0,0 +1,706 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for etc/ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = etc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = spotlight afpd cnid_dbd netatalk uams +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign etc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign etc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# 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/etc/afpd/Makefile.am b/etc/afpd/Makefile.am new file mode 100644 index 0000000..55b9d2e --- /dev/null +++ b/etc/afpd/Makefile.am @@ -0,0 +1,101 @@ +# Makefile.am for etc/afpd/ + +pkgconfdir = @PKGCONFDIR@ +BUILT_SOURCES = +EXTRA_DIST = afpstats-service.xml afpstats_service_glue.h +CLEANFILES = +DISTCLEANFILES = + +sbin_PROGRAMS = afpd + +afpd_SOURCES = \ + afp_config.c \ + afp_dsi.c \ + afp_options.c \ + afp_util.c \ + afprun.c \ + afs.c \ + appl.c \ + auth.c \ + catsearch.c \ + desktop.c \ + dircache.c \ + directory.c \ + enumerate.c \ + extattrs.c \ + fce_api.c \ + fce_util.c \ + file.c \ + filedir.c \ + fork.c \ + hash.c \ + main.c \ + mangle.c \ + messages.c \ + nfsquota.c \ + ofork.c \ + quota.c \ + spotlight_marshalling.c \ + status.c \ + switch.c \ + uam.c \ + uid.c \ + unix.c \ + volume.c + + +afpd_LDADD = \ + $(top_builddir)/libatalk/libatalk.la \ + @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@ @KRB5_LIBS@ @MYSQL_LIBS@ + +afpd_LDFLAGS = -export-dynamic + +afpd_CFLAGS = \ + @GSSAPI_CFLAGS@ @KRB5_CFLAGS@ @PTHREAD_CFLAGS@\ + -DAPPLCNAME \ + -DSERVERTEXT=\"$(SERVERTEXT)/\" \ + -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \ + -D_PATH_AFPDUAMPATH=\"$(UAMS_PATH)/\" \ + -D_PATH_CONFDIR=\"$(pkgconfdir)/\" \ + -D_PATH_STATEDIR='"$(localstatedir)/netatalk/"' + +if HAVE_TRACKER +afpd_SOURCES += spotlight.c +afpd_LDADD += $(top_builddir)/etc/spotlight/libspotlight.la +afpd_CFLAGS += @TRACKER_CFLAGS@ +endif + +if HAVE_ACLS +afpd_SOURCES += acls.c +endif + +if HAVE_DBUS_GLIB +BUILT_SOURCES += afpstats_service_glue.h +DISTCLEANFILES += afpstats_service_glue.h + +afpstats_service_glue.h: afpstats-service.xml + $(LIBTOOL) --mode=execute \ + dbus-binding-tool \ + --prefix=afpstats_obj \ + --mode=glib-server \ + --output=afpstats_service_glue.h \ + $(top_srcdir)/etc/afpd/afpstats-service.xml + +afpd_SOURCES += afpstats.c afpstats_obj.c +afpd_CFLAGS += $(DBUS_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_GTHREAD_CFLAGS) -DDBUS_COMPILATION +afpd_LDFLAGS += $(DBUS_LIBS) $(DBUS_GLIB_LIBS) $(DBUS_GTHREAD_LIBS) -ldbus-glib-1 +endif + +if WITH_DTRACE +DTRACE_OBJ = afpd-afp_dsi.o afpd-fork.o afpd-appl.o afpd-catsearch.o afpd-directory.o afpd-enumerate.o afpd-file.o afpd-filedir.o +afp_dtrace.o: $(top_srcdir)/include/atalk/afp_dtrace.d $(DTRACE_OBJ) + if test -f afp_dtrace.o ; then rm -f afp_dtrace.o ; fi + $(LIBTOOL) --mode=execute dtrace -G -s $(top_srcdir)/include/atalk/afp_dtrace.d -o afp_dtrace.o $(DTRACE_OBJ) +afpd_LDADD += afp_dtrace.o @DTRACE_LIBS@ +CLEANFILES += afp_dtrace.o +endif + +noinst_HEADERS = auth.h afp_config.h desktop.h directory.h fce_api_internal.h file.h \ + filedir.h fork.h icon.h mangle.h misc.h status.h switch.h \ + uam_auth.h uid.h unix.h volume.h hash.h acls.h acl_mappings.h extattrs.h \ + dircache.h afpstats_obj.h afpstats.h diff --git a/etc/afpd/Makefile.in b/etc/afpd/Makefile.in new file mode 100644 index 0000000..45b494b --- /dev/null +++ b/etc/afpd/Makefile.in @@ -0,0 +1,1345 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for etc/afpd/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +sbin_PROGRAMS = afpd$(EXEEXT) +@HAVE_TRACKER_TRUE@am__append_1 = spotlight.c +@HAVE_TRACKER_TRUE@am__append_2 = $(top_builddir)/etc/spotlight/libspotlight.la +@HAVE_TRACKER_TRUE@am__append_3 = @TRACKER_CFLAGS@ +@HAVE_ACLS_TRUE@am__append_4 = acls.c +@HAVE_DBUS_GLIB_TRUE@am__append_5 = afpstats_service_glue.h +@HAVE_DBUS_GLIB_TRUE@am__append_6 = afpstats_service_glue.h +@HAVE_DBUS_GLIB_TRUE@am__append_7 = afpstats.c afpstats_obj.c +@HAVE_DBUS_GLIB_TRUE@am__append_8 = $(DBUS_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_GTHREAD_CFLAGS) -DDBUS_COMPILATION +@HAVE_DBUS_GLIB_TRUE@am__append_9 = $(DBUS_LIBS) $(DBUS_GLIB_LIBS) $(DBUS_GTHREAD_LIBS) -ldbus-glib-1 +@WITH_DTRACE_TRUE@am__append_10 = afp_dtrace.o @DTRACE_LIBS@ +@WITH_DTRACE_TRUE@am__append_11 = afp_dtrace.o +subdir = etc/afpd +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(sbin_PROGRAMS) +am__afpd_SOURCES_DIST = afp_config.c afp_dsi.c afp_options.c \ + afp_util.c afprun.c afs.c appl.c auth.c catsearch.c desktop.c \ + dircache.c directory.c enumerate.c extattrs.c fce_api.c \ + fce_util.c file.c filedir.c fork.c hash.c main.c mangle.c \ + messages.c nfsquota.c ofork.c quota.c spotlight_marshalling.c \ + status.c switch.c uam.c uid.c unix.c volume.c spotlight.c \ + acls.c afpstats.c afpstats_obj.c +@HAVE_TRACKER_TRUE@am__objects_1 = afpd-spotlight.$(OBJEXT) +@HAVE_ACLS_TRUE@am__objects_2 = afpd-acls.$(OBJEXT) +@HAVE_DBUS_GLIB_TRUE@am__objects_3 = afpd-afpstats.$(OBJEXT) \ +@HAVE_DBUS_GLIB_TRUE@ afpd-afpstats_obj.$(OBJEXT) +am_afpd_OBJECTS = afpd-afp_config.$(OBJEXT) afpd-afp_dsi.$(OBJEXT) \ + afpd-afp_options.$(OBJEXT) afpd-afp_util.$(OBJEXT) \ + afpd-afprun.$(OBJEXT) afpd-afs.$(OBJEXT) afpd-appl.$(OBJEXT) \ + afpd-auth.$(OBJEXT) afpd-catsearch.$(OBJEXT) \ + afpd-desktop.$(OBJEXT) afpd-dircache.$(OBJEXT) \ + afpd-directory.$(OBJEXT) afpd-enumerate.$(OBJEXT) \ + afpd-extattrs.$(OBJEXT) afpd-fce_api.$(OBJEXT) \ + afpd-fce_util.$(OBJEXT) afpd-file.$(OBJEXT) \ + afpd-filedir.$(OBJEXT) afpd-fork.$(OBJEXT) afpd-hash.$(OBJEXT) \ + afpd-main.$(OBJEXT) afpd-mangle.$(OBJEXT) \ + afpd-messages.$(OBJEXT) afpd-nfsquota.$(OBJEXT) \ + afpd-ofork.$(OBJEXT) afpd-quota.$(OBJEXT) \ + afpd-spotlight_marshalling.$(OBJEXT) afpd-status.$(OBJEXT) \ + afpd-switch.$(OBJEXT) afpd-uam.$(OBJEXT) afpd-uid.$(OBJEXT) \ + afpd-unix.$(OBJEXT) afpd-volume.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) +afpd_OBJECTS = $(am_afpd_OBJECTS) +@WITH_DTRACE_TRUE@am__DEPENDENCIES_1 = afp_dtrace.o +afpd_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la \ + $(am__append_2) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +afpd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(afpd_CFLAGS) $(CFLAGS) \ + $(afpd_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(afpd_SOURCES) +DIST_SOURCES = $(am__afpd_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgconfdir = @PKGCONFDIR@ +BUILT_SOURCES = $(am__append_5) +EXTRA_DIST = afpstats-service.xml afpstats_service_glue.h +CLEANFILES = $(am__append_11) +DISTCLEANFILES = $(am__append_6) +afpd_SOURCES = afp_config.c afp_dsi.c afp_options.c afp_util.c \ + afprun.c afs.c appl.c auth.c catsearch.c desktop.c dircache.c \ + directory.c enumerate.c extattrs.c fce_api.c fce_util.c file.c \ + filedir.c fork.c hash.c main.c mangle.c messages.c nfsquota.c \ + ofork.c quota.c spotlight_marshalling.c status.c switch.c \ + uam.c uid.c unix.c volume.c $(am__append_1) $(am__append_4) \ + $(am__append_7) +afpd_LDADD = $(top_builddir)/libatalk/libatalk.la @LIBGCRYPT_LIBS@ \ + @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @PTHREAD_LIBS@ \ + @GSSAPI_LIBS@ @KRB5_LIBS@ @MYSQL_LIBS@ $(am__append_2) \ + $(am__append_10) +afpd_LDFLAGS = -export-dynamic $(am__append_9) +afpd_CFLAGS = @GSSAPI_CFLAGS@ @KRB5_CFLAGS@ @PTHREAD_CFLAGS@ \ + -DAPPLCNAME -DSERVERTEXT=\"$(SERVERTEXT)/\" \ + -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \ + -D_PATH_AFPDUAMPATH=\"$(UAMS_PATH)/\" \ + -D_PATH_CONFDIR=\"$(pkgconfdir)/\" \ + -D_PATH_STATEDIR='"$(localstatedir)/netatalk/"' \ + $(am__append_3) $(am__append_8) +@WITH_DTRACE_TRUE@DTRACE_OBJ = afpd-afp_dsi.o afpd-fork.o afpd-appl.o afpd-catsearch.o afpd-directory.o afpd-enumerate.o afpd-file.o afpd-filedir.o +noinst_HEADERS = auth.h afp_config.h desktop.h directory.h fce_api_internal.h file.h \ + filedir.h fork.h icon.h mangle.h misc.h status.h switch.h \ + uam_auth.h uid.h unix.h volume.h hash.h acls.h acl_mappings.h extattrs.h \ + dircache.h afpstats_obj.h afpstats.h + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign etc/afpd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign etc/afpd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +afpd$(EXEEXT): $(afpd_OBJECTS) $(afpd_DEPENDENCIES) $(EXTRA_afpd_DEPENDENCIES) + @rm -f afpd$(EXEEXT) + $(AM_V_CCLD)$(afpd_LINK) $(afpd_OBJECTS) $(afpd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-acls.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afp_config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afp_dsi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afp_options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afp_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afprun.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afpstats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afpstats_obj.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-afs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-appl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-catsearch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-desktop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-dircache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-directory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-enumerate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-extattrs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-fce_api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-fce_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-filedir.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-fork.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-hash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-mangle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-messages.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-nfsquota.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-ofork.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-quota.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-spotlight.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-spotlight_marshalling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-status.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-switch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-uam.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-uid.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-unix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afpd-volume.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +afpd-afp_config.o: afp_config.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_config.o -MD -MP -MF $(DEPDIR)/afpd-afp_config.Tpo -c -o afpd-afp_config.o `test -f 'afp_config.c' || echo '$(srcdir)/'`afp_config.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_config.Tpo $(DEPDIR)/afpd-afp_config.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_config.c' object='afpd-afp_config.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_config.o `test -f 'afp_config.c' || echo '$(srcdir)/'`afp_config.c + +afpd-afp_config.obj: afp_config.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_config.obj -MD -MP -MF $(DEPDIR)/afpd-afp_config.Tpo -c -o afpd-afp_config.obj `if test -f 'afp_config.c'; then $(CYGPATH_W) 'afp_config.c'; else $(CYGPATH_W) '$(srcdir)/afp_config.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_config.Tpo $(DEPDIR)/afpd-afp_config.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_config.c' object='afpd-afp_config.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_config.obj `if test -f 'afp_config.c'; then $(CYGPATH_W) 'afp_config.c'; else $(CYGPATH_W) '$(srcdir)/afp_config.c'; fi` + +afpd-afp_dsi.o: afp_dsi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_dsi.o -MD -MP -MF $(DEPDIR)/afpd-afp_dsi.Tpo -c -o afpd-afp_dsi.o `test -f 'afp_dsi.c' || echo '$(srcdir)/'`afp_dsi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_dsi.Tpo $(DEPDIR)/afpd-afp_dsi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_dsi.c' object='afpd-afp_dsi.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_dsi.o `test -f 'afp_dsi.c' || echo '$(srcdir)/'`afp_dsi.c + +afpd-afp_dsi.obj: afp_dsi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_dsi.obj -MD -MP -MF $(DEPDIR)/afpd-afp_dsi.Tpo -c -o afpd-afp_dsi.obj `if test -f 'afp_dsi.c'; then $(CYGPATH_W) 'afp_dsi.c'; else $(CYGPATH_W) '$(srcdir)/afp_dsi.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_dsi.Tpo $(DEPDIR)/afpd-afp_dsi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_dsi.c' object='afpd-afp_dsi.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_dsi.obj `if test -f 'afp_dsi.c'; then $(CYGPATH_W) 'afp_dsi.c'; else $(CYGPATH_W) '$(srcdir)/afp_dsi.c'; fi` + +afpd-afp_options.o: afp_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_options.o -MD -MP -MF $(DEPDIR)/afpd-afp_options.Tpo -c -o afpd-afp_options.o `test -f 'afp_options.c' || echo '$(srcdir)/'`afp_options.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_options.Tpo $(DEPDIR)/afpd-afp_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_options.c' object='afpd-afp_options.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_options.o `test -f 'afp_options.c' || echo '$(srcdir)/'`afp_options.c + +afpd-afp_options.obj: afp_options.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_options.obj -MD -MP -MF $(DEPDIR)/afpd-afp_options.Tpo -c -o afpd-afp_options.obj `if test -f 'afp_options.c'; then $(CYGPATH_W) 'afp_options.c'; else $(CYGPATH_W) '$(srcdir)/afp_options.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_options.Tpo $(DEPDIR)/afpd-afp_options.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_options.c' object='afpd-afp_options.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_options.obj `if test -f 'afp_options.c'; then $(CYGPATH_W) 'afp_options.c'; else $(CYGPATH_W) '$(srcdir)/afp_options.c'; fi` + +afpd-afp_util.o: afp_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_util.o -MD -MP -MF $(DEPDIR)/afpd-afp_util.Tpo -c -o afpd-afp_util.o `test -f 'afp_util.c' || echo '$(srcdir)/'`afp_util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_util.Tpo $(DEPDIR)/afpd-afp_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_util.c' object='afpd-afp_util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_util.o `test -f 'afp_util.c' || echo '$(srcdir)/'`afp_util.c + +afpd-afp_util.obj: afp_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afp_util.obj -MD -MP -MF $(DEPDIR)/afpd-afp_util.Tpo -c -o afpd-afp_util.obj `if test -f 'afp_util.c'; then $(CYGPATH_W) 'afp_util.c'; else $(CYGPATH_W) '$(srcdir)/afp_util.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afp_util.Tpo $(DEPDIR)/afpd-afp_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_util.c' object='afpd-afp_util.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afp_util.obj `if test -f 'afp_util.c'; then $(CYGPATH_W) 'afp_util.c'; else $(CYGPATH_W) '$(srcdir)/afp_util.c'; fi` + +afpd-afprun.o: afprun.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afprun.o -MD -MP -MF $(DEPDIR)/afpd-afprun.Tpo -c -o afpd-afprun.o `test -f 'afprun.c' || echo '$(srcdir)/'`afprun.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afprun.Tpo $(DEPDIR)/afpd-afprun.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afprun.c' object='afpd-afprun.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afprun.o `test -f 'afprun.c' || echo '$(srcdir)/'`afprun.c + +afpd-afprun.obj: afprun.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afprun.obj -MD -MP -MF $(DEPDIR)/afpd-afprun.Tpo -c -o afpd-afprun.obj `if test -f 'afprun.c'; then $(CYGPATH_W) 'afprun.c'; else $(CYGPATH_W) '$(srcdir)/afprun.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afprun.Tpo $(DEPDIR)/afpd-afprun.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afprun.c' object='afpd-afprun.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afprun.obj `if test -f 'afprun.c'; then $(CYGPATH_W) 'afprun.c'; else $(CYGPATH_W) '$(srcdir)/afprun.c'; fi` + +afpd-afs.o: afs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afs.o -MD -MP -MF $(DEPDIR)/afpd-afs.Tpo -c -o afpd-afs.o `test -f 'afs.c' || echo '$(srcdir)/'`afs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afs.Tpo $(DEPDIR)/afpd-afs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afs.c' object='afpd-afs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afs.o `test -f 'afs.c' || echo '$(srcdir)/'`afs.c + +afpd-afs.obj: afs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afs.obj -MD -MP -MF $(DEPDIR)/afpd-afs.Tpo -c -o afpd-afs.obj `if test -f 'afs.c'; then $(CYGPATH_W) 'afs.c'; else $(CYGPATH_W) '$(srcdir)/afs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afs.Tpo $(DEPDIR)/afpd-afs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afs.c' object='afpd-afs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afs.obj `if test -f 'afs.c'; then $(CYGPATH_W) 'afs.c'; else $(CYGPATH_W) '$(srcdir)/afs.c'; fi` + +afpd-appl.o: appl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-appl.o -MD -MP -MF $(DEPDIR)/afpd-appl.Tpo -c -o afpd-appl.o `test -f 'appl.c' || echo '$(srcdir)/'`appl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-appl.Tpo $(DEPDIR)/afpd-appl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='appl.c' object='afpd-appl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-appl.o `test -f 'appl.c' || echo '$(srcdir)/'`appl.c + +afpd-appl.obj: appl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-appl.obj -MD -MP -MF $(DEPDIR)/afpd-appl.Tpo -c -o afpd-appl.obj `if test -f 'appl.c'; then $(CYGPATH_W) 'appl.c'; else $(CYGPATH_W) '$(srcdir)/appl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-appl.Tpo $(DEPDIR)/afpd-appl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='appl.c' object='afpd-appl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-appl.obj `if test -f 'appl.c'; then $(CYGPATH_W) 'appl.c'; else $(CYGPATH_W) '$(srcdir)/appl.c'; fi` + +afpd-auth.o: auth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-auth.o -MD -MP -MF $(DEPDIR)/afpd-auth.Tpo -c -o afpd-auth.o `test -f 'auth.c' || echo '$(srcdir)/'`auth.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-auth.Tpo $(DEPDIR)/afpd-auth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='auth.c' object='afpd-auth.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-auth.o `test -f 'auth.c' || echo '$(srcdir)/'`auth.c + +afpd-auth.obj: auth.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-auth.obj -MD -MP -MF $(DEPDIR)/afpd-auth.Tpo -c -o afpd-auth.obj `if test -f 'auth.c'; then $(CYGPATH_W) 'auth.c'; else $(CYGPATH_W) '$(srcdir)/auth.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-auth.Tpo $(DEPDIR)/afpd-auth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='auth.c' object='afpd-auth.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-auth.obj `if test -f 'auth.c'; then $(CYGPATH_W) 'auth.c'; else $(CYGPATH_W) '$(srcdir)/auth.c'; fi` + +afpd-catsearch.o: catsearch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-catsearch.o -MD -MP -MF $(DEPDIR)/afpd-catsearch.Tpo -c -o afpd-catsearch.o `test -f 'catsearch.c' || echo '$(srcdir)/'`catsearch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-catsearch.Tpo $(DEPDIR)/afpd-catsearch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='catsearch.c' object='afpd-catsearch.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-catsearch.o `test -f 'catsearch.c' || echo '$(srcdir)/'`catsearch.c + +afpd-catsearch.obj: catsearch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-catsearch.obj -MD -MP -MF $(DEPDIR)/afpd-catsearch.Tpo -c -o afpd-catsearch.obj `if test -f 'catsearch.c'; then $(CYGPATH_W) 'catsearch.c'; else $(CYGPATH_W) '$(srcdir)/catsearch.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-catsearch.Tpo $(DEPDIR)/afpd-catsearch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='catsearch.c' object='afpd-catsearch.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-catsearch.obj `if test -f 'catsearch.c'; then $(CYGPATH_W) 'catsearch.c'; else $(CYGPATH_W) '$(srcdir)/catsearch.c'; fi` + +afpd-desktop.o: desktop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-desktop.o -MD -MP -MF $(DEPDIR)/afpd-desktop.Tpo -c -o afpd-desktop.o `test -f 'desktop.c' || echo '$(srcdir)/'`desktop.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-desktop.Tpo $(DEPDIR)/afpd-desktop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='desktop.c' object='afpd-desktop.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-desktop.o `test -f 'desktop.c' || echo '$(srcdir)/'`desktop.c + +afpd-desktop.obj: desktop.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-desktop.obj -MD -MP -MF $(DEPDIR)/afpd-desktop.Tpo -c -o afpd-desktop.obj `if test -f 'desktop.c'; then $(CYGPATH_W) 'desktop.c'; else $(CYGPATH_W) '$(srcdir)/desktop.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-desktop.Tpo $(DEPDIR)/afpd-desktop.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='desktop.c' object='afpd-desktop.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-desktop.obj `if test -f 'desktop.c'; then $(CYGPATH_W) 'desktop.c'; else $(CYGPATH_W) '$(srcdir)/desktop.c'; fi` + +afpd-dircache.o: dircache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-dircache.o -MD -MP -MF $(DEPDIR)/afpd-dircache.Tpo -c -o afpd-dircache.o `test -f 'dircache.c' || echo '$(srcdir)/'`dircache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-dircache.Tpo $(DEPDIR)/afpd-dircache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dircache.c' object='afpd-dircache.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-dircache.o `test -f 'dircache.c' || echo '$(srcdir)/'`dircache.c + +afpd-dircache.obj: dircache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-dircache.obj -MD -MP -MF $(DEPDIR)/afpd-dircache.Tpo -c -o afpd-dircache.obj `if test -f 'dircache.c'; then $(CYGPATH_W) 'dircache.c'; else $(CYGPATH_W) '$(srcdir)/dircache.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-dircache.Tpo $(DEPDIR)/afpd-dircache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dircache.c' object='afpd-dircache.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-dircache.obj `if test -f 'dircache.c'; then $(CYGPATH_W) 'dircache.c'; else $(CYGPATH_W) '$(srcdir)/dircache.c'; fi` + +afpd-directory.o: directory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-directory.o -MD -MP -MF $(DEPDIR)/afpd-directory.Tpo -c -o afpd-directory.o `test -f 'directory.c' || echo '$(srcdir)/'`directory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-directory.Tpo $(DEPDIR)/afpd-directory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='directory.c' object='afpd-directory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-directory.o `test -f 'directory.c' || echo '$(srcdir)/'`directory.c + +afpd-directory.obj: directory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-directory.obj -MD -MP -MF $(DEPDIR)/afpd-directory.Tpo -c -o afpd-directory.obj `if test -f 'directory.c'; then $(CYGPATH_W) 'directory.c'; else $(CYGPATH_W) '$(srcdir)/directory.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-directory.Tpo $(DEPDIR)/afpd-directory.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='directory.c' object='afpd-directory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-directory.obj `if test -f 'directory.c'; then $(CYGPATH_W) 'directory.c'; else $(CYGPATH_W) '$(srcdir)/directory.c'; fi` + +afpd-enumerate.o: enumerate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-enumerate.o -MD -MP -MF $(DEPDIR)/afpd-enumerate.Tpo -c -o afpd-enumerate.o `test -f 'enumerate.c' || echo '$(srcdir)/'`enumerate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-enumerate.Tpo $(DEPDIR)/afpd-enumerate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='enumerate.c' object='afpd-enumerate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-enumerate.o `test -f 'enumerate.c' || echo '$(srcdir)/'`enumerate.c + +afpd-enumerate.obj: enumerate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-enumerate.obj -MD -MP -MF $(DEPDIR)/afpd-enumerate.Tpo -c -o afpd-enumerate.obj `if test -f 'enumerate.c'; then $(CYGPATH_W) 'enumerate.c'; else $(CYGPATH_W) '$(srcdir)/enumerate.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-enumerate.Tpo $(DEPDIR)/afpd-enumerate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='enumerate.c' object='afpd-enumerate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-enumerate.obj `if test -f 'enumerate.c'; then $(CYGPATH_W) 'enumerate.c'; else $(CYGPATH_W) '$(srcdir)/enumerate.c'; fi` + +afpd-extattrs.o: extattrs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-extattrs.o -MD -MP -MF $(DEPDIR)/afpd-extattrs.Tpo -c -o afpd-extattrs.o `test -f 'extattrs.c' || echo '$(srcdir)/'`extattrs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-extattrs.Tpo $(DEPDIR)/afpd-extattrs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='extattrs.c' object='afpd-extattrs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-extattrs.o `test -f 'extattrs.c' || echo '$(srcdir)/'`extattrs.c + +afpd-extattrs.obj: extattrs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-extattrs.obj -MD -MP -MF $(DEPDIR)/afpd-extattrs.Tpo -c -o afpd-extattrs.obj `if test -f 'extattrs.c'; then $(CYGPATH_W) 'extattrs.c'; else $(CYGPATH_W) '$(srcdir)/extattrs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-extattrs.Tpo $(DEPDIR)/afpd-extattrs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='extattrs.c' object='afpd-extattrs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-extattrs.obj `if test -f 'extattrs.c'; then $(CYGPATH_W) 'extattrs.c'; else $(CYGPATH_W) '$(srcdir)/extattrs.c'; fi` + +afpd-fce_api.o: fce_api.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-fce_api.o -MD -MP -MF $(DEPDIR)/afpd-fce_api.Tpo -c -o afpd-fce_api.o `test -f 'fce_api.c' || echo '$(srcdir)/'`fce_api.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-fce_api.Tpo $(DEPDIR)/afpd-fce_api.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fce_api.c' object='afpd-fce_api.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-fce_api.o `test -f 'fce_api.c' || echo '$(srcdir)/'`fce_api.c + +afpd-fce_api.obj: fce_api.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-fce_api.obj -MD -MP -MF $(DEPDIR)/afpd-fce_api.Tpo -c -o afpd-fce_api.obj `if test -f 'fce_api.c'; then $(CYGPATH_W) 'fce_api.c'; else $(CYGPATH_W) '$(srcdir)/fce_api.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-fce_api.Tpo $(DEPDIR)/afpd-fce_api.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fce_api.c' object='afpd-fce_api.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-fce_api.obj `if test -f 'fce_api.c'; then $(CYGPATH_W) 'fce_api.c'; else $(CYGPATH_W) '$(srcdir)/fce_api.c'; fi` + +afpd-fce_util.o: fce_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-fce_util.o -MD -MP -MF $(DEPDIR)/afpd-fce_util.Tpo -c -o afpd-fce_util.o `test -f 'fce_util.c' || echo '$(srcdir)/'`fce_util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-fce_util.Tpo $(DEPDIR)/afpd-fce_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fce_util.c' object='afpd-fce_util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-fce_util.o `test -f 'fce_util.c' || echo '$(srcdir)/'`fce_util.c + +afpd-fce_util.obj: fce_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-fce_util.obj -MD -MP -MF $(DEPDIR)/afpd-fce_util.Tpo -c -o afpd-fce_util.obj `if test -f 'fce_util.c'; then $(CYGPATH_W) 'fce_util.c'; else $(CYGPATH_W) '$(srcdir)/fce_util.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-fce_util.Tpo $(DEPDIR)/afpd-fce_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fce_util.c' object='afpd-fce_util.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-fce_util.obj `if test -f 'fce_util.c'; then $(CYGPATH_W) 'fce_util.c'; else $(CYGPATH_W) '$(srcdir)/fce_util.c'; fi` + +afpd-file.o: file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-file.o -MD -MP -MF $(DEPDIR)/afpd-file.Tpo -c -o afpd-file.o `test -f 'file.c' || echo '$(srcdir)/'`file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-file.Tpo $(DEPDIR)/afpd-file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='file.c' object='afpd-file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-file.o `test -f 'file.c' || echo '$(srcdir)/'`file.c + +afpd-file.obj: file.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-file.obj -MD -MP -MF $(DEPDIR)/afpd-file.Tpo -c -o afpd-file.obj `if test -f 'file.c'; then $(CYGPATH_W) 'file.c'; else $(CYGPATH_W) '$(srcdir)/file.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-file.Tpo $(DEPDIR)/afpd-file.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='file.c' object='afpd-file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-file.obj `if test -f 'file.c'; then $(CYGPATH_W) 'file.c'; else $(CYGPATH_W) '$(srcdir)/file.c'; fi` + +afpd-filedir.o: filedir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-filedir.o -MD -MP -MF $(DEPDIR)/afpd-filedir.Tpo -c -o afpd-filedir.o `test -f 'filedir.c' || echo '$(srcdir)/'`filedir.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-filedir.Tpo $(DEPDIR)/afpd-filedir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filedir.c' object='afpd-filedir.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-filedir.o `test -f 'filedir.c' || echo '$(srcdir)/'`filedir.c + +afpd-filedir.obj: filedir.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-filedir.obj -MD -MP -MF $(DEPDIR)/afpd-filedir.Tpo -c -o afpd-filedir.obj `if test -f 'filedir.c'; then $(CYGPATH_W) 'filedir.c'; else $(CYGPATH_W) '$(srcdir)/filedir.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-filedir.Tpo $(DEPDIR)/afpd-filedir.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filedir.c' object='afpd-filedir.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-filedir.obj `if test -f 'filedir.c'; then $(CYGPATH_W) 'filedir.c'; else $(CYGPATH_W) '$(srcdir)/filedir.c'; fi` + +afpd-fork.o: fork.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-fork.o -MD -MP -MF $(DEPDIR)/afpd-fork.Tpo -c -o afpd-fork.o `test -f 'fork.c' || echo '$(srcdir)/'`fork.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-fork.Tpo $(DEPDIR)/afpd-fork.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fork.c' object='afpd-fork.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-fork.o `test -f 'fork.c' || echo '$(srcdir)/'`fork.c + +afpd-fork.obj: fork.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-fork.obj -MD -MP -MF $(DEPDIR)/afpd-fork.Tpo -c -o afpd-fork.obj `if test -f 'fork.c'; then $(CYGPATH_W) 'fork.c'; else $(CYGPATH_W) '$(srcdir)/fork.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-fork.Tpo $(DEPDIR)/afpd-fork.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fork.c' object='afpd-fork.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-fork.obj `if test -f 'fork.c'; then $(CYGPATH_W) 'fork.c'; else $(CYGPATH_W) '$(srcdir)/fork.c'; fi` + +afpd-hash.o: hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-hash.o -MD -MP -MF $(DEPDIR)/afpd-hash.Tpo -c -o afpd-hash.o `test -f 'hash.c' || echo '$(srcdir)/'`hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-hash.Tpo $(DEPDIR)/afpd-hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash.c' object='afpd-hash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-hash.o `test -f 'hash.c' || echo '$(srcdir)/'`hash.c + +afpd-hash.obj: hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-hash.obj -MD -MP -MF $(DEPDIR)/afpd-hash.Tpo -c -o afpd-hash.obj `if test -f 'hash.c'; then $(CYGPATH_W) 'hash.c'; else $(CYGPATH_W) '$(srcdir)/hash.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-hash.Tpo $(DEPDIR)/afpd-hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash.c' object='afpd-hash.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-hash.obj `if test -f 'hash.c'; then $(CYGPATH_W) 'hash.c'; else $(CYGPATH_W) '$(srcdir)/hash.c'; fi` + +afpd-main.o: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-main.o -MD -MP -MF $(DEPDIR)/afpd-main.Tpo -c -o afpd-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-main.Tpo $(DEPDIR)/afpd-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='afpd-main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c + +afpd-main.obj: main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-main.obj -MD -MP -MF $(DEPDIR)/afpd-main.Tpo -c -o afpd-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-main.Tpo $(DEPDIR)/afpd-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='afpd-main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` + +afpd-mangle.o: mangle.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-mangle.o -MD -MP -MF $(DEPDIR)/afpd-mangle.Tpo -c -o afpd-mangle.o `test -f 'mangle.c' || echo '$(srcdir)/'`mangle.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-mangle.Tpo $(DEPDIR)/afpd-mangle.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mangle.c' object='afpd-mangle.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-mangle.o `test -f 'mangle.c' || echo '$(srcdir)/'`mangle.c + +afpd-mangle.obj: mangle.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-mangle.obj -MD -MP -MF $(DEPDIR)/afpd-mangle.Tpo -c -o afpd-mangle.obj `if test -f 'mangle.c'; then $(CYGPATH_W) 'mangle.c'; else $(CYGPATH_W) '$(srcdir)/mangle.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-mangle.Tpo $(DEPDIR)/afpd-mangle.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mangle.c' object='afpd-mangle.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-mangle.obj `if test -f 'mangle.c'; then $(CYGPATH_W) 'mangle.c'; else $(CYGPATH_W) '$(srcdir)/mangle.c'; fi` + +afpd-messages.o: messages.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-messages.o -MD -MP -MF $(DEPDIR)/afpd-messages.Tpo -c -o afpd-messages.o `test -f 'messages.c' || echo '$(srcdir)/'`messages.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-messages.Tpo $(DEPDIR)/afpd-messages.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='messages.c' object='afpd-messages.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-messages.o `test -f 'messages.c' || echo '$(srcdir)/'`messages.c + +afpd-messages.obj: messages.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-messages.obj -MD -MP -MF $(DEPDIR)/afpd-messages.Tpo -c -o afpd-messages.obj `if test -f 'messages.c'; then $(CYGPATH_W) 'messages.c'; else $(CYGPATH_W) '$(srcdir)/messages.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-messages.Tpo $(DEPDIR)/afpd-messages.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='messages.c' object='afpd-messages.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-messages.obj `if test -f 'messages.c'; then $(CYGPATH_W) 'messages.c'; else $(CYGPATH_W) '$(srcdir)/messages.c'; fi` + +afpd-nfsquota.o: nfsquota.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-nfsquota.o -MD -MP -MF $(DEPDIR)/afpd-nfsquota.Tpo -c -o afpd-nfsquota.o `test -f 'nfsquota.c' || echo '$(srcdir)/'`nfsquota.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-nfsquota.Tpo $(DEPDIR)/afpd-nfsquota.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nfsquota.c' object='afpd-nfsquota.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-nfsquota.o `test -f 'nfsquota.c' || echo '$(srcdir)/'`nfsquota.c + +afpd-nfsquota.obj: nfsquota.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-nfsquota.obj -MD -MP -MF $(DEPDIR)/afpd-nfsquota.Tpo -c -o afpd-nfsquota.obj `if test -f 'nfsquota.c'; then $(CYGPATH_W) 'nfsquota.c'; else $(CYGPATH_W) '$(srcdir)/nfsquota.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-nfsquota.Tpo $(DEPDIR)/afpd-nfsquota.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nfsquota.c' object='afpd-nfsquota.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-nfsquota.obj `if test -f 'nfsquota.c'; then $(CYGPATH_W) 'nfsquota.c'; else $(CYGPATH_W) '$(srcdir)/nfsquota.c'; fi` + +afpd-ofork.o: ofork.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-ofork.o -MD -MP -MF $(DEPDIR)/afpd-ofork.Tpo -c -o afpd-ofork.o `test -f 'ofork.c' || echo '$(srcdir)/'`ofork.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-ofork.Tpo $(DEPDIR)/afpd-ofork.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofork.c' object='afpd-ofork.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-ofork.o `test -f 'ofork.c' || echo '$(srcdir)/'`ofork.c + +afpd-ofork.obj: ofork.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-ofork.obj -MD -MP -MF $(DEPDIR)/afpd-ofork.Tpo -c -o afpd-ofork.obj `if test -f 'ofork.c'; then $(CYGPATH_W) 'ofork.c'; else $(CYGPATH_W) '$(srcdir)/ofork.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-ofork.Tpo $(DEPDIR)/afpd-ofork.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofork.c' object='afpd-ofork.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-ofork.obj `if test -f 'ofork.c'; then $(CYGPATH_W) 'ofork.c'; else $(CYGPATH_W) '$(srcdir)/ofork.c'; fi` + +afpd-quota.o: quota.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-quota.o -MD -MP -MF $(DEPDIR)/afpd-quota.Tpo -c -o afpd-quota.o `test -f 'quota.c' || echo '$(srcdir)/'`quota.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-quota.Tpo $(DEPDIR)/afpd-quota.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='quota.c' object='afpd-quota.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-quota.o `test -f 'quota.c' || echo '$(srcdir)/'`quota.c + +afpd-quota.obj: quota.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-quota.obj -MD -MP -MF $(DEPDIR)/afpd-quota.Tpo -c -o afpd-quota.obj `if test -f 'quota.c'; then $(CYGPATH_W) 'quota.c'; else $(CYGPATH_W) '$(srcdir)/quota.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-quota.Tpo $(DEPDIR)/afpd-quota.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='quota.c' object='afpd-quota.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-quota.obj `if test -f 'quota.c'; then $(CYGPATH_W) 'quota.c'; else $(CYGPATH_W) '$(srcdir)/quota.c'; fi` + +afpd-spotlight_marshalling.o: spotlight_marshalling.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-spotlight_marshalling.o -MD -MP -MF $(DEPDIR)/afpd-spotlight_marshalling.Tpo -c -o afpd-spotlight_marshalling.o `test -f 'spotlight_marshalling.c' || echo '$(srcdir)/'`spotlight_marshalling.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-spotlight_marshalling.Tpo $(DEPDIR)/afpd-spotlight_marshalling.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spotlight_marshalling.c' object='afpd-spotlight_marshalling.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-spotlight_marshalling.o `test -f 'spotlight_marshalling.c' || echo '$(srcdir)/'`spotlight_marshalling.c + +afpd-spotlight_marshalling.obj: spotlight_marshalling.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-spotlight_marshalling.obj -MD -MP -MF $(DEPDIR)/afpd-spotlight_marshalling.Tpo -c -o afpd-spotlight_marshalling.obj `if test -f 'spotlight_marshalling.c'; then $(CYGPATH_W) 'spotlight_marshalling.c'; else $(CYGPATH_W) '$(srcdir)/spotlight_marshalling.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-spotlight_marshalling.Tpo $(DEPDIR)/afpd-spotlight_marshalling.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spotlight_marshalling.c' object='afpd-spotlight_marshalling.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-spotlight_marshalling.obj `if test -f 'spotlight_marshalling.c'; then $(CYGPATH_W) 'spotlight_marshalling.c'; else $(CYGPATH_W) '$(srcdir)/spotlight_marshalling.c'; fi` + +afpd-status.o: status.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-status.o -MD -MP -MF $(DEPDIR)/afpd-status.Tpo -c -o afpd-status.o `test -f 'status.c' || echo '$(srcdir)/'`status.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-status.Tpo $(DEPDIR)/afpd-status.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='status.c' object='afpd-status.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-status.o `test -f 'status.c' || echo '$(srcdir)/'`status.c + +afpd-status.obj: status.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-status.obj -MD -MP -MF $(DEPDIR)/afpd-status.Tpo -c -o afpd-status.obj `if test -f 'status.c'; then $(CYGPATH_W) 'status.c'; else $(CYGPATH_W) '$(srcdir)/status.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-status.Tpo $(DEPDIR)/afpd-status.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='status.c' object='afpd-status.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-status.obj `if test -f 'status.c'; then $(CYGPATH_W) 'status.c'; else $(CYGPATH_W) '$(srcdir)/status.c'; fi` + +afpd-switch.o: switch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-switch.o -MD -MP -MF $(DEPDIR)/afpd-switch.Tpo -c -o afpd-switch.o `test -f 'switch.c' || echo '$(srcdir)/'`switch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-switch.Tpo $(DEPDIR)/afpd-switch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='switch.c' object='afpd-switch.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-switch.o `test -f 'switch.c' || echo '$(srcdir)/'`switch.c + +afpd-switch.obj: switch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-switch.obj -MD -MP -MF $(DEPDIR)/afpd-switch.Tpo -c -o afpd-switch.obj `if test -f 'switch.c'; then $(CYGPATH_W) 'switch.c'; else $(CYGPATH_W) '$(srcdir)/switch.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-switch.Tpo $(DEPDIR)/afpd-switch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='switch.c' object='afpd-switch.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-switch.obj `if test -f 'switch.c'; then $(CYGPATH_W) 'switch.c'; else $(CYGPATH_W) '$(srcdir)/switch.c'; fi` + +afpd-uam.o: uam.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-uam.o -MD -MP -MF $(DEPDIR)/afpd-uam.Tpo -c -o afpd-uam.o `test -f 'uam.c' || echo '$(srcdir)/'`uam.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-uam.Tpo $(DEPDIR)/afpd-uam.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uam.c' object='afpd-uam.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-uam.o `test -f 'uam.c' || echo '$(srcdir)/'`uam.c + +afpd-uam.obj: uam.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-uam.obj -MD -MP -MF $(DEPDIR)/afpd-uam.Tpo -c -o afpd-uam.obj `if test -f 'uam.c'; then $(CYGPATH_W) 'uam.c'; else $(CYGPATH_W) '$(srcdir)/uam.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-uam.Tpo $(DEPDIR)/afpd-uam.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uam.c' object='afpd-uam.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-uam.obj `if test -f 'uam.c'; then $(CYGPATH_W) 'uam.c'; else $(CYGPATH_W) '$(srcdir)/uam.c'; fi` + +afpd-uid.o: uid.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-uid.o -MD -MP -MF $(DEPDIR)/afpd-uid.Tpo -c -o afpd-uid.o `test -f 'uid.c' || echo '$(srcdir)/'`uid.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-uid.Tpo $(DEPDIR)/afpd-uid.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uid.c' object='afpd-uid.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-uid.o `test -f 'uid.c' || echo '$(srcdir)/'`uid.c + +afpd-uid.obj: uid.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-uid.obj -MD -MP -MF $(DEPDIR)/afpd-uid.Tpo -c -o afpd-uid.obj `if test -f 'uid.c'; then $(CYGPATH_W) 'uid.c'; else $(CYGPATH_W) '$(srcdir)/uid.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-uid.Tpo $(DEPDIR)/afpd-uid.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uid.c' object='afpd-uid.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-uid.obj `if test -f 'uid.c'; then $(CYGPATH_W) 'uid.c'; else $(CYGPATH_W) '$(srcdir)/uid.c'; fi` + +afpd-unix.o: unix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-unix.o -MD -MP -MF $(DEPDIR)/afpd-unix.Tpo -c -o afpd-unix.o `test -f 'unix.c' || echo '$(srcdir)/'`unix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-unix.Tpo $(DEPDIR)/afpd-unix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unix.c' object='afpd-unix.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-unix.o `test -f 'unix.c' || echo '$(srcdir)/'`unix.c + +afpd-unix.obj: unix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-unix.obj -MD -MP -MF $(DEPDIR)/afpd-unix.Tpo -c -o afpd-unix.obj `if test -f 'unix.c'; then $(CYGPATH_W) 'unix.c'; else $(CYGPATH_W) '$(srcdir)/unix.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-unix.Tpo $(DEPDIR)/afpd-unix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unix.c' object='afpd-unix.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-unix.obj `if test -f 'unix.c'; then $(CYGPATH_W) 'unix.c'; else $(CYGPATH_W) '$(srcdir)/unix.c'; fi` + +afpd-volume.o: volume.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-volume.o -MD -MP -MF $(DEPDIR)/afpd-volume.Tpo -c -o afpd-volume.o `test -f 'volume.c' || echo '$(srcdir)/'`volume.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-volume.Tpo $(DEPDIR)/afpd-volume.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='volume.c' object='afpd-volume.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-volume.o `test -f 'volume.c' || echo '$(srcdir)/'`volume.c + +afpd-volume.obj: volume.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-volume.obj -MD -MP -MF $(DEPDIR)/afpd-volume.Tpo -c -o afpd-volume.obj `if test -f 'volume.c'; then $(CYGPATH_W) 'volume.c'; else $(CYGPATH_W) '$(srcdir)/volume.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-volume.Tpo $(DEPDIR)/afpd-volume.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='volume.c' object='afpd-volume.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-volume.obj `if test -f 'volume.c'; then $(CYGPATH_W) 'volume.c'; else $(CYGPATH_W) '$(srcdir)/volume.c'; fi` + +afpd-spotlight.o: spotlight.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-spotlight.o -MD -MP -MF $(DEPDIR)/afpd-spotlight.Tpo -c -o afpd-spotlight.o `test -f 'spotlight.c' || echo '$(srcdir)/'`spotlight.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-spotlight.Tpo $(DEPDIR)/afpd-spotlight.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spotlight.c' object='afpd-spotlight.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-spotlight.o `test -f 'spotlight.c' || echo '$(srcdir)/'`spotlight.c + +afpd-spotlight.obj: spotlight.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-spotlight.obj -MD -MP -MF $(DEPDIR)/afpd-spotlight.Tpo -c -o afpd-spotlight.obj `if test -f 'spotlight.c'; then $(CYGPATH_W) 'spotlight.c'; else $(CYGPATH_W) '$(srcdir)/spotlight.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-spotlight.Tpo $(DEPDIR)/afpd-spotlight.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spotlight.c' object='afpd-spotlight.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-spotlight.obj `if test -f 'spotlight.c'; then $(CYGPATH_W) 'spotlight.c'; else $(CYGPATH_W) '$(srcdir)/spotlight.c'; fi` + +afpd-acls.o: acls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-acls.o -MD -MP -MF $(DEPDIR)/afpd-acls.Tpo -c -o afpd-acls.o `test -f 'acls.c' || echo '$(srcdir)/'`acls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-acls.Tpo $(DEPDIR)/afpd-acls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acls.c' object='afpd-acls.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-acls.o `test -f 'acls.c' || echo '$(srcdir)/'`acls.c + +afpd-acls.obj: acls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-acls.obj -MD -MP -MF $(DEPDIR)/afpd-acls.Tpo -c -o afpd-acls.obj `if test -f 'acls.c'; then $(CYGPATH_W) 'acls.c'; else $(CYGPATH_W) '$(srcdir)/acls.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-acls.Tpo $(DEPDIR)/afpd-acls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acls.c' object='afpd-acls.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-acls.obj `if test -f 'acls.c'; then $(CYGPATH_W) 'acls.c'; else $(CYGPATH_W) '$(srcdir)/acls.c'; fi` + +afpd-afpstats.o: afpstats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afpstats.o -MD -MP -MF $(DEPDIR)/afpd-afpstats.Tpo -c -o afpd-afpstats.o `test -f 'afpstats.c' || echo '$(srcdir)/'`afpstats.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afpstats.Tpo $(DEPDIR)/afpd-afpstats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afpstats.c' object='afpd-afpstats.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afpstats.o `test -f 'afpstats.c' || echo '$(srcdir)/'`afpstats.c + +afpd-afpstats.obj: afpstats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afpstats.obj -MD -MP -MF $(DEPDIR)/afpd-afpstats.Tpo -c -o afpd-afpstats.obj `if test -f 'afpstats.c'; then $(CYGPATH_W) 'afpstats.c'; else $(CYGPATH_W) '$(srcdir)/afpstats.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afpstats.Tpo $(DEPDIR)/afpd-afpstats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afpstats.c' object='afpd-afpstats.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afpstats.obj `if test -f 'afpstats.c'; then $(CYGPATH_W) 'afpstats.c'; else $(CYGPATH_W) '$(srcdir)/afpstats.c'; fi` + +afpd-afpstats_obj.o: afpstats_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afpstats_obj.o -MD -MP -MF $(DEPDIR)/afpd-afpstats_obj.Tpo -c -o afpd-afpstats_obj.o `test -f 'afpstats_obj.c' || echo '$(srcdir)/'`afpstats_obj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afpstats_obj.Tpo $(DEPDIR)/afpd-afpstats_obj.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afpstats_obj.c' object='afpd-afpstats_obj.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afpstats_obj.o `test -f 'afpstats_obj.c' || echo '$(srcdir)/'`afpstats_obj.c + +afpd-afpstats_obj.obj: afpstats_obj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -MT afpd-afpstats_obj.obj -MD -MP -MF $(DEPDIR)/afpd-afpstats_obj.Tpo -c -o afpd-afpstats_obj.obj `if test -f 'afpstats_obj.c'; then $(CYGPATH_W) 'afpstats_obj.c'; else $(CYGPATH_W) '$(srcdir)/afpstats_obj.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/afpd-afpstats_obj.Tpo $(DEPDIR)/afpd-afpstats_obj.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afpstats_obj.c' object='afpd-afpstats_obj.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(afpd_CFLAGS) $(CFLAGS) -c -o afpd-afpstats_obj.obj `if test -f 'afpstats_obj.c'; then $(CYGPATH_W) 'afpstats_obj.c'; else $(CYGPATH_W) '$(srcdir)/afpstats_obj.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-sbinPROGRAMS + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-sbinPROGRAMS + + +@HAVE_DBUS_GLIB_TRUE@afpstats_service_glue.h: afpstats-service.xml +@HAVE_DBUS_GLIB_TRUE@ $(LIBTOOL) --mode=execute \ +@HAVE_DBUS_GLIB_TRUE@ dbus-binding-tool \ +@HAVE_DBUS_GLIB_TRUE@ --prefix=afpstats_obj \ +@HAVE_DBUS_GLIB_TRUE@ --mode=glib-server \ +@HAVE_DBUS_GLIB_TRUE@ --output=afpstats_service_glue.h \ +@HAVE_DBUS_GLIB_TRUE@ $(top_srcdir)/etc/afpd/afpstats-service.xml +@WITH_DTRACE_TRUE@afp_dtrace.o: $(top_srcdir)/include/atalk/afp_dtrace.d $(DTRACE_OBJ) +@WITH_DTRACE_TRUE@ if test -f afp_dtrace.o ; then rm -f afp_dtrace.o ; fi +@WITH_DTRACE_TRUE@ $(LIBTOOL) --mode=execute dtrace -G -s $(top_srcdir)/include/atalk/afp_dtrace.d -o afp_dtrace.o $(DTRACE_OBJ) + +# 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/etc/afpd/acl_mappings.h b/etc/afpd/acl_mappings.h new file mode 100644 index 0000000..7906aee --- /dev/null +++ b/etc/afpd/acl_mappings.h @@ -0,0 +1,105 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. + */ + +#ifndef ACL_MAPPINGS +#define ACL_MAPPINGS + +#ifdef HAVE_SOLARIS_ACLS +#include +#endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif + +#include "acls.h" + +/* + * Stuff for mapping between ACL implementations + */ + +/* Solaris 10u8 still hasn't got ACE_INHERITED_ACE */ +#ifndef ACE_INHERITED_ACE +#define ACE_INHERITED_ACE 0x0080 +#endif + +struct ace_rights_map { + uint32_t from; + uint32_t to; +}; + +#if (defined HAVE_SOLARIS_ACLS || defined HAVE_FREEBSD_SUNACL) +struct ace_rights_map nfsv4_to_darwin_rights[] = { + {ACE_READ_DATA, DARWIN_ACE_READ_DATA}, + {ACE_WRITE_DATA, DARWIN_ACE_WRITE_DATA}, + {ACE_APPEND_DATA, DARWIN_ACE_APPEND_DATA}, + {ACE_READ_NAMED_ATTRS, DARWIN_ACE_READ_EXTATTRIBUTES}, + {ACE_WRITE_NAMED_ATTRS, DARWIN_ACE_WRITE_EXTATTRIBUTES}, + {ACE_EXECUTE, DARWIN_ACE_EXECUTE}, + {ACE_DELETE_CHILD, DARWIN_ACE_DELETE_CHILD}, + {ACE_READ_ATTRIBUTES, DARWIN_ACE_READ_ATTRIBUTES}, + {ACE_WRITE_ATTRIBUTES, DARWIN_ACE_WRITE_ATTRIBUTES}, + {ACE_DELETE, DARWIN_ACE_DELETE}, + {ACE_READ_ACL, DARWIN_ACE_READ_SECURITY}, + {ACE_WRITE_ACL, DARWIN_ACE_WRITE_SECURITY}, + {ACE_WRITE_OWNER, DARWIN_ACE_TAKE_OWNERSHIP}, + {0,0} +}; + +struct ace_rights_map darwin_to_nfsv4_rights[] = { + {DARWIN_ACE_READ_DATA, ACE_READ_DATA}, + {DARWIN_ACE_WRITE_DATA, ACE_WRITE_DATA}, + {DARWIN_ACE_APPEND_DATA, ACE_APPEND_DATA}, + {DARWIN_ACE_READ_EXTATTRIBUTES, ACE_READ_NAMED_ATTRS}, + {DARWIN_ACE_WRITE_EXTATTRIBUTES, ACE_WRITE_NAMED_ATTRS}, + {DARWIN_ACE_EXECUTE, ACE_EXECUTE}, + {DARWIN_ACE_DELETE_CHILD, ACE_DELETE_CHILD}, + {DARWIN_ACE_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, + {DARWIN_ACE_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, + {DARWIN_ACE_DELETE, ACE_DELETE}, + {DARWIN_ACE_READ_SECURITY, ACE_READ_ACL}, + {DARWIN_ACE_WRITE_SECURITY, ACE_WRITE_ACL}, + {DARWIN_ACE_TAKE_OWNERSHIP, ACE_WRITE_OWNER}, + {0,0} +}; + +struct nfsv4_to_darwin_flags_map { + uint16_t from; + uint32_t to; +}; + +struct nfsv4_to_darwin_flags_map nfsv4_to_darwin_flags[] = { + {ACE_FILE_INHERIT_ACE, DARWIN_ACE_FLAGS_FILE_INHERIT}, + {ACE_DIRECTORY_INHERIT_ACE, DARWIN_ACE_FLAGS_DIRECTORY_INHERIT}, + {ACE_NO_PROPAGATE_INHERIT_ACE, DARWIN_ACE_FLAGS_LIMIT_INHERIT}, + {ACE_INHERIT_ONLY_ACE, DARWIN_ACE_FLAGS_ONLY_INHERIT}, + {ACE_INHERITED_ACE, DARWIN_ACE_FLAGS_INHERITED}, + {0,0} +}; + +struct darwin_to_nfsv4_flags_map { + uint32_t from; + uint16_t to; +}; + +struct darwin_to_nfsv4_flags_map darwin_to_nfsv4_flags[] = { + {DARWIN_ACE_FLAGS_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, + {DARWIN_ACE_FLAGS_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, + {DARWIN_ACE_FLAGS_LIMIT_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, + {DARWIN_ACE_FLAGS_ONLY_INHERIT, ACE_INHERIT_ONLY_ACE}, + {DARWIN_ACE_FLAGS_INHERITED, ACE_INHERITED_ACE}, + {0,0} +}; +#endif /* HAVE_SOLARIS_ACLS || HAVE_FREEBSD_SUNACL */ + +#endif /* ACL_MAPPINGS */ diff --git a/etc/afpd/acls.c b/etc/afpd/acls.c new file mode 100644 index 0000000..a792273 --- /dev/null +++ b/etc/afpd/acls.c @@ -0,0 +1,1795 @@ +/* + Copyright (c) 2008, 2009, 2010 Frank Lahm + Copyright (c) 2011 Laura Mueller + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SOLARIS_ACLS +#include +#endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif +#ifdef HAVE_POSIX_ACLS +#include +#endif +#ifdef HAVE_ACL_LIBACL_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "directory.h" +#include "desktop.h" +#include "volume.h" +#include "fork.h" +#include "unix.h" +#include "acls.h" +#include "acl_mappings.h" +#include "auth.h" + +/* for map_acl() */ +#define SOLARIS_2_DARWIN 1 +#define DARWIN_2_SOLARIS 2 +#define POSIX_DEFAULT_2_DARWIN 3 +#define POSIX_ACCESS_2_DARWIN 4 +#define DARWIN_2_POSIX_DEFAULT 5 +#define DARWIN_2_POSIX_ACCESS 6 + +#define MAP_MASK 31 +#define IS_DIR 32 + +/* bit flags for set_acl() and map_aces_darwin_to_posix() */ +#define HAS_DEFAULT_ACL 0x01 +#define HAS_EXT_DEFAULT_ACL 0x02 + +/******************************************************** + * Solaris funcs + ********************************************************/ + +#ifdef HAVE_NFSV4_ACLS + +/*! + * Compile access rights for a user to one file-system object + * + * This combines combines all access rights for a user to one fs-object and + * returns the result as a Darwin allowed rights ACE. + * This must honor trivial ACEs which are a mode_t mapping. + * + * @param obj (r) handle + * @param path (r) path to filesystem object + * @param sb (rw) struct stat of path + * @param ma (rw) UARights struct + * @param rights_out (w) mapped Darwin ACL rights + * + * @returns 0 or -1 on error + */ +static int solaris_acl_rights(const AFPObj *obj, + const char *path, + struct stat *sb, + struct maccess *ma, + uint32_t *rights_out) +{ + EC_INIT; + int i, ace_count, checkgroup; + ace_t *aces = NULL; + uid_t who; + uint16_t flags, type; + uint32_t rights, allowed_rights = 0, denied_rights = 0, darwin_rights; + + /* Get ACL from file/dir */ + EC_NEG1_LOG(ace_count = get_nfsv4_acl(path, &aces)); + + if (ace_count == 0) + goto EC_CLEANUP; + + /* Now check requested rights */ + i = 0; + do { /* Loop through ACEs */ + who = aces[i].a_who; + flags = aces[i].a_flags; + type = aces[i].a_type; + rights = aces[i].a_access_mask; + + if (flags & ACE_INHERIT_ONLY_ACE) + continue; + + /* Now the tricky part: decide if ACE effects our user. I'll explain: + if its a dedicated (non trivial) ACE for the user + OR + if its a ACE for a group we're member of + OR + if its a trivial ACE_OWNER ACE and requested UUID is the owner + OR + if its a trivial ACE_GROUP ACE and requested UUID is group + OR + if its a trivial ACE_EVERYONE ACE + THEN + process ACE */ + if (((who == obj->uid) && !(flags & (ACE_TRIVIAL|ACE_IDENTIFIER_GROUP))) + || + ((flags & ACE_IDENTIFIER_GROUP) && !(flags & ACE_GROUP) && gmem(who, obj->ngroups, obj->groups)) + || + ((flags & ACE_OWNER) && (obj->uid == sb->st_uid)) + || + ((flags & ACE_GROUP) && !(obj->uid == sb->st_uid) && gmem(sb->st_gid, obj->ngroups, obj->groups)) + || + (flags & ACE_EVERYONE && !(obj->uid == sb->st_uid) && !gmem(sb->st_gid, obj->ngroups, obj->groups)) + ) { + /* Found an applicable ACE */ + if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) + allowed_rights |= rights; + else if (type == ACE_ACCESS_DENIED_ACE_TYPE) + /* Only or to denied rights if not previously allowed !! */ + denied_rights |= ((!allowed_rights) & rights); + } + } while (++i < ace_count); + + + /* Darwin likes to ask for "delete_child" on dir, + "write_data" is actually the same, so we add that for dirs */ + if (S_ISDIR(sb->st_mode) && (allowed_rights & ACE_WRITE_DATA)) + allowed_rights |= ACE_DELETE_CHILD; + + /* Remove denied from allowed rights */ + allowed_rights &= ~denied_rights; + + /* map rights */ + darwin_rights = 0; + for (i=0; nfsv4_to_darwin_rights[i].from != 0; i++) { + if (allowed_rights & nfsv4_to_darwin_rights[i].from) + darwin_rights |= nfsv4_to_darwin_rights[i].to; + } + + LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", darwin_rights); + + if (rights_out) + *rights_out = darwin_rights; + + if (ma && obj->options.flags & OPTION_ACL2MACCESS) { + if (darwin_rights & DARWIN_ACE_READ_DATA) + ma->ma_user |= AR_UREAD; + if (darwin_rights & DARWIN_ACE_WRITE_DATA) + ma->ma_user |= AR_UWRITE; + if (darwin_rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH)) + ma->ma_user |= AR_USEARCH; + } + + if (sb && obj->options.flags & OPTION_ACL2MODE) { + if (darwin_rights & DARWIN_ACE_READ_DATA) + sb->st_mode |= S_IRUSR; + if (darwin_rights & DARWIN_ACE_WRITE_DATA) + sb->st_mode |= S_IWUSR; + if (darwin_rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH)) + sb->st_mode |= S_IXUSR; + } + +EC_CLEANUP: + if (aces) free(aces); + + EC_EXIT; +} + +/* + Maps ACE array from Solaris to Darwin. Darwin ACEs are stored in network byte order. + Return numer of mapped ACEs or -1 on error. + All errors while mapping (e.g. getting UUIDs from LDAP) are fatal. +*/ +static int map_aces_solaris_to_darwin(const ace_t *aces, + darwin_ace_t *darwin_aces, + int ace_count) +{ + EC_INIT; + int i, count = 0; + uint32_t flags; + uint32_t rights; + struct passwd *pwd = NULL; + struct group *grp = NULL; + + LOG(log_maxdebug, logtype_afpd, "map_aces_solaris_to_darwin: parsing %d ACES", ace_count); + + while(ace_count--) { + LOG(log_maxdebug, logtype_afpd, "ACE No. %d", ace_count + 1); + /* if its a ACE resulting from nfsv4 mode mapping, discard it */ + if (aces->a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE)) { + LOG(log_debug, logtype_afpd, "trivial ACE"); + aces++; + continue; + } + + if ( ! (aces->a_flags & ACE_IDENTIFIER_GROUP) ) { /* user ace */ + LOG(log_debug, logtype_afpd, "uid: %d", aces->a_who); + EC_NULL_LOG(pwd = getpwuid(aces->a_who)); + LOG(log_debug, logtype_afpd, "uid: %d -> name: %s", aces->a_who, pwd->pw_name); + EC_ZERO_LOG(getuuidfromname(pwd->pw_name, + UUID_USER, + darwin_aces->darwin_ace_uuid)); + } else { /* group ace */ + LOG(log_debug, logtype_afpd, "gid: %d", aces->a_who); + EC_NULL_LOG(grp = getgrgid(aces->a_who)); + LOG(log_debug, logtype_afpd, "gid: %d -> name: %s", aces->a_who, grp->gr_name); + EC_ZERO_LOG(getuuidfromname(grp->gr_name, + UUID_GROUP, + darwin_aces->darwin_ace_uuid)); + } + + /* map flags */ + if (aces->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) + flags = DARWIN_ACE_FLAGS_PERMIT; + else if (aces->a_type == ACE_ACCESS_DENIED_ACE_TYPE) + flags = DARWIN_ACE_FLAGS_DENY; + else { /* unsupported type */ + aces++; + continue; + } + for(i=0; nfsv4_to_darwin_flags[i].from != 0; i++) { + if (aces->a_flags & nfsv4_to_darwin_flags[i].from) + flags |= nfsv4_to_darwin_flags[i].to; + } + darwin_aces->darwin_ace_flags = htonl(flags); + + /* map rights */ + rights = 0; + for (i=0; nfsv4_to_darwin_rights[i].from != 0; i++) { + if (aces->a_access_mask & nfsv4_to_darwin_rights[i].from) + rights |= nfsv4_to_darwin_rights[i].to; + } + darwin_aces->darwin_ace_rights = htonl(rights); + + count++; + aces++; + darwin_aces++; + } + + return count; +EC_CLEANUP: + EC_EXIT; +} + +/* + Maps ACE array from Darwin to Solaris. Darwin ACEs are expected in network byte order. + Return numer of mapped ACEs or -1 on error. + All errors while mapping (e.g. getting UUIDs from LDAP) are fatal. +*/ +static int map_aces_darwin_to_solaris(darwin_ace_t *darwin_aces, + ace_t *nfsv4_aces, + int ace_count) +{ + EC_INIT; + int i, mapped_aces = 0; + uint32_t darwin_ace_flags; + uint32_t darwin_ace_rights; + uint16_t nfsv4_ace_flags; + uint32_t nfsv4_ace_rights; + char *name = NULL; + uuidtype_t uuidtype; + struct passwd *pwd; + struct group *grp; + + while(ace_count--) { + nfsv4_ace_flags = 0; + nfsv4_ace_rights = 0; + + /* uid/gid first */ + EC_ZERO(getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype)); + switch (uuidtype) { + case UUID_USER: + EC_NULL_LOG(pwd = getpwnam(name)); + nfsv4_aces->a_who = pwd->pw_uid; + break; + case UUID_GROUP: + EC_NULL_LOG(grp = getgrnam(name)); + nfsv4_aces->a_who = (uid_t)(grp->gr_gid); + nfsv4_ace_flags |= ACE_IDENTIFIER_GROUP; + break; + default: + LOG(log_error, logtype_afpd, "map_aces_darwin_to_solaris: unkown uuidtype"); + EC_FAIL; + } + free(name); + name = NULL; + + /* now type: allow/deny */ + darwin_ace_flags = ntohl(darwin_aces->darwin_ace_flags); + if (darwin_ace_flags & DARWIN_ACE_FLAGS_PERMIT) + nfsv4_aces->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + else if (darwin_ace_flags & DARWIN_ACE_FLAGS_DENY) + nfsv4_aces->a_type = ACE_ACCESS_DENIED_ACE_TYPE; + else { /* unsupported type */ + darwin_aces++; + continue; + } + /* map flags */ + for(i=0; darwin_to_nfsv4_flags[i].from != 0; i++) { + if (darwin_ace_flags & darwin_to_nfsv4_flags[i].from) + nfsv4_ace_flags |= darwin_to_nfsv4_flags[i].to; + } + + /* map rights */ + darwin_ace_rights = ntohl(darwin_aces->darwin_ace_rights); + for (i=0; darwin_to_nfsv4_rights[i].from != 0; i++) { + if (darwin_ace_rights & darwin_to_nfsv4_rights[i].from) + nfsv4_ace_rights |= darwin_to_nfsv4_rights[i].to; + } + + LOG(log_debug9, logtype_afpd, + "map_aces_darwin_to_solaris: ACE flags: Darwin:%08x -> NFSv4:%04x", + darwin_ace_flags, nfsv4_ace_flags); + LOG(log_debug9, logtype_afpd, + "map_aces_darwin_to_solaris: ACE rights: Darwin:%08x -> NFSv4:%08x", + darwin_ace_rights, nfsv4_ace_rights); + + nfsv4_aces->a_flags = nfsv4_ace_flags; + nfsv4_aces->a_access_mask = nfsv4_ace_rights; + + mapped_aces++; + darwin_aces++; + nfsv4_aces++; + } + + return mapped_aces; +EC_CLEANUP: + if (name) + free(name); + EC_EXIT; +} +#endif /* HAVE_NFSV4_ACLS */ + +/******************************************************** + * POSIX 1e funcs + ********************************************************/ + +#ifdef HAVE_POSIX_ACLS + +static uint32_t posix_permset_to_darwin_rights(acl_entry_t e, int is_dir) +{ + EC_INIT; + uint32_t rights = 0; + acl_permset_t permset; + + EC_ZERO_LOG(acl_get_permset(e, &permset)); + +#ifdef HAVE_ACL_GET_PERM_NP + if (acl_get_perm_np(permset, ACL_READ)) +#else + if (acl_get_perm(permset, ACL_READ)) +#endif + rights = DARWIN_ACE_READ_DATA + | DARWIN_ACE_READ_EXTATTRIBUTES + | DARWIN_ACE_READ_ATTRIBUTES + | DARWIN_ACE_READ_SECURITY; +#ifdef HAVE_ACL_GET_PERM_NP + if (acl_get_perm_np(permset, ACL_WRITE)) { +#else + if (acl_get_perm(permset, ACL_WRITE)) { +#endif + rights |= DARWIN_ACE_WRITE_DATA + | DARWIN_ACE_APPEND_DATA + | DARWIN_ACE_WRITE_EXTATTRIBUTES + | DARWIN_ACE_WRITE_ATTRIBUTES; + if (is_dir) + rights |= DARWIN_ACE_DELETE_CHILD; + } +#ifdef HAVE_ACL_GET_PERM_NP + if (acl_get_perm_np(permset, ACL_EXECUTE)) +#else + if (acl_get_perm(permset, ACL_EXECUTE)) +#endif + rights |= DARWIN_ACE_EXECUTE; + +EC_CLEANUP: + LOG(log_maxdebug, logtype_afpd, "mapped rights: 0x%08x", rights); + return rights; +} + +/*! + * Compile access rights for a user to one file-system object + * + * This combines combines all access rights for a user to one fs-object and + * returns the result as a Darwin allowed rights ACE. + * This must honor trivial ACEs which are a mode_t mapping. + * + * @param path (r) path to filesystem object + * @param sb (r) struct stat of path + * @param result (rw) resulting Darwin allow ACE + * + * @returns 0 or -1 on error + */ + +static int posix_acl_rights(const AFPObj *obj, + const char *path, + const struct stat *sb, + uint32_t *result) +{ + EC_INIT; + int entry_id = ACL_FIRST_ENTRY; + uint32_t rights = 0; /* rights which do not depend on ACL_MASK */ + uint32_t acl_rights = 0; /* rights which are subject to limitations imposed by ACL_MASK */ + uint32_t mask_rights = 0xffffffff; + uid_t *uid = NULL; + gid_t *gid = NULL; + acl_t acl = NULL; + acl_entry_t e; + acl_tag_t tag; + + EC_NULL_LOGSTR(acl = acl_get_file(path, ACL_TYPE_ACCESS), + "acl_get_file(\"%s\"): %s", fullpathname(path), strerror(errno)); + + /* Iterate through all ACEs. If we apply mask_rights later there is no need to iterate twice. */ + while (acl_get_entry(acl, entry_id, &e) == 1) { + entry_id = ACL_NEXT_ENTRY; + EC_ZERO_LOG(acl_get_tag_type(e, &tag)); + + switch (tag) { + case ACL_USER_OBJ: + if (sb->st_uid == obj->uid) { + LOG(log_maxdebug, logtype_afpd, "ACL_USER_OBJ: %u", sb->st_uid); + rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); + } + break; + + case ACL_USER: + EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e)); + + if (*uid == obj->uid) { + LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid); + acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); + } + acl_free(uid); + uid = NULL; + break; + + case ACL_GROUP_OBJ: + if (!(sb->st_uid == obj->uid) && gmem(sb->st_gid, obj->ngroups, obj->groups)) { + LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid); + acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); + } + break; + + case ACL_GROUP: + EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e)); + + if (gmem(*gid, obj->ngroups, obj->groups)) { + LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid); + acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); + } + acl_free(gid); + gid = NULL; + break; + + case ACL_MASK: + mask_rights = posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); + LOG(log_maxdebug, logtype_afpd, "maskrights: 0x%08x", mask_rights); + break; + + case ACL_OTHER: + if (!(sb->st_uid == obj->uid) && !gmem(sb->st_gid, obj->ngroups, obj->groups)) { + LOG(log_maxdebug, logtype_afpd, "ACL_OTHER"); + rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)); + } + break; + + default: + continue; + } + } /* while */ + + /* apply the mask and collect the rights */ + rights |= (acl_rights & mask_rights); + + *result |= rights; + +EC_CLEANUP: + if (acl) acl_free(acl); + if (uid) acl_free(uid); + if (gid) acl_free(gid); + EC_EXIT; +} + +/*! + * Helper function for posix_acls_to_uaperms() to convert Posix ACL permissions + * into access rights needed to fill ua_permissions of a FPUnixPrivs structure. + * + * @param entry (r) Posix ACL entry + * + * @returns access rights + */ +static u_char acl_permset_to_uarights(acl_entry_t entry) { + acl_permset_t permset; + u_char rights = 0; + + if (acl_get_permset(entry, &permset) == -1) + return rights; + +#ifdef HAVE_ACL_GET_PERM_NP + if (acl_get_perm_np(permset, ACL_READ)) +#else + if (acl_get_perm(permset, ACL_READ)) +#endif + rights |= AR_UREAD; + +#ifdef HAVE_ACL_GET_PERM_NP + if (acl_get_perm_np(permset, ACL_WRITE)) +#else + if (acl_get_perm(permset, ACL_WRITE)) +#endif + rights |= AR_UWRITE; + +#ifdef HAVE_ACL_GET_PERM_NP + if (acl_get_perm_np(permset, ACL_EXECUTE)) +#else + if (acl_get_perm(permset, ACL_EXECUTE)) +#endif + rights |= AR_USEARCH; + + return rights; +} + +/*! + * Update FPUnixPrivs for a file-system object on a volume supporting ACLs + * + * Checks permissions granted by ACLS for a user to one fs-object and + * updates user and group permissions in given struct maccess. As OS X + * doesn't conform to Posix 1003.1e Draft 17 it expects proper group + * permissions in st_mode of struct stat even if the fs-object has an + * ACL_MASK entry, st_mode gets modified to properly reflect group + * permissions. + * + * @param path (r) path to filesystem object + * @param sb (rw) struct stat of path + * @param maccess (rw) struct maccess of path + * + * @returns 0 or -1 on error + */ +static int posix_acls_to_uaperms(const AFPObj *obj, const char *path, struct stat *sb, struct maccess *ma) { + EC_INIT; + + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t entry; + acl_tag_t tag; + acl_t acl = NULL; + uid_t *uid; + gid_t *gid; + uid_t whoami = geteuid(); + + u_char group_rights = 0x00; + u_char acl_rights = 0x00; + u_char mask = 0xff; + + acl = acl_get_file(path, ACL_TYPE_ACCESS); + if (acl == NULL) { + LOG(log_debug, logtype_afpd, "acl_get_file: %s: %s", + path, strerror(errno)); + EC_FAIL; + } + + /* iterate through all ACEs */ + while (acl_get_entry(acl, entry_id, &entry) == 1) { + entry_id = ACL_NEXT_ENTRY; + EC_ZERO_LOG(acl_get_tag_type(entry, &tag)); + + switch (tag) { + case ACL_USER: + EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(entry)); + + if (*uid == obj->uid && !(whoami == sb->st_uid)) { + LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid); + acl_rights |= acl_permset_to_uarights(entry); + } + acl_free(uid); + break; + + case ACL_GROUP_OBJ: + group_rights = acl_permset_to_uarights(entry); + LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid); + + if (gmem(sb->st_gid, obj->ngroups, obj->groups) && !(whoami == sb->st_uid)) + acl_rights |= group_rights; + break; + + case ACL_GROUP: + EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(entry)); + + if (gmem(*gid, obj->ngroups, obj->groups) && !(whoami == sb->st_uid)) { + LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid); + acl_rights |= acl_permset_to_uarights(entry); + } + acl_free(gid); + break; + + case ACL_MASK: + mask = acl_permset_to_uarights(entry); + LOG(log_maxdebug, logtype_afpd, "ACL_MASK: 0x%02x", mask); + break; + + default: + break; + } + } + + if (obj->options.flags & OPTION_ACL2MACCESS) { + /* apply the mask and adjust user and group permissions */ + ma->ma_user |= (acl_rights & mask); + ma->ma_group = (group_rights & mask); + } + + if (obj->options.flags & OPTION_ACL2MODE) { + /* update st_mode to properly reflect group permissions */ + sb->st_mode &= ~S_IRWXG; + if (ma->ma_group & AR_USEARCH) + sb->st_mode |= S_IXGRP; + if (ma->ma_group & AR_UWRITE) + sb->st_mode |= S_IWGRP; + if (ma->ma_group & AR_UREAD) + sb->st_mode |= S_IRGRP; + } + +EC_CLEANUP: + if (acl) acl_free(acl); + + EC_EXIT; +} + +#if 0 +/*! + * Add entries of one acl to another acl + * + * @param aclp (rw) destination acl where new aces will be added + * @param acl (r) source acl where aces will be copied from + * + * @returns 0 on success, -1 on error + */ +static int acl_add_acl(acl_t *aclp, const acl_t acl) +{ + EC_INIT; + int id; + acl_entry_t se, de; + + for (id = ACL_FIRST_ENTRY; acl_get_entry(acl, id, &se) == 1; id = ACL_NEXT_ENTRY) { + EC_ZERO_LOG_ERR(acl_create_entry(aclp, &de), AFPERR_MISC); + EC_ZERO_LOG_ERR(acl_copy_entry(de, se), AFPERR_MISC); + } + +EC_CLEANUP: + EC_EXIT; +} +#endif + +/*! + * Map Darwin ACE rights to POSIX 1e perm + * + * We can only map few rights: + * DARWIN_ACE_READ_DATA -> ACL_READ + * DARWIN_ACE_WRITE_DATA -> ACL_WRITE + * DARWIN_ACE_DELETE_CHILD & (is_dir == 1) -> ACL_WRITE + * DARWIN_ACE_EXECUTE -> ACL_EXECUTE + * + * @param entry (rw) result of the mapping + * @param is_dir (r) 1 for dirs, 0 for files + * + * @returns mapping result as acl_perm_t, -1 on error + */ +static acl_perm_t map_darwin_right_to_posix_permset(uint32_t darwin_ace_rights, int is_dir) +{ + acl_perm_t perm = 0; + + if (darwin_ace_rights & DARWIN_ACE_READ_DATA) + perm |= ACL_READ; + + if (darwin_ace_rights & (DARWIN_ACE_WRITE_DATA | (is_dir ? DARWIN_ACE_DELETE_CHILD : 0))) + perm |= ACL_WRITE; + + if (darwin_ace_rights & DARWIN_ACE_EXECUTE) + perm |= ACL_EXECUTE; + + return perm; +} + +/*! + * Add a ACL_USER or ACL_GROUP permission to an ACL, extending existing ACEs + * + * Add a permission of "type" for user or group "id" to an ACL. Scan the ACL + * for existing permissions for this type/id, if there is one add the perm, + * otherwise create a new ACL entry. + * perm can be or'ed ACL_READ, ACL_WRITE and ACL_EXECUTE. + * + * @param aclp (rw) pointer to ACL + * @param type (r) acl_tag_t of ACL_USER or ACL_GROUP + * @param id (r) uid_t uid for ACL_USER, or gid casted to uid_t for ACL_GROUP + * @param perm (r) acl_perm_t permissions to add + * + * @returns 0 on success, -1 on failure + */ +static int posix_acl_add_perm(acl_t *aclp, acl_tag_t type, uid_t id, acl_perm_t perm) +{ + EC_INIT; + uid_t *eid = NULL; + acl_entry_t e; + acl_tag_t tag; + int entry_id = ACL_FIRST_ENTRY; + acl_permset_t permset; + + int found = 0; + for ( ; (! found) && acl_get_entry(*aclp, entry_id, &e) == 1; entry_id = ACL_NEXT_ENTRY) { + EC_ZERO_LOG(acl_get_tag_type(e, &tag)); + if (tag != ACL_USER && tag != ACL_GROUP) + continue; + EC_NULL_LOG(eid = (uid_t *)acl_get_qualifier(e)); + if ((*eid == id) && (type == tag)) { + /* found an ACE for this type/id */ + found = 1; + EC_ZERO_LOG(acl_get_permset(e, &permset)); + EC_ZERO_LOG(acl_add_perm(permset, perm)); + } + + acl_free(eid); + eid = NULL; + } + + if ( ! found) { + /* there was no existing ACE for this type/id */ + EC_ZERO_LOG(acl_create_entry(aclp, &e)); + EC_ZERO_LOG(acl_set_tag_type(e, type)); + EC_ZERO_LOG(acl_set_qualifier(e, &id)); + EC_ZERO_LOG(acl_get_permset(e, &permset)); + EC_ZERO_LOG(acl_clear_perms(permset)); + EC_ZERO_LOG(acl_add_perm(permset, perm)); + EC_ZERO_LOG(acl_set_permset(e, permset)); + } + +EC_CLEANUP: + if (eid) acl_free(eid); + + EC_EXIT; +} + +/*! + * Map Darwin ACL to POSIX ACL. + * + * aclp must point to a acl_init'ed acl_t or an acl_t that can eg contain default ACEs. + * Mapping pecularities: + * - we create a default ace (which inherits to files and dirs) if either + DARWIN_ACE_FLAGS_FILE_INHERIT or DARWIN_ACE_FLAGS_DIRECTORY_INHERIT is requested + * - we throw away DARWIN_ACE_FLAGS_LIMIT_INHERIT (can't be mapped), thus the ACL will + * not be limited + * + * @param darwin_aces (r) pointer to darwin_aces buffer + * @param def_aclp (rw) directories: pointer to an initialized acl_t with + the default acl files: *def_aclp will be NULL + * @param acc_aclp (rw) pointer to an initialized acl_t with the access acl + * @param ace_count (r) number of ACEs in darwin_aces buffer + * @param default_acl_flags (rw) flags to indicate if the object has a basic default + * acl or an extended default acl. + * + * @returns 0 on success storing the result in aclp, -1 on error. default_acl_flags + * is set to HAS_DEFAULT_ACL|HAS_EXT_DEFAULT_ACL in case there is at least one + * extended default ace. Otherwise default_acl_flags is left unchanged. + */ +static int map_aces_darwin_to_posix(const darwin_ace_t *darwin_aces, + acl_t *def_aclp, + acl_t *acc_aclp, + int ace_count, + uint32_t *default_acl_flags) +{ + EC_INIT; + char *name = NULL; + uuidtype_t uuidtype; + struct passwd *pwd; + struct group *grp; + uid_t id; + uint32_t darwin_ace_flags, darwin_ace_rights; + acl_tag_t tag; + acl_perm_t perm; + + for ( ; ace_count != 0; ace_count--, darwin_aces++) { + /* type: allow/deny, posix only has allow */ + darwin_ace_flags = ntohl(darwin_aces->darwin_ace_flags); + if ( ! (darwin_ace_flags & DARWIN_ACE_FLAGS_PERMIT)) + continue; + + darwin_ace_rights = ntohl(darwin_aces->darwin_ace_rights); + perm = map_darwin_right_to_posix_permset(darwin_ace_rights, (*def_aclp != NULL)); + if (perm == 0) + continue; /* dont add empty perm */ + + LOG(log_debug, logtype_afpd, "map_ace: no: %u, flags: %08x, darwin: %08x, posix: %02x", + ace_count, darwin_ace_flags, darwin_ace_rights, perm); + + /* uid/gid */ + EC_ZERO_LOG(getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype)); + switch (uuidtype) { + case UUID_USER: + EC_NULL_LOG(pwd = getpwnam(name)); + tag = ACL_USER; + id = pwd->pw_uid; + LOG(log_debug, logtype_afpd, "map_ace: name: %s, uid: %u", name, id); + break; + case UUID_GROUP: + EC_NULL_LOG(grp = getgrnam(name)); + tag = ACL_GROUP; + id = (uid_t)(grp->gr_gid); + LOG(log_debug, logtype_afpd, "map_ace: name: %s, gid: %u", name, id); + break; + default: + continue; + } + free(name); + name = NULL; + + if (darwin_ace_flags & DARWIN_ACE_INHERIT_CONTROL_FLAGS) { + if (*def_aclp == NULL) { + /* ace request inheritane but we haven't got a default acl pointer */ + LOG(log_warning, logtype_afpd, "map_acl: unexpected ACE, flags: 0x%04x", + darwin_ace_flags); + EC_FAIL; + } + /* add it as default ace */ + EC_ZERO_LOG(posix_acl_add_perm(def_aclp, tag, id, perm)); + *default_acl_flags = (HAS_DEFAULT_ACL|HAS_EXT_DEFAULT_ACL); + + if (! (darwin_ace_flags & DARWIN_ACE_FLAGS_ONLY_INHERIT)) + /* if it not a "inherit only" ace, it must be added as access aces too */ + EC_ZERO_LOG(posix_acl_add_perm(acc_aclp, tag, id, perm)); + } else { + EC_ZERO_LOG(posix_acl_add_perm(acc_aclp, tag, id, perm)); + } + } + +EC_CLEANUP: + if (name) + free(name); + + EC_EXIT; +} + +/* + * Map ACEs from POSIX to Darwin. + * type is either POSIX_DEFAULT_2_DARWIN or POSIX_ACCESS_2_DARWIN, cf. acl_get_file. + * Return number of mapped ACES, -1 on error. + */ +static int map_acl_posix_to_darwin(int type, const acl_t acl, darwin_ace_t *darwin_aces) +{ + EC_INIT; + int mapped_aces = 0; + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t e; + acl_tag_t tag; + uid_t *uid = NULL; + gid_t *gid = NULL; + struct passwd *pwd = NULL; + struct group *grp = NULL; + uint32_t flags; + uint32_t rights, maskrights = 0; + darwin_ace_t *saved_darwin_aces = darwin_aces; + + LOG(log_maxdebug, logtype_afpd, "map_aces_posix_to_darwin(%s)", + (type & MAP_MASK) == POSIX_DEFAULT_2_DARWIN ? + "POSIX_DEFAULT_2_DARWIN" : "POSIX_ACCESS_2_DARWIN"); + + /* itereate through all ACEs */ + while (acl_get_entry(acl, entry_id, &e) == 1) { + entry_id = ACL_NEXT_ENTRY; + + /* get ACE type */ + EC_ZERO_LOG(acl_get_tag_type(e, &tag)); + + /* we return user and group ACE */ + switch (tag) { + case ACL_USER: + EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e)); + EC_NULL_LOG(pwd = getpwuid(*uid)); + LOG(log_debug, logtype_afpd, "map_aces_posix_to_darwin: uid: %d -> name: %s", + *uid, pwd->pw_name); + EC_ZERO_LOG(getuuidfromname(pwd->pw_name, UUID_USER, darwin_aces->darwin_ace_uuid)); + acl_free(uid); + uid = NULL; + break; + + case ACL_GROUP: + EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e)); + EC_NULL_LOG(grp = getgrgid(*gid)); + LOG(log_debug, logtype_afpd, "map_aces_posix_to_darwin: gid: %d -> name: %s", + *gid, grp->gr_name); + EC_ZERO_LOG(getuuidfromname(grp->gr_name, UUID_GROUP, darwin_aces->darwin_ace_uuid)); + acl_free(gid); + gid = NULL; + break; + + case ACL_MASK: + maskrights = posix_permset_to_darwin_rights(e, type & IS_DIR); + continue; + + default: + continue; + } + + /* flags */ + flags = DARWIN_ACE_FLAGS_PERMIT; + if ((type & MAP_MASK) == POSIX_DEFAULT_2_DARWIN) + flags |= DARWIN_ACE_FLAGS_FILE_INHERIT + | DARWIN_ACE_FLAGS_DIRECTORY_INHERIT + | DARWIN_ACE_FLAGS_ONLY_INHERIT; + darwin_aces->darwin_ace_flags = htonl(flags); + + /* rights */ + rights = posix_permset_to_darwin_rights(e, type & IS_DIR); + darwin_aces->darwin_ace_rights = htonl(rights); + + darwin_aces++; + mapped_aces++; + } /* while */ + + /* Loop through the mapped ACE buffer once again, applying the mask */ + for (int i = mapped_aces; i > 0; i--) { + saved_darwin_aces->darwin_ace_rights &= htonl(maskrights); + saved_darwin_aces++; + } + + EC_STATUS(mapped_aces); + +EC_CLEANUP: + if (uid) acl_free(uid); + if (gid) acl_free(gid); + EC_EXIT; +} +#endif + +/* + * Multiplex ACL mapping (SOLARIS_2_DARWIN, DARWIN_2_SOLARIS, POSIX_2_DARWIN, DARWIN_2_POSIX). + * Reads from 'aces' buffer, writes to 'rbuf' buffer. + * Caller must provide buffer. + * Darwin ACEs are read and written in network byte order. + * Needs to know how many ACEs are in the ACL (ace_count) for Solaris ACLs. + * Ignores trivial ACEs. + * Return no of mapped ACEs or -1 on error. + */ +static int map_acl(int type, void *acl, darwin_ace_t *buf, int ace_count) +{ + int mapped_aces; + + LOG(log_debug9, logtype_afpd, "map_acl: BEGIN"); + + switch (type & MAP_MASK) { + +#ifdef HAVE_NFSV4_ACLS + case SOLARIS_2_DARWIN: + mapped_aces = map_aces_solaris_to_darwin( acl, buf, ace_count); + break; + + case DARWIN_2_SOLARIS: + mapped_aces = map_aces_darwin_to_solaris( buf, acl, ace_count); + break; +#endif /* HAVE_NFSV4_ACLS */ + +#ifdef HAVE_POSIX_ACLS + case POSIX_DEFAULT_2_DARWIN: + mapped_aces = map_acl_posix_to_darwin(type, (const acl_t)acl, buf); + break; + + case POSIX_ACCESS_2_DARWIN: + mapped_aces = map_acl_posix_to_darwin(type, (const acl_t)acl, buf); + break; + + case DARWIN_2_POSIX_DEFAULT: + break; + + case DARWIN_2_POSIX_ACCESS: + break; +#endif /* HAVE_POSIX_ACLS */ + + default: + mapped_aces = -1; + break; + } + + LOG(log_debug9, logtype_afpd, "map_acl: END"); + return mapped_aces; +} + +/* Get ACL from object omitting trivial ACEs. Map to Darwin ACL style and + store Darwin ACL at rbuf. Add length of ACL written to rbuf to *rbuflen. + Returns 0 on success, -1 on error. */ +static int get_and_map_acl(char *name, char *rbuf, size_t *rbuflen) +{ + EC_INIT; + int mapped_aces = 0; + int dirflag; + char *darwin_ace_count = rbuf; +#ifdef HAVE_NFSV4_ACLS + int ace_count = 0; + ace_t *aces = NULL; +#endif +#ifdef HAVE_POSIX_ACLS + struct stat st; +#endif + LOG(log_debug9, logtype_afpd, "get_and_map_acl: BEGIN"); + + /* Skip length and flags */ + rbuf += 4; + *rbuf = 0; + rbuf += 4; + +#ifdef HAVE_NFSV4_ACLS + EC_NEG1(ace_count = get_nfsv4_acl(name, &aces)); + EC_NEG1(mapped_aces = map_acl(SOLARIS_2_DARWIN, aces, (darwin_ace_t *)rbuf, ace_count)); +#endif /* HAVE_NFSV4_ACLS */ + +#ifdef HAVE_POSIX_ACLS + acl_t defacl = NULL , accacl = NULL; + + /* stat to check if its a dir */ + EC_ZERO_LOG(lstat(name, &st)); + + /* if its a dir, check for default acl too */ + dirflag = 0; + if (S_ISDIR(st.st_mode)) { + dirflag = IS_DIR; + EC_NULL_LOG(defacl = acl_get_file(name, ACL_TYPE_DEFAULT)); + EC_NEG1(mapped_aces = map_acl(POSIX_DEFAULT_2_DARWIN | dirflag, + defacl, + (darwin_ace_t *)rbuf, + 0)); + } + + EC_NULL_LOG(accacl = acl_get_file(name, ACL_TYPE_ACCESS)); + + int tmp; + EC_NEG1(tmp = map_acl(POSIX_ACCESS_2_DARWIN | dirflag, + accacl, + (darwin_ace_t *)(rbuf + mapped_aces * sizeof(darwin_ace_t)), + 0)); + mapped_aces += tmp; +#endif /* HAVE_POSIX_ACLS */ + + LOG(log_debug, logtype_afpd, "get_and_map_acl: mapped %d ACEs", mapped_aces); + + *rbuflen += sizeof(darwin_acl_header_t) + (mapped_aces * sizeof(darwin_ace_t)); + mapped_aces = htonl(mapped_aces); + memcpy(darwin_ace_count, &mapped_aces, sizeof(uint32_t)); + + EC_STATUS(0); + +EC_CLEANUP: +#ifdef HAVE_NFSV4_ACLS + if (aces) free(aces); +#endif +#ifdef HAVE_POSIX_ACLS + if (defacl) acl_free(defacl); + if (accacl) acl_free(accacl); +#endif /* HAVE_POSIX_ACLS */ + + LOG(log_debug9, logtype_afpd, "get_and_map_acl: END"); + + EC_EXIT; +} + +/* Removes all non-trivial ACLs from object. Returns full AFPERR code. */ +static int remove_acl(const struct vol *vol,const char *path, int dir) +{ + int ret = AFP_OK; + +#if (defined HAVE_NFSV4_ACLS || defined HAVE_POSIX_ACLS) + /* Ressource etc. first */ + if ((ret = vol->vfs->vfs_remove_acl(vol, path, dir)) != AFP_OK) + return ret; + /* now the data fork or dir */ + ret = remove_acl_vfs(path); +#endif + return ret; +} + +/* + Set ACL. Subtleties: + - the client sends a complete list of ACEs, not only new ones. So we dont need to do + any combination business (one exception being 'kFileSec_Inherit': see next) + - client might request that we add inherited ACEs via 'kFileSec_Inherit'. + We will store inherited ACEs first, which is Darwins canonical order. + - returns AFPerror code +*/ +#ifdef HAVE_NFSV4_ACLS +static int set_acl(const struct vol *vol, + char *name, + int inherit, + darwin_ace_t *daces, + uint32_t ace_count) +{ + EC_INIT; + int i, nfsv4_ace_count; + int tocopy_aces_count = 0, new_aces_count = 0, trivial_ace_count = 0; + ace_t *old_aces, *new_aces = NULL; + uint16_t flags; + + LOG(log_debug9, logtype_afpd, "set_acl: BEGIN"); + + if (inherit) + /* inherited + trivial ACEs */ + flags = ACE_INHERITED_ACE | ACE_OWNER | ACE_GROUP | ACE_EVERYONE; + else + /* only trivial ACEs */ + flags = ACE_OWNER | ACE_GROUP | ACE_EVERYONE; + + /* Get existing ACL and count ACEs which have to be copied */ + if ((nfsv4_ace_count = get_nfsv4_acl(name, &old_aces)) == -1) + return AFPERR_MISC; + for ( i=0; i < nfsv4_ace_count; i++) { + if (old_aces[i].a_flags & flags) + tocopy_aces_count++; + } + + /* Now malloc buffer exactly sized to fit all new ACEs */ + if ((new_aces = malloc((ace_count + tocopy_aces_count) * sizeof(ace_t))) == NULL) { + LOG(log_error, logtype_afpd, "set_acl: malloc %s", strerror(errno)); + EC_STATUS(AFPERR_MISC); + goto EC_CLEANUP; + } + + /* Start building new ACL */ + + /* Copy local inherited ACEs. Therefore we have 'Darwin canonical order' (see chmod there): + inherited ACEs first. */ + if (inherit) { + for (i=0; i < nfsv4_ace_count; i++) { + if (old_aces[i].a_flags & ACE_INHERITED_ACE) { + memcpy(&new_aces[new_aces_count], &old_aces[i], sizeof(ace_t)); + new_aces_count++; + } + } + } + LOG(log_debug7, logtype_afpd, "set_acl: copied %d inherited ACEs", new_aces_count); + + /* Now the ACEs from the client */ + if ((ret = (map_acl(DARWIN_2_SOLARIS, + &new_aces[new_aces_count], + daces, + ace_count))) == -1) { + EC_STATUS(AFPERR_PARAM); + goto EC_CLEANUP; + } + new_aces_count += ret; + LOG(log_debug7, logtype_afpd, "set_acl: mapped %d ACEs from client", ret); + + /* Now copy the trivial ACEs */ + for (i=0; i < nfsv4_ace_count; i++) { + if (old_aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE)) { + memcpy(&new_aces[new_aces_count], &old_aces[i], sizeof(ace_t)); + new_aces_count++; + trivial_ace_count++; + } + } + LOG(log_debug7, logtype_afpd, "set_acl: copied %d trivial ACEs", trivial_ace_count); + + /* Ressourcefork first */ + if ((ret = (vol->vfs->vfs_acl(vol, name, ACE_SETACL, new_aces_count, new_aces))) != 0) { + LOG(log_debug, logtype_afpd, "set_acl: error setting acl: %s", strerror(errno)); + switch (errno) { + case ENOENT: + break; + case EACCES: + case EPERM: + EC_EXIT_STATUS(AFPERR_ACCESS); + default: + EC_EXIT_STATUS(AFPERR_MISC); + } + } + + if ((ret = (acl(name, ACE_SETACL, new_aces_count, new_aces))) != 0) { + LOG(log_error, logtype_afpd, "set_acl: error setting acl: %s", strerror(errno)); + switch (errno) { + case EACCES: + case EPERM: + EC_EXIT_STATUS(AFPERR_ACCESS); + case ENOENT: + EC_EXIT_STATUS(AFPERR_NOITEM); + default: + EC_EXIT_STATUS(AFPERR_MISC); + } + } + + EC_STATUS(AFP_OK); + +EC_CLEANUP: + if (old_aces) free(old_aces); + if (new_aces) free(new_aces); + + LOG(log_debug9, logtype_afpd, "set_acl: END"); + EC_EXIT; +} +#endif /* HAVE_NFSV4_ACLS */ + +#ifdef HAVE_POSIX_ACLS +#ifndef HAVE_ACL_FROM_MODE +static acl_t acl_from_mode(mode_t mode) +{ + acl_t acl; + acl_entry_t entry; + acl_permset_t permset; + + if (!(acl = acl_init(3))) + return NULL; + + if (acl_create_entry(&acl, &entry) != 0) + goto error; + acl_set_tag_type(entry, ACL_USER_OBJ); + acl_get_permset(entry, &permset); + acl_clear_perms(permset); + if (mode & S_IRUSR) + acl_add_perm(permset, ACL_READ); + if (mode & S_IWUSR) + acl_add_perm(permset, ACL_WRITE); + if (mode & S_IXUSR) + acl_add_perm(permset, ACL_EXECUTE); + acl_set_permset(entry, permset); + + if (acl_create_entry(&acl, &entry) != 0) + goto error; + acl_set_tag_type(entry, ACL_GROUP_OBJ); + acl_get_permset(entry, &permset); + acl_clear_perms(permset); + if (mode & S_IRGRP) + acl_add_perm(permset, ACL_READ); + if (mode & S_IWGRP) + acl_add_perm(permset, ACL_WRITE); + if (mode & S_IXGRP) + acl_add_perm(permset, ACL_EXECUTE); + acl_set_permset(entry, permset); + + if (acl_create_entry(&acl, &entry) != 0) + goto error; + acl_set_tag_type(entry, ACL_OTHER); + acl_get_permset(entry, &permset); + acl_clear_perms(permset); + if (mode & S_IROTH) + acl_add_perm(permset, ACL_READ); + if (mode & S_IWOTH) + acl_add_perm(permset, ACL_WRITE); + if (mode & S_IXOTH) + acl_add_perm(permset, ACL_EXECUTE); + acl_set_permset(entry, permset); + + return acl; + +error: + acl_free(acl); + return NULL; +} +#endif + +static int set_acl(const struct vol *vol, + const char *name, + int inherit _U_, + darwin_ace_t *daces, + uint32_t ace_count) +{ + EC_INIT; + struct stat st; + acl_t default_acl = NULL; + acl_t access_acl = NULL; + acl_entry_t entry; + acl_tag_t tag; + int entry_id = ACL_FIRST_ENTRY; + /* flags to indicate if the object has a minimal default acl and/or an extended + * default acl. + */ + uint32_t default_acl_flags = 0; + + LOG(log_maxdebug, logtype_afpd, "set_acl: BEGIN"); + + EC_NULL_LOG_ERR(access_acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC); + + /* Iterate through acl and remove all extended acl entries. */ + while (acl_get_entry(access_acl, entry_id, &entry) == 1) { + entry_id = ACL_NEXT_ENTRY; + EC_ZERO_LOG(acl_get_tag_type(entry, &tag)); + + if ((tag == ACL_USER) || (tag == ACL_GROUP) || (tag == ACL_MASK)) { + EC_ZERO_LOG_ERR(acl_delete_entry(access_acl, entry), AFPERR_MISC); + } + } /* while */ + + /* In case we are acting on a directory prepare a default acl. For files default_acl will be NULL. + * If the directory already has a default acl it will be preserved. + */ + EC_ZERO_LOG_ERR(lstat(name, &st), AFPERR_NOOBJ); + + if (S_ISDIR(st.st_mode)) { + default_acl = acl_get_file(name, ACL_TYPE_DEFAULT); + + if (default_acl) { + /* If default_acl is not empty then the dir has a default acl. */ + if (acl_get_entry(default_acl, ACL_FIRST_ENTRY, &entry) == 1) + default_acl_flags = HAS_DEFAULT_ACL; + + acl_free(default_acl); + } + default_acl = acl_dup(access_acl); + } + /* adds the clients aces */ + EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &default_acl, &access_acl, ace_count, &default_acl_flags), AFPERR_MISC); + + /* calcuate ACL mask */ + EC_ZERO_LOG_ERR(acl_calc_mask(&access_acl), AFPERR_MISC); + + /* is it ok? */ + EC_ZERO_LOG_ERR(acl_valid(access_acl), AFPERR_MISC); + + /* set it */ + EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, access_acl), AFPERR_MISC); + EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_ACCESS, 0, access_acl), AFPERR_MISC); + + if (default_acl) { + /* If the dir has an extended default acl it's ACL_MASK must be updated.*/ + if (default_acl_flags & HAS_EXT_DEFAULT_ACL) + EC_ZERO_LOG_ERR(acl_calc_mask(&default_acl), AFPERR_MISC); + + if (default_acl_flags) { + EC_ZERO_LOG_ERR(acl_valid(default_acl), AFPERR_MISC); + EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, default_acl), AFPERR_MISC); + EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_DEFAULT, 0, default_acl), AFPERR_MISC); + } + } + +EC_CLEANUP: + if (access_acl) acl_free(access_acl); + if (default_acl) acl_free(default_acl); + + LOG(log_maxdebug, logtype_afpd, "set_acl: END"); + EC_EXIT; +} +#endif /* HAVE_POSIX_ACLS */ + +/*! + * Checks if a given UUID has requested_rights(type darwin_ace_rights) for path. + * + * Note: this gets called frequently and is a good place for optimizations ! + * + * @param vol (r) volume + * @param dir (rw) directory + * @param path (r) path to filesystem object + * @param uuid (r) UUID of user + * @param requested_rights (r) requested Darwin ACE + * + * @returns AFP result code +*/ +static int check_acl_access(const AFPObj *obj, + const struct vol *vol, + struct dir *dir, + const char *path, + const uuidp_t uuid, + uint32_t requested_rights) +{ + int ret; + uint32_t allowed_rights = 0; + char *username = NULL; + struct stat st; + bstring parent = NULL; + int is_dir; + + LOG(log_maxdebug, logtype_afpd, "check_acl_access(dir: \"%s\", path: \"%s\", curdir: \"%s\", 0x%08x)", + cfrombstr(dir->d_fullpath), path, getcwdpath(), requested_rights); + + AFP_ASSERT(vol); + + /* This check is not used anymore, as OS X Server seems to be ignoring too */ +#if 0 + /* Get uid or gid from UUID */ + EC_ZERO_ERR(getnamefromuuid(uuid, &username, &uuidtype), AFPERR_PARAM); + switch (uuidtype) { + case UUID_USER: + break; + case UUID_GROUP: + LOG(log_warning, logtype_afpd, "check_acl_access: afp_access not supported for groups"); + EC_STATUS(AFPERR_MISC); + goto EC_CLEANUP; + default: + EC_STATUS(AFPERR_MISC); + goto EC_CLEANUP; + } +#endif + + EC_ZERO_LOG_ERR(ostat(path, &st, vol_syml_opt(vol)), AFPERR_PARAM); + + is_dir = !strcmp(path, "."); + + if (is_dir && (curdir->d_rights_cache != 0xffffffff)) { + /* its a dir and the cache value is valid */ + allowed_rights = curdir->d_rights_cache; + LOG(log_debug, logtype_afpd, "check_access: allowed rights from dircache: 0x%08x", allowed_rights); + } else { +#ifdef HAVE_NFSV4_ACLS + EC_ZERO_LOG(solaris_acl_rights(obj, path, &st, NULL, &allowed_rights)); +#endif +#ifdef HAVE_POSIX_ACLS + EC_ZERO_LOG(posix_acl_rights(obj, path, &st, &allowed_rights)); +#endif + /* + * The DARWIN_ACE_DELETE right might implicitly result from write acces to the parent + * directory. As it seems the 10.6 AFP client is puzzled when this right is not + * allowed where a delete would succeed because the parent dir gives write perms. + * So we check the parent dir for write access and set the right accordingly. + * Currentyl acl2ownermode calls us with dir = NULL, because it doesn't make sense + * there to do this extra check -- afaict. + */ + if (vol && dir && (requested_rights & DARWIN_ACE_DELETE)) { + int i; + uint32_t parent_rights = 0; + + if (curdir->d_did == DIRDID_ROOT_PARENT) { + /* use volume path */ + EC_NULL_LOG_ERR(parent = bfromcstr(vol->v_path), AFPERR_MISC); + } else { + /* build path for parent */ + EC_NULL_LOG_ERR(parent = bstrcpy(curdir->d_fullpath), AFPERR_MISC); + EC_ZERO_LOG_ERR(bconchar(parent, '/'), AFPERR_MISC); + EC_ZERO_LOG_ERR(bcatcstr(parent, path), AFPERR_MISC); + EC_NEG1_LOG_ERR(i = bstrrchr(parent, '/'), AFPERR_MISC); + EC_ZERO_LOG_ERR(binsertch(parent, i, 1, 0), AFPERR_MISC); + } + + LOG(log_debug, logtype_afpd,"parent: %s", cfrombstr(parent)); + EC_ZERO_LOG_ERR(lstat(cfrombstr(parent), &st), AFPERR_MISC); + +#ifdef HAVE_NFSV4_ACLS + EC_ZERO_LOG(solaris_acl_rights(obj, cfrombstr(parent), &st, NULL, &parent_rights)); +#endif +#ifdef HAVE_POSIX_ACLS + EC_ZERO_LOG(posix_acl_rights(obj, path, &st, &parent_rights)); +#endif + if (parent_rights & (DARWIN_ACE_WRITE_DATA | DARWIN_ACE_DELETE_CHILD)) + allowed_rights |= DARWIN_ACE_DELETE; /* man, that was a lot of work! */ + } + + if (is_dir) { + /* Without DARWIN_ACE_DELETE set OS X 10.6 refuses to rename subdirectories in a + * directory. + */ + if (allowed_rights & DARWIN_ACE_ADD_SUBDIRECTORY) + allowed_rights |= DARWIN_ACE_DELETE; + + curdir->d_rights_cache = allowed_rights; + } + LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights); + } + + if ((requested_rights & allowed_rights) != requested_rights) { + LOG(log_debug, logtype_afpd, "some requested right wasn't allowed: 0x%08x / 0x%08x", + requested_rights, allowed_rights); + EC_STATUS(AFPERR_ACCESS); + } else { + LOG(log_debug, logtype_afpd, "all requested rights are allowed: 0x%08x", + requested_rights); + EC_STATUS(AFP_OK); + } + +EC_CLEANUP: + if (username) free(username); + if (parent) bdestroy(parent); + + EC_EXIT; +} + +/******************************************************** + * Interface + ********************************************************/ + +int afp_access(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + int ret; + struct vol *vol; + struct dir *dir; + uint32_t did, darwin_ace_rights; + uint16_t vid; + struct path *s_path; + uuidp_t uuid; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof(vid); + if (NULL == ( vol = getvolbyvid( vid ))) { + LOG(log_error, logtype_afpd, "afp_access: error getting volid:%d", vid); + return AFPERR_NOOBJ; + } + + memcpy(&did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did ))) { + LOG(log_error, logtype_afpd, "afp_access: error getting did:%d", did); + return afp_errno; + } + + /* Skip bitmap */ + ibuf += 2; + + /* Store UUID address */ + uuid = (uuidp_t)ibuf; + ibuf += UUID_BINSIZE; + + /* Store ACE rights */ + memcpy(&darwin_ace_rights, ibuf, 4); + darwin_ace_rights = ntohl(darwin_ace_rights); + ibuf += 4; + + /* get full path and handle file/dir subtleties in netatalk code*/ + if (NULL == ( s_path = cname( vol, dir, &ibuf ))) { + LOG(log_error, logtype_afpd, "afp_getacl: cname got an error!"); + return AFPERR_NOOBJ; + } + if (!s_path->st_valid) + of_statdir(vol, s_path); + if ( s_path->st_errno != 0 ) { + LOG(log_error, logtype_afpd, "afp_getacl: cant stat"); + return AFPERR_NOOBJ; + } + + ret = check_acl_access(obj, vol, dir, s_path->u_name, uuid, darwin_ace_rights); + + return ret; +} + +int afp_getacl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + int ret; + uint32_t did; + uint16_t vid, bitmap; + struct path *s_path; + struct passwd *pw; + struct group *gr; + + LOG(log_debug9, logtype_afpd, "afp_getacl: BEGIN"); + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof(vid); + if (NULL == ( vol = getvolbyvid( vid ))) { + LOG(log_error, logtype_afpd, "afp_getacl: error getting volid:%d", vid); + return AFPERR_NOOBJ; + } + + memcpy(&did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did ))) { + LOG(log_error, logtype_afpd, "afp_getacl: error getting did:%d", did); + return afp_errno; + } + + memcpy(&bitmap, ibuf, sizeof( bitmap )); + memcpy(rbuf, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + rbuf += sizeof( bitmap ); + *rbuflen += sizeof( bitmap ); + + /* skip maxreplysize */ + ibuf += 4; + + /* get full path and handle file/dir subtleties in netatalk code*/ + if (NULL == ( s_path = cname( vol, dir, &ibuf ))) { + LOG(log_error, logtype_afpd, "afp_getacl: cname got an error!"); + return AFPERR_NOOBJ; + } + if (!s_path->st_valid) + of_statdir(vol, s_path); + if ( s_path->st_errno != 0 ) { + LOG(log_error, logtype_afpd, "afp_getacl: cant stat"); + return AFPERR_NOOBJ; + } + + /* Shall we return owner UUID ? */ + if (bitmap & kFileSec_UUID) { + LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner user UUID"); + if (NULL == (pw = getpwuid(s_path->st.st_uid))) { + LOG(log_debug, logtype_afpd, "afp_getacl: local uid: %u", s_path->st.st_uid); + localuuid_from_id((unsigned char *)rbuf, UUID_USER, s_path->st.st_uid); + } else { + LOG(log_debug, logtype_afpd, "afp_getacl: got uid: %d, name: %s", s_path->st.st_uid, pw->pw_name); + if ((ret = getuuidfromname(pw->pw_name, UUID_USER, (unsigned char *)rbuf)) != 0) + return AFPERR_MISC; + } + rbuf += UUID_BINSIZE; + *rbuflen += UUID_BINSIZE; + } + + /* Shall we return group UUID ? */ + if (bitmap & kFileSec_GRPUUID) { + LOG(log_debug, logtype_afpd, "afp_getacl: client requested files owner group UUID"); + if (NULL == (gr = getgrgid(s_path->st.st_gid))) { + LOG(log_debug, logtype_afpd, "afp_getacl: local gid: %u", s_path->st.st_gid); + localuuid_from_id((unsigned char *)rbuf, UUID_GROUP, s_path->st.st_gid); + } else { + LOG(log_debug, logtype_afpd, "afp_getacl: got gid: %d, name: %s", s_path->st.st_gid, gr->gr_name); + if ((ret = getuuidfromname(gr->gr_name, UUID_GROUP, (unsigned char *)rbuf)) != 0) + return AFPERR_MISC; + } + rbuf += UUID_BINSIZE; + *rbuflen += UUID_BINSIZE; + } + + /* Shall we return ACL ? */ + if (bitmap & kFileSec_ACL) { + LOG(log_debug, logtype_afpd, "afp_getacl: client requested files ACL"); + if (get_and_map_acl(s_path->u_name, rbuf, rbuflen) != 0) { + LOG(log_error, logtype_afpd, "afp_getacl(\"%s/%s\"): mapping error", + getcwdpath(), s_path->u_name); + return AFPERR_MISC; + } + } + + LOG(log_debug9, logtype_afpd, "afp_getacl: END"); + return AFP_OK; +} + +int afp_setacl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + int ret; + uint32_t did; + uint16_t vid, bitmap; + struct path *s_path; + + LOG(log_debug9, logtype_afpd, "afp_setacl: BEGIN"); + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof(vid); + if (NULL == ( vol = getvolbyvid( vid ))) { + LOG(log_error, logtype_afpd, "afp_setacl: error getting volid:%d", vid); + return AFPERR_NOOBJ; + } + + memcpy(&did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did ))) { + LOG(log_error, logtype_afpd, "afp_setacl: error getting did:%d", did); + return afp_errno; + } + + memcpy(&bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + + /* get full path and handle file/dir subtleties in netatalk code*/ + if (NULL == ( s_path = cname( vol, dir, &ibuf ))) { + LOG(log_error, logtype_afpd, "afp_setacl: cname got an error!"); + return AFPERR_NOOBJ; + } + if (!s_path->st_valid) + of_statdir(vol, s_path); + if ( s_path->st_errno != 0 ) { + LOG(log_error, logtype_afpd, "afp_setacl: cant stat"); + return AFPERR_NOOBJ; + } + LOG(log_debug, logtype_afpd, "afp_setacl: unixname: %s", s_path->u_name); + + /* Padding? */ + if ((unsigned long)ibuf & 1) + ibuf++; + + /* Start processing request */ + + /* Change owner: dont even try */ + if (bitmap & kFileSec_UUID) { + LOG(log_debug, logtype_afpd, + "afp_setacl(\"%s\"): ignoring change owner request", + fullpathname(s_path->u_name)); + ret = AFP_OK; + ibuf += UUID_BINSIZE; + } + + /* Change group: certain changes might be allowed, so try it. FIXME: not implemented yet. */ + if (bitmap & kFileSec_UUID) { + LOG(log_debug, logtype_afpd, + "afp_setacl(\"%s\"): ignoring change group request", + fullpathname(s_path->u_name)); + ret = AFP_OK; + ibuf += UUID_BINSIZE; + } + + /* Remove ACL ? */ + if (bitmap & kFileSec_REMOVEACL) { + LOG(log_debug, logtype_afpd, "afp_setacl: Remove ACL request."); + if ((ret = remove_acl(vol, s_path->u_name, S_ISDIR(s_path->st.st_mode))) != AFP_OK) + LOG(log_error, logtype_afpd, "afp_setacl: error from remove_acl"); + } + + /* Change ACL ? */ + if (bitmap & kFileSec_ACL) { + LOG(log_debug, logtype_afpd, "afp_setacl: Change ACL request."); + /* Get no of ACEs the client put on the wire */ + uint32_t ace_count; + memcpy(&ace_count, ibuf, sizeof(uint32_t)); + ace_count = htonl(ace_count); + ibuf += 8; /* skip ACL flags (see acls.h) */ + + ret = set_acl(vol, + s_path->u_name, + (bitmap & kFileSec_Inherit), + (darwin_ace_t *)ibuf, + ace_count); + if (ret == 0) + ret = AFP_OK; + else { + LOG(log_warning, logtype_afpd, "afp_setacl(\"%s/%s\"): error", + getcwdpath(), s_path->u_name); + ret = AFPERR_MISC; + } + } + + LOG(log_debug9, logtype_afpd, "afp_setacl: END"); + return ret; +} + +/******************************************************************** + * ACL funcs interfacing with other parts + ********************************************************************/ + +/*! + * map ACL to user maccess + * + * This is the magic function that makes ACLs usable by calculating + * the access granted by ACEs to the logged in user. + */ +int acltoownermode(const AFPObj *obj, const struct vol *vol, char *path, struct stat *st, struct maccess *ma) +{ + EC_INIT; + + if ( ! (obj->options.flags & (OPTION_ACL2MACCESS | OPTION_ACL2MODE)) + || ! (vol->v_flags & AFPVOL_ACLS)) + return 0; + + LOG(log_maxdebug, logtype_afpd, "acltoownermode(\"%s/%s\", 0x%02x)", + getcwdpath(), path, ma->ma_user); + +#ifdef HAVE_NFSV4_ACLS + EC_ZERO_LOG(solaris_acl_rights(obj, path, st, ma, NULL)); +#endif + +#ifdef HAVE_POSIX_ACLS + ret = posix_acls_to_uaperms(obj, path, st, ma); + if (ret != 0) { + EC_FAIL; + } +#endif + + LOG(log_maxdebug, logtype_afpd, "resulting user maccess: 0x%02x group maccess: 0x%02x", ma->ma_user, ma->ma_group); + +EC_CLEANUP: + EC_EXIT; +} diff --git a/etc/afpd/acls.h b/etc/afpd/acls.h new file mode 100644 index 0000000..4d423af --- /dev/null +++ b/etc/afpd/acls.h @@ -0,0 +1,120 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. + */ + +#ifndef AFPD_ACLS_H +#define AFPD_ACLS_H + +#ifdef HAVE_SOLARIS_ACLS +#include +#endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif + +#include /* for atalk_uuid_t */ + +/* + * This is what Apple says about ACL flags in sys/kauth.h: + * + * The low 16 bits of the flags field are reserved for filesystem + * internal use and must be preserved by all APIs. This includes + * round-tripping flags through user-space interfaces. + * The high 16 bits of the flags are used to store attributes and + * to request specific handling of the ACL. + * + * The constants are included for reference. We DONT expect them on + * the wire! We will ignore and spoil em. + */ + +#ifdef HAVE_NFSV4_ACLS +/* Some stuff for the handling of NFSv4 ACLs */ +#define ACE_TRIVIAL (ACE_OWNER | ACE_GROUP | ACE_EVERYONE) +#endif /* HAVE_NFSV4_ACLS */ + +/* FPGet|Set Bitmap */ +enum { + kFileSec_UUID = (1<<0), + kFileSec_GRPUUID = (1<<1), + kFileSec_ACL = (1<<2), + kFileSec_REMOVEACL = (1<<3), + kFileSec_Inherit = (1<<4) +}; + +/* ACL Flags */ +#define DARWIN_ACL_FLAGS_PRIVATE (0xffff) +/* inheritance will be deferred until the first rename operation */ +#define KAUTH_ACL_DEFER_INHERIT (1<<16) +/* this ACL must not be overwritten as part of an inheritance operation */ +#define KAUTH_ACL_NO_INHERIT (1<<17) + +/* ACE Flags */ +#define DARWIN_ACE_FLAGS_KINDMASK 0xf +#define DARWIN_ACE_FLAGS_PERMIT (1<<0) /* 0x00000001 */ +#define DARWIN_ACE_FLAGS_DENY (1<<1) /* 0x00000002 */ +#define DARWIN_ACE_FLAGS_INHERITED (1<<4) /* 0x00000010 */ +#define DARWIN_ACE_FLAGS_FILE_INHERIT (1<<5) /* 0x00000020 */ +#define DARWIN_ACE_FLAGS_DIRECTORY_INHERIT (1<<6) /* 0x00000040 */ +#define DARWIN_ACE_FLAGS_LIMIT_INHERIT (1<<7) /* 0x00000080 */ +#define DARWIN_ACE_FLAGS_ONLY_INHERIT (1<<8) /* 0x00000100 */ + +/* All flag bits controlling ACE inheritance */ +#define DARWIN_ACE_INHERIT_CONTROL_FLAGS \ + (DARWIN_ACE_FLAGS_FILE_INHERIT |\ + DARWIN_ACE_FLAGS_DIRECTORY_INHERIT |\ + DARWIN_ACE_FLAGS_LIMIT_INHERIT |\ + DARWIN_ACE_FLAGS_ONLY_INHERIT) + +/* ACE Rights */ +#define DARWIN_ACE_READ_DATA 0x00000002 +#define DARWIN_ACE_LIST_DIRECTORY 0x00000002 +#define DARWIN_ACE_WRITE_DATA 0x00000004 +#define DARWIN_ACE_ADD_FILE 0x00000004 +#define DARWIN_ACE_EXECUTE 0x00000008 +#define DARWIN_ACE_SEARCH 0x00000008 +#define DARWIN_ACE_DELETE 0x00000010 +#define DARWIN_ACE_APPEND_DATA 0x00000020 +#define DARWIN_ACE_ADD_SUBDIRECTORY 0x00000020 +#define DARWIN_ACE_DELETE_CHILD 0x00000040 +#define DARWIN_ACE_READ_ATTRIBUTES 0x00000080 +#define DARWIN_ACE_WRITE_ATTRIBUTES 0x00000100 +#define DARWIN_ACE_READ_EXTATTRIBUTES 0x00000200 +#define DARWIN_ACE_WRITE_EXTATTRIBUTES 0x00000400 +#define DARWIN_ACE_READ_SECURITY 0x00000800 +#define DARWIN_ACE_WRITE_SECURITY 0x00001000 +#define DARWIN_ACE_TAKE_OWNERSHIP 0x00002000 + +/* Access Control List Entry (ACE) */ +typedef struct { + atalk_uuid_t darwin_ace_uuid; + uint32_t darwin_ace_flags; + uint32_t darwin_ace_rights; +} darwin_ace_t; + +/* Access Control List */ +typedef struct { + uint32_t darwin_acl_count; + uint32_t darwin_acl_flags; +} darwin_acl_header_t; + +/* FP functions */ +int afp_access (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getacl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setacl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +/* Parse afp.conf */ +extern int acl_ldap_readconfig(char *name); + +/* Misc funcs */ +extern int acltoownermode(const AFPObj *obj, const struct vol *vol, char *path, struct stat *st, struct maccess *ma); +#endif diff --git a/etc/afpd/afp_config.c b/etc/afpd/afp_config.c new file mode 100644 index 0000000..2082a31 --- /dev/null +++ b/etc/afpd/afp_config.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_GETIFADDRS +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LDAP +#include +#endif + +#include "afp_config.h" +#include "uam_auth.h" +#include "status.h" +#include "volume.h" + +/*! + * Free and cleanup config and DSI + * + * "dsi" can be NULL in which case all DSI objects and the config object is freed, + * otherwise its an afpd session child and only any unneeded DSI objects are freed + */ +void configfree(AFPObj *obj, DSI *dsi) +{ + DSI *p, *q; + + if (!dsi) { + /* Master afpd reloading config */ + auth_unload(); + } + + unload_volumes(obj); + + /* Master and child releasing unneeded DSI handles */ + for (p = obj->dsi; p; p = q) { + q = p->next; + if (p == dsi) + continue; + dsi_free(p); + free(p); + } + obj->dsi = NULL; + + /* afpd session child passes dsi handle to obj handle */ + if (dsi) { + dsi->next = NULL; + obj->dsi = dsi; + } +} + +/*! + * Get everything running + */ +int configinit(AFPObj *obj) +{ + EC_INIT; + DSI *dsi = NULL; + DSI **next = &obj->dsi; + char *p = NULL, *q = NULL, *savep; + const char *r; + struct ifaddrs *ifaddr, *ifa; + int family, s; + static char interfaddr[NI_MAXHOST]; + + auth_load(obj, obj->options.uampath, obj->options.uamlist); + set_signature(&obj->options); +#ifdef HAVE_LDAP + acl_ldap_freeconfig(); +#endif /* HAVE_LDAP */ + + LOG(log_debug, logtype_afpd, "DSIConfigInit: hostname: %s, listen: %s, interfaces: %s, port: %s", + obj->options.hostname, + obj->options.listen ? obj->options.listen : "-", + obj->options.interfaces ? obj->options.interfaces : "-", + obj->options.port); + + /* + * Setup addresses we listen on from hostname and/or "afp listen" option + */ + if (obj->options.listen) { + EC_NULL( q = p = strdup(obj->options.listen) ); + EC_NULL( p = strtok_r(p, ", ", &savep) ); + while (p) { + if ((dsi = dsi_init(obj, obj->options.hostname, p, obj->options.port)) == NULL) + break; + + status_init(obj, dsi); + *next = dsi; + next = &dsi->next; + dsi->AFPobj = obj; + + LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d", + getip_string((struct sockaddr *)&dsi->server), + getip_port((struct sockaddr *)&dsi->server)); + + p = strtok_r(NULL, ", ", &savep); + } + if (q) { + free(q); + q = NULL; + } + } + + /* + * Setup addresses we listen on from "afp interfaces". + * We use getifaddrs() instead of if_nameindex() because the latter appears still + * to be unable to return ipv4 addresses + */ + if (obj->options.interfaces) { +#ifndef HAVE_GETIFADDRS + LOG(log_error, logtype_afpd, "option \"afp interfaces\" not supported"); +#else + if (getifaddrs(&ifaddr) == -1) { + LOG(log_error, logtype_afpd, "getinterfaddr: getifaddrs() failed: %s", strerror(errno)); + EC_FAIL; + } + + EC_NULL( q = p = strdup(obj->options.interfaces) ); + EC_NULL( p = strtok_r(p, ", ", &savep) ); + while (p) { + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; + if (STRCMP(ifa->ifa_name, !=, p)) + continue; + + family = ifa->ifa_addr->sa_family; + if (family == AF_INET || family == AF_INET6) { + if (getnameinfo(ifa->ifa_addr, + (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), + interfaddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0) { + LOG(log_error, logtype_afpd, "getinterfaddr: getnameinfo() failed %s", gai_strerror(errno)); + continue; + } + + if ((dsi = dsi_init(obj, obj->options.hostname, interfaddr, obj->options.port)) == NULL) + continue; + + status_init(obj, dsi); + *next = dsi; + next = &dsi->next; + dsi->AFPobj = obj; + + LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on interface %s with address %s:%d", + p, + getip_string((struct sockaddr *)&dsi->server), + getip_port((struct sockaddr *)&dsi->server)); + } /* if (family == AF_INET || family == AF_INET6) */ + } /* for (ifa != NULL) */ + p = strtok_r(NULL, ", ", &savep); + } + freeifaddrs(ifaddr); +#endif + } + + /* + * Check whether we got a valid DSI from options.listen or options.interfaces, + * if not add a DSI that accepts all connections and goes though the list of + * network interaces for determining an IP we can advertise in DSIStatus + */ + if (dsi == NULL) { + if ((dsi = dsi_init(obj, obj->options.hostname, NULL, obj->options.port)) == NULL) + EC_FAIL_LOG("no suitable network address found, use \"afp listen\" or \"afp interfaces\"", 0); + status_init(obj, dsi); + *next = dsi; + next = &dsi->next; + dsi->AFPobj = obj; + + LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d", + getip_string((struct sockaddr *)&dsi->server), + getip_port((struct sockaddr *)&dsi->server)); + } + +#ifdef HAVE_LDAP + /* Parse afp.conf */ + acl_ldap_readconfig(obj->iniconfig); +#endif /* HAVE_LDAP */ + + if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce listener", NULL))) { + LOG(log_note, logtype_afpd, "Adding FCE listener: %s", r); + fce_add_udp_socket(r); + } + if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce coalesce", NULL))) { + LOG(log_note, logtype_afpd, "Fce coalesce: %s", r); + fce_set_coalesce(r); + } + if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce events", NULL))) { + LOG(log_note, logtype_afpd, "Fce events: %s", r); + fce_set_events(r); + } + r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce version", "1"); + LOG(log_debug, logtype_afpd, "Fce version: %s", r); + obj->fce_version = atoi(r); + + if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce ignore names", ".DS_Store"))) { + obj->fce_ign_names = strdup(r); + } + + if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce notify script", NULL))) { + obj->fce_notify_script = strdup(r); + } + + + +EC_CLEANUP: + if (q) + free(q); + EC_EXIT; +} diff --git a/etc/afpd/afp_config.h b/etc/afpd/afp_config.h new file mode 100644 index 0000000..bfa93c7 --- /dev/null +++ b/etc/afpd/afp_config.h @@ -0,0 +1,11 @@ +#ifndef AFPD_CONFIG_H +#define AFPD_CONFIG_H 1 + +#include +#include +#include + +extern int configinit (AFPObj *); +extern void configfree (AFPObj *, DSI *); + +#endif diff --git a/etc/afpd/afp_dsi.c b/etc/afpd/afp_dsi.c new file mode 100644 index 0000000..e3823de --- /dev/null +++ b/etc/afpd/afp_dsi.c @@ -0,0 +1,713 @@ +/* + * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + * + * modified from main.c. this handles afp over tcp. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif /* HAVE_SYS_STAT_H */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "switch.h" +#include "auth.h" +#include "fork.h" +#include "dircache.h" + +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + +/* + * We generally pass this from afp_over_dsi to all afp_* funcs, so it should already be + * available everywhere. Unfortunately some funcs (eg acltoownermode) need acces to it + * but are deeply nested in the function chain with the caller already without acces to it. + * Changing this would require adding a reference to the caller which itself might be + * called in many places (eg acltoownermode is called from accessmode). + * The only sane way out is providing a copy of it here: + */ +AFPObj *AFPobj = NULL; + +typedef struct { + uint16_t DSIreqID; + uint8_t AFPcommand; + uint32_t result; +} rc_elem_t; + +/* + * AFP replay cache: + * - fix sized array + * - indexed just by taking DSIreqID mod REPLAYCACHE_SIZE + */ +static rc_elem_t replaycache[REPLAYCACHE_SIZE]; + +static sigjmp_buf recon_jmp; +static void afp_dsi_close(AFPObj *obj) +{ + DSI *dsi = obj->dsi; + sigset_t sigs; + + close(obj->ipc_fd); + obj->ipc_fd = -1; + + /* we may have been called from a signal handler caught when afpd was running + * as uid 0, that's the wrong user for volume's prexec_close scripts if any, + * restore our login user + */ + if (geteuid() != obj->uid) { + if (seteuid( obj->uid ) < 0) { + LOG(log_error, logtype_afpd, "can't seteuid(%u) back %s: uid: %u, euid: %u", + obj->uid, strerror(errno), getuid(), geteuid()); + exit(EXITERR_SYS); + } + } + + close_all_vol(obj); + if (obj->logout) { + /* Block sigs, PAM/systemd/whoever might send us a SIG??? in (*obj->logout)() -> pam_close_session() */ + sigfillset(&sigs); + pthread_sigmask(SIG_BLOCK, &sigs, NULL); + (*obj->logout)(); + } + + LOG(log_note, logtype_afpd, "AFP statistics: %.2f KB read, %.2f KB written", + dsi->read_count/1024.0, dsi->write_count/1024.0); + log_dircache_stat(); + + dsi_close(dsi); +} + +/* ------------------------------- + * SIGTERM + * a little bit of code duplication. + */ +static void afp_dsi_die(int sig) +{ + DSI *dsi = (DSI *)AFPobj->dsi; + + if (dsi->flags & DSI_RECONINPROG) { + /* Primary reconnect succeeded, got SIGTERM from afpd parent */ + dsi->flags &= ~DSI_RECONINPROG; + return; /* this returns to afp_disconnect */ + } + + if (dsi->flags & DSI_DISCONNECTED) { + LOG(log_note, logtype_afpd, "Disconnected session terminating"); + exit(0); + } + + dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN); + afp_dsi_close(AFPobj); + if (sig) /* if no signal, assume dieing because logins are disabled & + don't log it (maintenance mode)*/ + LOG(log_info, logtype_afpd, "Connection terminated"); + if (sig == SIGTERM || sig == SIGALRM) { + exit( 0 ); + } + else { + exit(sig); + } +} + +/* SIGURG handler (primary reconnect) */ +static void afp_dsi_transfer_session(int sig _U_) +{ + uint16_t dsiID; + int socket; + DSI *dsi = (DSI *)AFPobj->dsi; + + LOG(log_debug, logtype_afpd, "afp_dsi_transfer_session: got SIGURG, trying to receive session"); + + if (readt(AFPobj->ipc_fd, &dsiID, 2, 0, 2) != 2) { + LOG(log_error, logtype_afpd, "afp_dsi_transfer_session: couldn't receive DSI id, goodbye"); + afp_dsi_close(AFPobj); + exit(EXITERR_SYS); + } + + if ((socket = recv_fd(AFPobj->ipc_fd, 1)) == -1) { + LOG(log_error, logtype_afpd, "afp_dsi_transfer_session: couldn't receive session fd, goodbye"); + afp_dsi_close(AFPobj); + exit(EXITERR_SYS); + } + + LOG(log_debug, logtype_afpd, "afp_dsi_transfer_session: received socket fd: %i", socket); + + dsi->proto_close(dsi); + dsi->socket = socket; + dsi->flags = DSI_RECONSOCKET; + dsi->datalen = 0; + dsi->eof = dsi->start = dsi->buffer; + dsi->in_write = 0; + dsi->header.dsi_requestID = dsiID; + dsi->header.dsi_command = DSIFUNC_CMD; + + /* + * The session transfer happens in the middle of FPDisconnect old session, thus we + * have to send the reply now. + */ + if (!dsi_cmdreply(dsi, AFP_OK)) { + LOG(log_error, logtype_afpd, "dsi_cmdreply: %s", strerror(errno) ); + afp_dsi_close(AFPobj); + exit(EXITERR_CLNT); + } + + LOG(log_note, logtype_afpd, "afp_dsi_transfer_session: succesfull primary reconnect"); + /* + * Now returning from this signal handler return to dsi_receive which should start + * reading/continuing from the connected socket that was passed via the parent from + * another session. The parent will terminate that session. + */ + siglongjmp(recon_jmp, 1); +} + +/* ------------------- */ +static void afp_dsi_timedown(int sig _U_) +{ + struct sigaction sv; + struct itimerval it; + DSI *dsi = (DSI *)AFPobj->dsi; + dsi->flags |= DSI_DIE; + /* shutdown and don't reconnect. server going down in 5 minutes. */ + setmessage("The server is going down for maintenance."); + if (dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT | + AFPATTN_MESG | AFPATTN_TIME(5)) < 0) { + DSI *dsi = (DSI *)AFPobj->dsi; + dsi->down_request = 1; + } + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + it.it_value.tv_sec = 300; + it.it_value.tv_usec = 0; + + if ( setitimer( ITIMER_REAL, &it, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_timedown: setitimer: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + memset(&sv, 0, sizeof(sv)); + sv.sa_handler = afp_dsi_die; + sigemptyset( &sv.sa_mask ); + sigaddset(&sv.sa_mask, SIGHUP); + sigaddset(&sv.sa_mask, SIGTERM); + sv.sa_flags = SA_RESTART; + if ( sigaction( SIGALRM, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_timedown: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + + /* ignore myself */ + sv.sa_handler = SIG_IGN; + sigemptyset( &sv.sa_mask ); + sv.sa_flags = SA_RESTART; + if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_timedown: sigaction SIGHUP: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } +} + +/* --------------------------------- + * SIGHUP reload configuration file + */ +volatile int reload_request = 0; + +static void afp_dsi_reload(int sig _U_) +{ + reload_request = 1; +} + +/* --------------------------------- + * SIGINT: enable max_debug LOGging + */ +static volatile sig_atomic_t debug_request = 0; + +static void afp_dsi_debug(int sig _U_) +{ + debug_request = 1; +} + +/* ---------------------- */ +static void afp_dsi_getmesg (int sig _U_) +{ + DSI *dsi = (DSI *)AFPobj->dsi; + + dsi->msg_request = 1; + if (dsi_attention(AFPobj->dsi, AFPATTN_MESG | AFPATTN_TIME(5)) < 0) + dsi->msg_request = 2; +} + +static void alarm_handler(int sig _U_) +{ + int err; + DSI *dsi = (DSI *)AFPobj->dsi; + + /* we have to restart the timer because some libraries may use alarm() */ + setitimer(ITIMER_REAL, &dsi->timer, NULL); + + /* we got some traffic from the client since the previous timer tick. */ + if ((dsi->flags & DSI_DATA)) { + dsi->flags &= ~DSI_DATA; + return; + } + + dsi->tickle++; + LOG(log_maxdebug, logtype_afpd, "alarm: tickles: %u, flags: %s|%s|%s|%s|%s|%s|%s|%s|%s", + dsi->tickle, + (dsi->flags & DSI_DATA) ? "DSI_DATA" : "-", + (dsi->flags & DSI_RUNNING) ? "DSI_RUNNING" : "-", + (dsi->flags & DSI_SLEEPING) ? "DSI_SLEEPING" : "-", + (dsi->flags & DSI_EXTSLEEP) ? "DSI_EXTSLEEP" : "-", + (dsi->flags & DSI_DISCONNECTED) ? "DSI_DISCONNECTED" : "-", + (dsi->flags & DSI_DIE) ? "DSI_DIE" : "-", + (dsi->flags & DSI_NOREPLY) ? "DSI_NOREPLY" : "-", + (dsi->flags & DSI_RECONSOCKET) ? "DSI_RECONSOCKET" : "-", + (dsi->flags & DSI_RECONINPROG) ? "DSI_RECONINPROG" : "-"); + + if (dsi->flags & DSI_SLEEPING) { + if (dsi->tickle > AFPobj->options.sleep) { + LOG(log_note, logtype_afpd, "afp_alarm: sleep time ended"); + afp_dsi_die(EXITERR_CLNT); + } + return; + } + + if (dsi->flags & DSI_DISCONNECTED) { + if (geteuid() == 0) { + LOG(log_note, logtype_afpd, "afp_alarm: unauthenticated user, connection problem"); + afp_dsi_die(EXITERR_CLNT); + } + if (dsi->tickle > AFPobj->options.disconnected) { + LOG(log_error, logtype_afpd, "afp_alarm: reconnect timer expired, goodbye"); + afp_dsi_die(EXITERR_CLNT); + } + return; + } + + /* if we're in the midst of processing something, don't die. */ + if (dsi->tickle >= AFPobj->options.timeout) { + LOG(log_error, logtype_afpd, "afp_alarm: child timed out, entering disconnected state"); + if (dsi_disconnect(dsi) != 0) + afp_dsi_die(EXITERR_CLNT); + return; + } + + if ((err = pollvoltime(AFPobj)) == 0) { + LOG(log_debug, logtype_afpd, "afp_alarm: sending DSI tickle"); + err = dsi_tickle(AFPobj->dsi); + } + if (err <= 0) { + if (geteuid() == 0) { + LOG(log_note, logtype_afpd, "afp_alarm: unauthenticated user, connection problem"); + afp_dsi_die(EXITERR_CLNT); + } + LOG(log_error, logtype_afpd, "afp_alarm: connection problem, entering disconnected state"); + if (dsi_disconnect(dsi) != 0) + afp_dsi_die(EXITERR_CLNT); + } +} + +static void child_handler(int sig _U_) +{ + wait(NULL); +} + +/* ----------------- + if dsi->in_write is set attention, tickle (and close?) msg + aren't sent. We don't care about tickle +*/ +static void pending_request(DSI *dsi) +{ + /* send pending attention */ + + /* read msg if any, it could be done in afp_getsrvrmesg */ + if (dsi->msg_request) { + if (dsi->msg_request == 2) { + /* didn't send it in signal handler */ + dsi_attention(AFPobj->dsi, AFPATTN_MESG | AFPATTN_TIME(5)); + } + dsi->msg_request = 0; + readmessage(AFPobj); + } + if (dsi->down_request) { + dsi->down_request = 0; + dsi_attention(AFPobj->dsi, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT | + AFPATTN_MESG | AFPATTN_TIME(5)); + } +} + +void afp_over_dsi_sighandlers(AFPObj *obj) +{ + DSI *dsi = (DSI *) obj->dsi; + struct sigaction action; + + memset(&action, 0, sizeof(action)); + sigfillset(&action.sa_mask); + action.sa_flags = SA_RESTART; + + /* install SIGHUP */ + action.sa_handler = afp_dsi_reload; + if ( sigaction( SIGHUP, &action, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + + /* install SIGURG */ + action.sa_handler = afp_dsi_transfer_session; + if ( sigaction( SIGURG, &action, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + + /* install SIGTERM */ + action.sa_handler = afp_dsi_die; + if ( sigaction( SIGTERM, &action, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + + /* install SIGQUIT */ + action.sa_handler = afp_dsi_die; + if ( sigaction(SIGQUIT, &action, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + + /* SIGUSR2 - server message support */ + action.sa_handler = afp_dsi_getmesg; + if ( sigaction( SIGUSR2, &action, NULL) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + + /* SIGUSR1 - set down in 5 minutes */ + action.sa_handler = afp_dsi_timedown; + action.sa_flags = SA_RESTART; + if ( sigaction( SIGUSR1, &action, NULL) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + + /* SIGINT - enable max_debug LOGging to /tmp/afpd.PID.XXXXXX */ + action.sa_handler = afp_dsi_debug; + if ( sigaction( SIGINT, &action, NULL) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } + +#ifndef DEBUGGING + /* SIGALRM - tickle handler */ + action.sa_handler = alarm_handler; + if ((sigaction(SIGALRM, &action, NULL) < 0) || + (setitimer(ITIMER_REAL, &dsi->timer, NULL) < 0)) { + afp_dsi_die(EXITERR_SYS); + } +#endif /* DEBUGGING */ + + /* SIGCHLD */ + action.sa_handler = child_handler; +#ifdef SA_NOCLDWAIT +/* this enhancement simplifies things for Solaris, it also improves performance */ + action.sa_flags |= SA_NOCLDWAIT; +#endif + if (sigaction(SIGCHLD, &action, NULL) < 0 ) { + LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) ); + afp_dsi_die(EXITERR_SYS); + } +} + +/* ------------------------------------------- + afp over dsi. this never returns. +*/ +void afp_over_dsi(AFPObj *obj) +{ + DSI *dsi = (DSI *) obj->dsi; + int rc_idx; + uint32_t err, cmd; + uint8_t function; + + AFPobj = obj; + obj->exit = afp_dsi_die; + obj->reply = (int (*)()) dsi_cmdreply; + obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention; + dsi->tickle = 0; + + afp_over_dsi_sighandlers(obj); + + if (dircache_init(obj->options.dircachesize) != 0) + afp_dsi_die(EXITERR_SYS); + + /* set TCP snd/rcv buf */ + if (obj->options.tcp_rcvbuf) { + if (setsockopt(dsi->socket, + SOL_SOCKET, + SO_RCVBUF, + &obj->options.tcp_rcvbuf, + sizeof(obj->options.tcp_rcvbuf)) != 0) { + LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_RCVBUF): %s", strerror(errno)); + } + } + if (obj->options.tcp_sndbuf) { + if (setsockopt(dsi->socket, + SOL_SOCKET, + SO_SNDBUF, + &obj->options.tcp_sndbuf, + sizeof(obj->options.tcp_sndbuf)) != 0) { + LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_SNDBUF): %s", strerror(errno)); + } + } + + /* set TCP_NODELAY */ + int flag = 1; + setsockopt(dsi->socket, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag)); + + ipc_child_state(obj, DSI_RUNNING); + + /* get stuck here until the end */ + while (1) { + if (sigsetjmp(recon_jmp, 1) != 0) + /* returning from SIGALARM handler for a primary reconnect */ + continue; + + /* Blocking read on the network socket */ + cmd = dsi_stream_receive(dsi); + + if (cmd == 0) { + /* cmd == 0 is the error condition */ + if (dsi->flags & DSI_RECONSOCKET) { + /* we just got a reconnect so we immediately try again to receive on the new fd */ + dsi->flags &= ~DSI_RECONSOCKET; + continue; + } + + /* the client sometimes logs out (afp_logout) but doesn't close the DSI session */ + if (dsi->flags & DSI_AFP_LOGGED_OUT) { + LOG(log_note, logtype_afpd, "afp_over_dsi: client logged out, terminating DSI session"); + afp_dsi_close(obj); + exit(0); + } + + if (dsi->flags & DSI_RECONINPROG) { + LOG(log_note, logtype_afpd, "afp_over_dsi: failed reconnect"); + afp_dsi_close(obj); + exit(0); + } + + /* Some error on the client connection, enter disconnected state */ + if (dsi_disconnect(dsi) != 0) + afp_dsi_die(EXITERR_CLNT); + + ipc_child_state(obj, DSI_DISCONNECTED); + + while (dsi->flags & DSI_DISCONNECTED) + pause(); /* gets interrupted by SIGALARM or SIGURG tickle */ + ipc_child_state(obj, DSI_RUNNING); + continue; /* continue receiving until disconnect timer expires + * or a primary reconnect succeeds */ + } + + if (!(dsi->flags & DSI_EXTSLEEP) && (dsi->flags & DSI_SLEEPING)) { + LOG(log_debug, logtype_afpd, "afp_over_dsi: got data, ending normal sleep"); + dsi->flags &= ~DSI_SLEEPING; + dsi->tickle = 0; + ipc_child_state(obj, DSI_RUNNING); + } + + if (reload_request) { + reload_request = 0; + load_volumes(AFPobj, lv_force); + } + + /* The first SIGINT enables debugging, the next restores the config */ + if (debug_request) { + static int debugging = 0; + debug_request = 0; + + dircache_dump(); + uuidcache_dump(); + + if (debugging) { + if (obj->options.logconfig) + setuplog(obj->options.logconfig, obj->options.logfile); + else + setuplog("default:note", NULL); + debugging = 0; + } else { + char logstr[50]; + debugging = 1; + sprintf(logstr, "/tmp/afpd.%u.XXXXXX", getpid()); + setuplog("default:maxdebug", logstr); + } + } + + + dsi->flags |= DSI_DATA; + dsi->tickle = 0; + + switch(cmd) { + + case DSIFUNC_CLOSE: + LOG(log_debug, logtype_afpd, "DSI: close session request"); + afp_dsi_close(obj); + LOG(log_note, logtype_afpd, "done"); + exit(0); + + case DSIFUNC_TICKLE: + dsi->flags &= ~DSI_DATA; /* thats no data in the sense we use it in alarm_handler */ + LOG(log_debug, logtype_afpd, "DSI: client tickle"); + /* timer is not every 30 seconds anymore, so we don't get killed on the client side. */ + if ((dsi->flags & DSI_DIE)) + dsi_tickle(dsi); + break; + + case DSIFUNC_CMD: +#ifdef AFS + if ( writtenfork ) { + if ( flushfork( writtenfork ) < 0 ) { + LOG(log_error, logtype_afpd, "main flushfork: %s", strerror(errno) ); + } + writtenfork = NULL; + } +#endif /* AFS */ + + function = (u_char) dsi->commands[0]; + + /* AFP replay cache */ + rc_idx = dsi->clientID % REPLAYCACHE_SIZE; + LOG(log_debug, logtype_dsi, "DSI request ID: %u", dsi->clientID); + + if (replaycache[rc_idx].DSIreqID == dsi->clientID + && replaycache[rc_idx].AFPcommand == function) { + LOG(log_note, logtype_afpd, "AFP Replay Cache match: id: %u / cmd: %s", + dsi->clientID, AfpNum2name(function)); + err = replaycache[rc_idx].result; + /* AFP replay cache end */ + } else { + /* send off an afp command. in a couple cases, we take advantage + * of the fact that we're a stream-based protocol. */ + if (afp_switch[function]) { + dsi->datalen = DSI_DATASIZ; + dsi->flags |= DSI_RUNNING; + + LOG(log_debug, logtype_afpd, "<== Start AFP command: %s", AfpNum2name(function)); + + AFP_AFPFUNC_START(function, (char *)AfpNum2name(function)); + err = (*afp_switch[function])(obj, + (char *)dsi->commands, dsi->cmdlen, + (char *)&dsi->data, &dsi->datalen); + + AFP_AFPFUNC_DONE(function, (char *)AfpNum2name(function)); + LOG(log_debug, logtype_afpd, "==> Finished AFP command: %s -> %s", + AfpNum2name(function), AfpErr2name(err)); + + dir_free_invalid_q(); + + dsi->flags &= ~DSI_RUNNING; + + /* Add result to the AFP replay cache */ + replaycache[rc_idx].DSIreqID = dsi->clientID; + replaycache[rc_idx].AFPcommand = function; + replaycache[rc_idx].result = err; + } else { + LOG(log_maxdebug, logtype_afpd, "bad function %X", function); + dsi->datalen = 0; + err = AFPERR_NOOP; + } + } + + /* single shot toggle that gets set by dsi_readinit. */ + if (dsi->flags & DSI_NOREPLY) { + dsi->flags &= ~DSI_NOREPLY; + break; + } else if (!dsi_cmdreply(dsi, err)) { + LOG(log_error, logtype_afpd, "dsi_cmdreply(%d): %s", dsi->socket, strerror(errno) ); + if (dsi_disconnect(dsi) != 0) + afp_dsi_die(EXITERR_CLNT); + } + break; + + case DSIFUNC_WRITE: /* FPWrite and FPAddIcon */ + function = (u_char) dsi->commands[0]; + if ( afp_switch[ function ] != NULL ) { + dsi->datalen = DSI_DATASIZ; + dsi->flags |= DSI_RUNNING; + + LOG(log_debug, logtype_afpd, "<== Start AFP command: %s", AfpNum2name(function)); + + AFP_AFPFUNC_START(function, (char *)AfpNum2name(function)); + + err = (*afp_switch[function])(obj, + (char *)dsi->commands, dsi->cmdlen, + (char *)&dsi->data, &dsi->datalen); + + AFP_AFPFUNC_DONE(function, (char *)AfpNum2name(function)); + + LOG(log_debug, logtype_afpd, "==> Finished AFP command: %s -> %s", + AfpNum2name(function), AfpErr2name(err)); + + dsi->flags &= ~DSI_RUNNING; + } else { + LOG(log_error, logtype_afpd, "(write) bad function %x", function); + dsi->datalen = 0; + err = AFPERR_NOOP; + } + + if (!dsi_wrtreply(dsi, err)) { + LOG(log_error, logtype_afpd, "dsi_wrtreply: %s", strerror(errno) ); + if (dsi_disconnect(dsi) != 0) + afp_dsi_die(EXITERR_CLNT); + } + break; + + case DSIFUNC_ATTN: /* attention replies */ + break; + + /* error. this usually implies a mismatch of some kind + * between server and client. if things are correct, + * we need to flush the rest of the packet if necessary. */ + default: + LOG(log_info, logtype_afpd,"afp_dsi: spurious command %d", cmd); + dsi_writeinit(dsi, dsi->data, DSI_DATASIZ); + dsi_writeflush(dsi); + break; + } + pending_request(dsi); + + fce_pending_events(obj); + } + + /* error */ + afp_dsi_die(EXITERR_CLNT); +} diff --git a/etc/afpd/afp_options.c b/etc/afpd/afp_options.c new file mode 100644 index 0000000..95faf80 --- /dev/null +++ b/etc/afpd/afp_options.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + * + * modified from main.c. this handles afp options. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_NETDB_H +#include +#endif /* HAVE_NETDB_H */ + +#ifdef ADMIN_GRP +#include +#include +#endif /* ADMIN_GRP */ + +#include +#include +#include +#include +#include +#include + +#include "status.h" +#include "auth.h" +#include "dircache.h" + +#define LENGTH 512 + +/* + * Show version information about afpd. + * Used by "afp -v". + */ +static void show_version( void ) +{ + int num, i; + + printf( "afpd %s - Apple Filing Protocol (AFP) daemon of Netatalk\n\n", VERSION ); + + puts( "This program is free software; you can redistribute it and/or modify it under" ); + puts( "the terms of the GNU General Public License as published by the Free Software" ); + puts( "Foundation; either version 2 of the License, or (at your option) any later" ); + puts( "version. Please see the file COPYING for further information and details.\n" ); + + puts( "afpd has been compiled with support for these features:\n" ); + + num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] ); + printf( " AFP versions:\t" ); + for ( i = 0; i < num; i++ ) { + printf( "%d.%d ", afp_versions[ i ].av_number/10, afp_versions[ i ].av_number%10); + } + puts( "" ); + + printf( " CNID backends:\t" ); +#ifdef CNID_BACKEND_CDB + printf( "cdb "); +#endif +#ifdef CNID_BACKEND_DB3 + printf( "db3 " ); +#endif +#ifdef CNID_BACKEND_DBD +#ifdef CNID_BACKEND_DBD_TXN + printf( "dbd-txn " ); +#else + printf( "dbd " ); +#endif +#endif +#ifdef CNID_BACKEND_HASH + printf( "hash " ); +#endif +#ifdef CNID_BACKEND_LAST + printf( "last " ); +#endif +#ifdef CNID_BACKEND_MTAB + printf( "mtab " ); +#endif +#ifdef CNID_BACKEND_TDB + printf( "tdb " ); +#endif +#ifdef CNID_BACKEND_MYSQL + printf( "mysql " ); +#endif + puts( "" ); +} + +/* + * Show extended version information about afpd and Netatalk. + * Used by "afp -V". + */ +static void show_version_extended(void ) +{ + show_version( ); + + printf( " Zeroconf support:\t" ); +#if defined (HAVE_MDNS) + puts( "mDNSResponder" ); +#elif defined (HAVE_AVAHI) + puts( "Avahi" ); +#else + puts( "No" ); +#endif + + printf( " TCP wrappers support:\t" ); +#ifdef TCPWRAP + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " Quota support:\t" ); +#ifndef NO_QUOTA_SUPPORT + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " Admin group support:\t" ); +#ifdef ADMIN_GRP + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " Valid shell checks:\t" ); +#ifndef DISABLE_SHELLCHECK + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " cracklib support:\t" ); +#ifdef USE_CRACKLIB + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " EA support:\t" ); + puts( EA_MODULES ); + + printf( " ACL support:\t" ); +#ifdef HAVE_ACLS + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " LDAP support:\t" ); +#ifdef HAVE_LDAP + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " D-Bus support:\t" ); +#ifdef HAVE_DBUS_GLIB + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " Spotlight support:\t" ); +#ifdef HAVE_TRACKER + puts( "Yes" ); +#else + puts( "No" ); +#endif + + printf( " DTrace probes:\t" ); +#ifdef WITH_DTRACE + puts( "Yes" ); +#else + puts( "No" ); +#endif +} + +/* + * Display compiled-in default paths + */ +static void show_paths( void ) +{ + printf( " afp.conf:\t%s\n", _PATH_CONFDIR "afp.conf"); + printf( " extmap.conf:\t%s\n", _PATH_CONFDIR "extmap.conf"); + printf( " state directory:\t%s\n", _PATH_STATEDIR); + printf( " afp_signature.conf:\t%s\n", _PATH_STATEDIR "afp_signature.conf"); + printf( " afp_voluuid.conf:\t%s\n", _PATH_STATEDIR "afp_voluuid.conf"); + printf( " UAM search path:\t%s\n", _PATH_AFPDUAMPATH ); + printf( " Server messages path:\t%s\n", SERVERTEXT); +} + +/* + * Display usage information about afpd. + */ +static void show_usage(void) +{ + fprintf( stderr, "Usage:\tafpd [-d] [-F configfile]\n"); + fprintf( stderr, "\tafpd -h|-v|-V\n"); +} + +void afp_options_parse_cmdline(AFPObj *obj, int ac, char **av) +{ + int c, err = 0; + + while (EOF != ( c = getopt( ac, av, "dF:vVh" )) ) { + switch ( c ) { + case 'd': + obj->cmdlineflags |= OPTION_DEBUG; + break; + case 'F': + obj->cmdlineconfigfile = strdup(optarg); + break; + case 'v': /* version */ + show_version( ); puts( "" ); + show_paths( ); puts( "" ); + exit( 0 ); + break; + case 'V': /* extended version */ + show_version_extended( ); puts( "" ); + show_paths( ); puts( "" ); + exit( 0 ); + break; + case 'h': /* usage */ + show_usage(); + exit( 0 ); + break; + default : + err++; + } + } + if ( err || optind != ac ) { + show_usage(); + exit( 2 ); + } + + return; +} diff --git a/etc/afpd/afp_util.c b/etc/afpd/afp_util.c new file mode 100644 index 0000000..b7bc00f --- /dev/null +++ b/etc/afpd/afp_util.c @@ -0,0 +1,160 @@ +/* + * + * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + * + * Copyright (c) 2002 netatalk + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +const char *AfpNum2name(int num) +{ + switch(num) { + case AFP_BYTELOCK : return "AFP_BYTELOCK"; /* 1 */ + case AFP_CLOSEVOL : return "AFP_CLOSEVOL"; /* 2 */ + case AFP_CLOSEDIR : return "AFP_CLOSEDIR"; /* 3 */ + case AFP_CLOSEFORK : return "AFP_CLOSEFORK"; /* 4 */ + case AFP_COPYFILE : return "AFP_COPYFILE"; /* 5 */ + case AFP_CREATEDIR : return "AFP_CREATEDIR"; /* 6 */ + case AFP_CREATEFILE : return "AFP_CREATEFILE"; /* 7 */ + case AFP_DELETE : return "AFP_DELETE"; /* 8 */ + case AFP_ENUMERATE : return "AFP_ENUMERATE"; /* 9 */ + case AFP_FLUSH : return "AFP_FLUSH"; /* 10 */ + case AFP_FLUSHFORK : return "AFP_FLUSHFORK"; /* 11 */ + + case AFP_GETFORKPARAM : return "AFP_GETFORKPARAM"; /* 14 */ + case AFP_GETSRVINFO : return "AFP_GETSRVINFO"; /* 15 */ + case AFP_GETSRVPARAM : return "AFP_GETSRVPARAM"; /* 16 */ + case AFP_GETVOLPARAM : return "AFP_GETVOLPARAM"; /* 17 */ + case AFP_LOGIN : return "AFP_LOGIN"; /* 18 */ + case AFP_LOGINCONT : return "AFP_LOGINCONT"; /* 19 */ + case AFP_LOGOUT : return "AFP_LOGOUT"; /* 20 */ + case AFP_MAPID : return "AFP_MAPID"; /* 21 */ + case AFP_MAPNAME : return "AFP_MAPNAME"; /* 22 */ + case AFP_MOVE : return "AFP_MOVE"; /* 23 */ + case AFP_OPENVOL : return "AFP_OPENVOL"; /* 24 */ + case AFP_OPENDIR : return "AFP_OPENDIR"; /* 25 */ + case AFP_OPENFORK : return "AFP_OPENFORK"; /* 26 */ + case AFP_READ : return "AFP_READ"; /* 27 */ + case AFP_RENAME : return "AFP_RENAME"; /* 28 */ + case AFP_SETDIRPARAM : return "AFP_SETDIRPARAM"; /* 29 */ + case AFP_SETFILEPARAM : return "AFP_SETFILEPARAM"; /* 30 */ + case AFP_SETFORKPARAM : return "AFP_SETFORKPARAM"; /* 31 */ + case AFP_SETVOLPARAM : return "AFP_SETVOLPARAM "; /* 32 */ + case AFP_WRITE : return "AFP_WRITE"; /* 33 */ + case AFP_GETFLDRPARAM : return "AFP_GETFLDRPARAM"; /* 34 */ + case AFP_SETFLDRPARAM : return "AFP_SETFLDRPARAM"; /* 35 */ + case AFP_CHANGEPW : return "AFP_CHANGEPW"; /* 36 */ + case AFP_GETUSERINFO : return "AFP_GETUSERINFO"; /* 37 */ + case AFP_GETSRVRMSG : return "AFP_GETSRVRMSG"; /* 38 */ + case AFP_CREATEID : return "AFP_CREATEID"; /* 39 */ + case AFP_DELETEID : return "AFP_DELETEID"; /* 40 */ + case AFP_RESOLVEID : return "AFP_RESOLVEID"; /* 41 */ + case AFP_EXCHANGEFILE : return "AFP_EXCHANGEFILE"; /* 42 */ + case AFP_CATSEARCH : return "AFP_CATSEARCH"; /* 43 */ + + case AFP_OPENDT : return "AFP_OPENDT"; /* 48 */ + case AFP_CLOSEDT : return "AFP_CLOSEDT"; /* 49 */ + case AFP_GETICON : return "AFP_GETICON"; /* 51 */ + case AFP_GTICNINFO : return "AFP_GTICNINFO"; /* 52 */ + case AFP_ADDAPPL : return "AFP_ADDAPPL"; /* 53 */ + case AFP_RMVAPPL : return "AFP_RMVAPPL"; /* 54 */ + case AFP_GETAPPL : return "AFP_GETAPPL"; /* 55 */ + case AFP_ADDCMT : return "AFP_ADDCMT"; /* 56 */ + case AFP_RMVCMT : return "AFP_RMVCMT"; /* 57 */ + case AFP_GETCMT : return "AFP_GETCMT"; /* 58 */ + case AFP_ADDICON : return "AFP_ADDICON"; /* 192 */ + /* version 3.0 */ + case AFP_BYTELOCK_EXT : return "AFP_BYTELOCK_EXT"; /* 59 */ + case AFP_READ_EXT : return "AFP_READ_EXT"; /* 60 */ + case AFP_WRITE_EXT : return "AFP_WRITE_EXT"; /* 61 */ + case AFP_GETSESSTOKEN : return "AFP_GETSESSTOKEN"; /* 64 */ + case AFP_LOGIN_EXT : return "AFP_LOGIN_EXT"; /* 63 */ + case AFP_DISCTOLDSESS : return "AFP_DISCTOLDSESS"; /* 65 */ + case AFP_ENUMERATE_EXT : return "AFP_ENUMERATE_EXT"; /* 66 */ + case AFP_CATSEARCH_EXT : return "AFP_CATSEARCH_EXT"; /* 67 */ + /* version 3.1 */ + case AFP_ENUMERATE_EXT2: return "AFP_ENUMERATE_EXT2"; /* 68 */ + case AFP_ZZZ : return "AFP_ZZZ"; /* 122 */ + /* version 3.2 */ + case AFP_GETEXTATTR : return "AFP_GETEXTATTR"; /* 69 */ + case AFP_SETEXTATTR : return "AFP_SETEXTATTR"; /* 70 */ + case AFP_REMOVEATTR : return "AFP_REMOVEATTR"; /* 71 */ + case AFP_LISTEXTATTR : return "AFP_LISTEXTATTR"; /* 72 */ + case AFP_GETACL : return "AFP_GETACL"; /* 73 */ + case AFP_SETACL : return "AFP_SETACL"; /* 74 */ + case AFP_ACCESS : return "AFP_ACCESS"; /* 75 */ + case AFP_SPOTLIGHT_PRIVATE : return "AFP_SPOTLIGHT_PRIVATE"; /* 76 */ + case AFP_SYNCDIR : return "AFP_SYNCDIR"; /* 78 */ + case AFP_SYNCFORK : return "AFP_SYNCFORK"; /* 79 */ + } + return "not yet defined"; +} + +#define AFPERR2NAME(err) case err : return #err + +const char *AfpErr2name(int err) +{ + switch (err) { + AFPERR2NAME(AFP_OK); + AFPERR2NAME(AFPERR_DID1); + AFPERR2NAME(AFPERR_ACCESS); + AFPERR2NAME(AFPERR_AUTHCONT); + AFPERR2NAME(AFPERR_BADUAM); + AFPERR2NAME(AFPERR_BADVERS); + AFPERR2NAME(AFPERR_BITMAP); + AFPERR2NAME(AFPERR_CANTMOVE); + AFPERR2NAME(AFPERR_DENYCONF); + AFPERR2NAME(AFPERR_DIRNEMPT); + AFPERR2NAME(AFPERR_DFULL); + AFPERR2NAME(AFPERR_EOF); + AFPERR2NAME(AFPERR_BUSY); + AFPERR2NAME(AFPERR_FLATVOL); + AFPERR2NAME(AFPERR_NOITEM); + AFPERR2NAME(AFPERR_LOCK); + AFPERR2NAME(AFPERR_MISC); + AFPERR2NAME(AFPERR_NLOCK); + AFPERR2NAME(AFPERR_NOSRVR); + AFPERR2NAME(AFPERR_EXIST); + AFPERR2NAME(AFPERR_NOOBJ); + AFPERR2NAME(AFPERR_PARAM); + AFPERR2NAME(AFPERR_NORANGE); + AFPERR2NAME(AFPERR_RANGEOVR); + AFPERR2NAME(AFPERR_SESSCLOS); + AFPERR2NAME(AFPERR_NOTAUTH); + AFPERR2NAME(AFPERR_NOOP); + AFPERR2NAME(AFPERR_BADTYPE); + AFPERR2NAME(AFPERR_NFILE); + AFPERR2NAME(AFPERR_SHUTDOWN); + AFPERR2NAME(AFPERR_NORENAME); + AFPERR2NAME(AFPERR_NODIR); + AFPERR2NAME(AFPERR_ITYPE); + AFPERR2NAME(AFPERR_VLOCK); + AFPERR2NAME(AFPERR_OLOCK); + AFPERR2NAME(AFPERR_CTNSHRD); + AFPERR2NAME(AFPERR_NOID); + AFPERR2NAME(AFPERR_EXISTID); + AFPERR2NAME(AFPERR_DIFFVOL); + AFPERR2NAME(AFPERR_CATCHNG); + AFPERR2NAME(AFPERR_SAMEOBJ); + AFPERR2NAME(AFPERR_BADID); + AFPERR2NAME(AFPERR_PWDSAME); + AFPERR2NAME(AFPERR_PWDSHORT); + AFPERR2NAME(AFPERR_PWDEXPR); + AFPERR2NAME(AFPERR_INSHRD); + AFPERR2NAME(AFPERR_INTRASH); + AFPERR2NAME(AFPERR_PWDCHNG); + AFPERR2NAME(AFPERR_PWDPOLCY); + AFPERR2NAME(AFPERR_USRLOGIN); + } + return "not yet defined"; +} diff --git a/etc/afpd/afprun.c b/etc/afpd/afprun.c new file mode 100644 index 0000000..ed41247 --- /dev/null +++ b/etc/afpd/afprun.c @@ -0,0 +1,320 @@ +/* + Unix SMB/CIFS implementation. + run a command as a specified user + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + modified for netatalk dgautheron@magic.fr +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +/* #define __USE_GNU 1 */ +#include + +#include +#include +#include +#include + +/* FIXME */ +#ifdef linux +#ifndef USE_SETRESUID +#define USE_SETRESUID 1 +#endif +#else +#ifndef USE_SETEUID +#define USE_SETEUID 1 +#endif +#endif + +#include + +/**************************************************************************n + Find a suitable temporary directory. The result should be copied immediately + as it may be overwritten by a subsequent call. + ****************************************************************************/ + +static const char *tmpdir(void) +{ + char *p; + + if ((p = getenv("TMPDIR"))) + return p; + return "/tmp"; +} + +/**************************************************************************** +This is a utility function of afprun(). +****************************************************************************/ + +static int setup_out_fd(void) +{ + int fd; + char path[MAXPATHLEN +1]; + + snprintf(path, sizeof(path)-1, "%s/afp.XXXXXX", tmpdir()); + + /* now create the file */ + fd = mkstemp(path); + + if (fd == -1) { + LOG(log_error, logtype_afpd, "setup_out_fd: Failed to create file %s. (%s)",path, strerror(errno) ); + return -1; + } + + /* Ensure file only kept around by open fd. */ + unlink(path); + return fd; +} + +/**************************************************************************** + Gain root privilege before doing something. + We want to end up with ruid==euid==0 +****************************************************************************/ +static void gain_root_privilege(void) +{ + seteuid(0); +} + +/**************************************************************************** + Ensure our real and effective groups are zero. + we want to end up with rgid==egid==0 +****************************************************************************/ +static void gain_root_group_privilege(void) +{ + setegid(0); +} + +/**************************************************************************** + Become the specified uid and gid - permanently ! + there should be no way back if possible +****************************************************************************/ +static void become_user_permanently(uid_t uid, gid_t gid) +{ + /* + * First - gain root privilege. We do this to ensure + * we can lose it again. + */ + + gain_root_privilege(); + gain_root_group_privilege(); + +#if USE_SETRESUID + setresgid(gid,gid,gid); + setgid(gid); + setresuid(uid,uid,uid); + setuid(uid); +#endif + +#if USE_SETREUID + setregid(gid,gid); + setgid(gid); + setreuid(uid,uid); + setuid(uid); +#endif + +#if USE_SETEUID + setegid(gid); + setgid(gid); + setuid(uid); + seteuid(uid); + setuid(uid); +#endif + +#if USE_SETUIDX + setgidx(ID_REAL, gid); + setgidx(ID_EFFECTIVE, gid); + setgid(gid); + setuidx(ID_REAL, uid); + setuidx(ID_EFFECTIVE, uid); + setuid(uid); +#endif +} + +/**************************************************************************** +run a command being careful about uid/gid handling and putting the output in +outfd (or discard it if outfd is NULL). +****************************************************************************/ + +int afprun(int root, char *cmd, int *outfd) +{ + pid_t pid; + uid_t uid = geteuid(); + gid_t gid = getegid(); + + /* point our stdout at the file we want output to go into */ + if (outfd && ((*outfd = setup_out_fd()) == -1)) { + return -1; + } + LOG(log_debug, logtype_afpd, "running %s as user %d", cmd, root?0:uid); + /* in this method we will exec /bin/sh with the correct + arguments, after first setting stdout to point at the file */ + + if ((pid=fork()) < 0) { + LOG(log_error, logtype_afpd, "afprun: fork failed with error %s", strerror(errno) ); + if (outfd) { + close(*outfd); + *outfd = -1; + } + return errno; + } + + if (pid) { + /* + * Parent. + */ + int status=0; + pid_t wpid; + + /* the parent just waits for the child to exit */ + while((wpid = waitpid(pid,&status,0)) < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + break; + } + if (wpid != pid) { + LOG(log_error, logtype_afpd, "waitpid(%d) : %s",(int)pid, strerror(errno) ); + if (outfd) { + close(*outfd); + *outfd = -1; + } + return -1; + } + /* Reset the seek pointer. */ + if (outfd) { + lseek(*outfd, 0, SEEK_SET); + } + +#if defined(WIFEXITED) && defined(WEXITSTATUS) + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } +#endif + return status; + } + + /* we are in the child. we exec /bin/sh to do the work for us. we + don't directly exec the command we want because it may be a + pipeline or anything else the config file specifies */ + + /* point our stdout at the file we want output to go into */ + if (outfd) { + close(1); + if (dup2(*outfd,1) != 1) { + LOG(log_error, logtype_afpd, "Failed to create stdout file descriptor"); + close(*outfd); + exit(80); + } + } + + if (chdir("/") < 0) { + LOG(log_error, logtype_afpd, "afprun: can't change directory to \"/\" %s", strerror(errno) ); + exit(83); + } + + /* now completely lose our privileges. This is a fairly paranoid + way of doing it, but it does work on all systems that I know of */ + if (root) { + become_user_permanently(0, 0); + uid = gid = 0; + } + else { + become_user_permanently(uid, gid); + } + if (getuid() != uid || geteuid() != uid || getgid() != gid || getegid() != gid) { + /* we failed to lose our privileges - do not execute the command */ + exit(81); /* we can't print stuff at this stage, instead use exit codes for debugging */ + } + + /* close all other file descriptors, leaving only 0, 1 and 2. 0 and + 2 point to /dev/null from the startup code */ + { + int fd; + for (fd=3;fd<256;fd++) close(fd); + } + + execl("/bin/sh","sh","-c",cmd,NULL); + /* not reached */ + exit(82); + return 1; +} + +/* + * Run a command in the background without waiting, + * being careful about uid/gid handling + */ +int afprun_bg(int root, char *cmd) +{ + pid_t pid; + uid_t uid = geteuid(); + gid_t gid = getegid(); + int fd, fdlimit = sysconf(_SC_OPEN_MAX); + + LOG(log_debug, logtype_afpd, "running %s as user %d", cmd, root ? 0 : uid); + + /* in this method we will exec /bin/sh with the correct + arguments, after first setting stdout to point at the file */ + + if ((pid = fork()) < 0) { + LOG(log_error, logtype_afpd, "afprun: fork failed with error %s", strerror(errno) ); + return errno; + } + + if (pid) + /* parent, just return */ + return 0; + + /* we are in the child. we exec /bin/sh to do the work for us. we + don't directly exec the command we want because it may be a + pipeline or anything else the config file specifies */ + + if (chdir("/") < 0) { + LOG(log_error, logtype_afpd, "afprun: can't change directory to \"/\" %s", strerror(errno) ); + exit(83); + } + + /* now completely lose our privileges. This is a fairly paranoid + way of doing it, but it does work on all systems that I know of */ + if (root) { + become_user_permanently(0, 0); + uid = gid = 0; + } else { + become_user_permanently(uid, gid); + } + + if (getuid() != uid || geteuid() != uid || getgid() != gid || getegid() != gid) { + /* we failed to lose our privileges - do not execute the command */ + exit(81); + } + + fd = 3; + while (fd < fdlimit) + close(fd++); + + execl("/bin/sh","sh","-c", cmd, NULL); + + /* not reached */ + exit(82); + return 1; +} diff --git a/etc/afpd/afpstats-service.xml b/etc/afpd/afpstats-service.xml new file mode 100644 index 0000000..099c778 --- /dev/null +++ b/etc/afpd/afpstats-service.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/etc/afpd/afpstats.c b/etc/afpd/afpstats.c new file mode 100644 index 0000000..80d3e6f --- /dev/null +++ b/etc/afpd/afpstats.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2013 Frank Lahm + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "afpstats_obj.h" +#include "afpstats_service_glue.h" + +/* + * Beware: this struct is accessed and modified from the main thread + * and from this thread, thus be careful to lock and unlock the mutex. + */ +static server_child_t *childs; + +static gpointer afpstats_thread(gpointer _data) +{ + DBusGConnection *bus; + DBusGProxy *bus_proxy; + GError *error = NULL; + GMainContext *ctxt; + GMainLoop *thread_loop; + guint request_name_result; + sigset_t sigs; + + /* Block all signals in this thread */ + sigfillset(&sigs); + pthread_sigmask(SIG_BLOCK, &sigs, NULL); + + ctxt = g_main_context_new(); + thread_loop = g_main_loop_new(ctxt, FALSE); + + dbus_g_object_type_install_info(AFPSTATS_TYPE_OBJECT, &dbus_glib_afpstats_obj_object_info); + + if (!(bus = dbus_g_bus_get_private(DBUS_BUS_SYSTEM, ctxt, &error))) { + LOG(log_error, logtype_afpd,"Couldn't connect to system bus: %s", error->message); + return NULL; + } + + if (!(bus_proxy = dbus_g_proxy_new_for_name(bus, "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus"))) { + LOG(log_error, logtype_afpd,"Couldn't create bus proxy"); + return NULL; + } + + if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, + G_TYPE_STRING, "org.netatalk.AFPStats", + G_TYPE_UINT, 0, + G_TYPE_INVALID, + G_TYPE_UINT, &request_name_result, + G_TYPE_INVALID)) { + LOG(log_error, logtype_afpd, "Failed to acquire DBUS name: %s", error->message); + return NULL; + } + + AFPStatsObj *obj = g_object_new(AFPSTATS_TYPE_OBJECT, NULL); + dbus_g_connection_register_g_object(bus, "/org/netatalk/AFPStats", G_OBJECT(obj)); + + g_main_loop_run(thread_loop); + return thread_loop; +} + +static void my_glib_log(const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + LOG(log_error, logtype_afpd, "%s: %s", log_domain, message); +} + +server_child_t *afpstats_get_and_lock_childs(void) +{ + pthread_mutex_lock(&childs->servch_lock); + return childs; +} + +void afpstats_unlock_childs(void) +{ + pthread_mutex_unlock(&childs->servch_lock); +} + +int afpstats_init(server_child_t *childs_in) +{ + GThread *thread; + + childs = childs_in; + g_type_init(); + g_thread_init(NULL); + dbus_g_thread_init(); + (void)g_log_set_default_handler(my_glib_log, NULL); + + thread = g_thread_create(afpstats_thread, NULL, TRUE, NULL); + + return 0; +} diff --git a/etc/afpd/afpstats.h b/etc/afpd/afpstats.h new file mode 100644 index 0000000..9f742ad --- /dev/null +++ b/etc/afpd/afpstats.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013 Frank Lahm + * + * 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. + */ + +#ifndef AFPD_AFPSTATS_H +#define AFPD_AFPSTATS_H + +#include + +extern int afpstats_init(server_child_t *); +extern server_child_t *afpstats_get_and_lock_childs(void); +extern void afpstats_unlock_childs(void); +#endif diff --git a/etc/afpd/afpstats_obj.c b/etc/afpd/afpstats_obj.c new file mode 100644 index 0000000..755d7a5 --- /dev/null +++ b/etc/afpd/afpstats_obj.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013 Frank Lahm + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include +#include +#include + +#include +#include + +#include "afpstats.h" +#include "afpstats_obj.h" + +struct AFPStatsObj +{ + GObject parent; +}; + +struct AFPStatsObjClass +{ + GObjectClass parent; +}; + +static void afpstats_obj_init(AFPStatsObj *obj) +{ +} + +static void afpstats_obj_class_init(AFPStatsObjClass *klass) +{ +} + +static gpointer afpstats_obj_parent_class = NULL; + +static void afpstats_obj_class_intern_init(gpointer klass) +{ + afpstats_obj_parent_class = g_type_class_peek_parent(klass); + afpstats_obj_class_init((AFPStatsObjClass *)klass); +} + +GType afpstats_obj_get_type(void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter(&g_define_type_id__volatile)) { + GType g_define_type_id = g_type_register_static_simple( + G_TYPE_OBJECT, + g_intern_static_string("AFPStatsObj"), + sizeof(AFPStatsObjClass), + (GClassInitFunc)afpstats_obj_class_intern_init, + sizeof(AFPStatsObj), + (GInstanceInitFunc)afpstats_obj_init, + (GTypeFlags)0); + g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +gboolean afpstats_obj_get_users(AFPStatsObj *obj, gchar ***ret, GError **error) +{ + gchar **names; + server_child_t *childs = afpstats_get_and_lock_childs(); + afp_child_t *child; + struct passwd *pw; + int i = 0, j; + char buf[256]; + + names = g_new(char *, childs->servch_count + 1); + + for (j = 0; j < CHILD_HASHSIZE && i < childs->servch_count; j++) { + child = childs->servch_table[j]; + while (child) { + if (child->afpch_valid && (pw = getpwuid(child->afpch_uid))) { + time_t time = child->afpch_logintime; + strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime(&time)); + names[i++] = g_strdup_printf("name: %s, pid: %d, logintime: %s, state: %s, volumes: %s", + pw->pw_name, child->afpch_pid, buf, + child->afpch_state == DSI_RUNNING ? "active" : + child->afpch_state == DSI_SLEEPING ? "sleeping" : + child->afpch_state == DSI_EXTSLEEP ? "sleeping" : + child->afpch_state == DSI_DISCONNECTED ? "disconnected" : + "unknown", + child->afpch_volumes ? child->afpch_volumes : "-"); + } + child = child->afpch_next; + } + } + names[i] = NULL; + *ret = names; + + afpstats_unlock_childs(); + + return TRUE; +} diff --git a/etc/afpd/afpstats_obj.h b/etc/afpd/afpstats_obj.h new file mode 100644 index 0000000..9d83000 --- /dev/null +++ b/etc/afpd/afpstats_obj.h @@ -0,0 +1,19 @@ +#ifndef AFPSTATS_OBJ_H +#define AFPSTATS_OBJ_H + +#include + +typedef struct AFPStatsObj AFPStatsObj; +typedef struct AFPStatsObjClass AFPStatsObjClass; + +GType afpstats_obj_get_type(void); +gboolean afpstats_obj_get_users(AFPStatsObj *obj, gchar ***ret, GError **error); + +#define AFPSTATS_TYPE_OBJECT (afpstats_obj_get_type ()) +#define AFPSTATS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST((object), AFPSTATS_TYPE_OBJECT, AFPStatsObj)) +#define AFPSTATS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), AFPSTATS_TYPE_OBJECT, AFPStatsObjClass)) +#define AFPSTATS_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), AFPSTATS_TYPE_OBJECT)) +#define AFPSTATS_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), AFPSTATS_TYPE_OBJECT)) +#define AFPSTATS_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), AFPSTATS_TYPE_OBJECT, AFPStatsObjClass)) + +#endif /* AFPSTATS_OBJ_H */ diff --git a/etc/afpd/afpstats_service_glue.h b/etc/afpd/afpstats_service_glue.h new file mode 100644 index 0000000..65081c4 --- /dev/null +++ b/etc/afpd/afpstats_service_glue.h @@ -0,0 +1,121 @@ +/* Generated by dbus-binding-tool; do not edit! */ + + +#ifndef __dbus_glib_marshal_afpstats_obj_MARSHAL_H__ +#define __dbus_glib_marshal_afpstats_obj_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#define g_marshal_value_peek_variant(v) g_value_get_variant (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* BOOLEAN:POINTER,POINTER */ +extern void dbus_glib_marshal_afpstats_obj_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +void +dbus_glib_marshal_afpstats_obj_BOOLEAN__POINTER_POINTER (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + data2); + + g_value_set_boolean (return_value, v_return); +} + +G_END_DECLS + +#endif /* __dbus_glib_marshal_afpstats_obj_MARSHAL_H__ */ + +#include +static const DBusGMethodInfo dbus_glib_afpstats_obj_methods[] = { + { (GCallback) afpstats_obj_get_users, dbus_glib_marshal_afpstats_obj_BOOLEAN__POINTER_POINTER, 0 }, +}; + +const DBusGObjectInfo dbus_glib_afpstats_obj_object_info = { 1, + dbus_glib_afpstats_obj_methods, + 1, +"org.netatalk.AFPStats\0GetUsers\0S\0ret\0O\0F\0N\0as\0\0\0", +"\0", +"\0" +}; + diff --git a/etc/afpd/afs.c b/etc/afpd/afs.c new file mode 100644 index 0000000..efe2ab6 --- /dev/null +++ b/etc/afpd/afs.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef AFS + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include + +#include "globals.h" +#include "directory.h" +#include "volume.h" +#include "misc.h" +#include "unix.h" + +int afs_getvolspace(struct vol *vol, VolSpace *bfree, VolSpace *btotal, uint32_t *bsize) +{ + struct ViceIoctl vi; + struct VolumeStatus *vs; + char venuspace[ sizeof( struct VolumeStatus ) + 3 ]; + int total, free; + + vi.in_size = 0; + vi.out_size = sizeof( venuspace ); + vi.out = venuspace; + if ( pioctl( vol->v_path, VIOCGETVOLSTAT, &vi, 1 ) < 0 ) { + return( AFPERR_PARAM ); + } + + vs = (struct VolumeStatus *)venuspace; + + if ( vs->PartBlocksAvail > 0 ) { + if ( vs->MaxQuota != 0 ) { +#ifdef min +#undef min +#endif +#define min(x,y) (((x)<(y))?(x):(y)) + free = min( vs->MaxQuota - vs->BlocksInUse, vs->PartBlocksAvail ); + } else { + free = vs->PartBlocksAvail; + } + } else { + free = 0; + } + + if ( vs->MaxQuota != 0 ) { + total = free + vs->BlocksInUse; + } else { + total = vs->PartMaxBlocks; + } + + *bsize = 1024; + *bfree = (VolSpace) free * 1024; + *btotal = (VolSpace) total * 1024; + + return( AFP_OK ); +} + +int afp_getdiracl(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + struct ViceIoctl vi; + struct vol *vol; + struct dir *dir; + struct path *path; + uint32_t did; + uint16_t vid; + + ibuf += 2; + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( short ); + if (( vol = getvolbyvid( vid )) == NULL ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( int ); + if (( dir = dirlookup( vol, did )) == NULL ) { + *rbuflen = 0; + return afp_errno; + } + + if (( path = cname( vol, dir, &ibuf )) == NULL ) { + *rbuflen = 0; + return get_afp_errno(AFPERR_PARAM); + } + if ( *path->m_name != '\0' ) { + *rbuflen = 0; + return (path_isadir( path))? afp_errno: AFPERR_BITMAP; + } + + vi.in_size = 0; + vi.out_size = *rbuflen; + vi.out = rbuf; + if ( pioctl( ".", VIOCGETAL, &vi, 1 ) < 0 ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + *rbuflen = strlen( vi.out ) + 1; + return( AFP_OK ); +} + +/* + * Calculate the mode for a directory in AFS. First, make sure the + * directory is in AFS. Could probably use something less heavy than + * VIOCGETAL. If the directory is on AFS, use access() calls to + * estimate permission, a la mdw. + */ +#ifdef accessmode + #undef accessmode +#endif + +void afsmode(const struct volume *vol, char *path, struct maccess *ma, struct dir *dir, struct stat *st) +{ + struct ViceIoctl vi; + char buf[ 1024 ]; + + if (( dir->d_flags & DIRF_FSMASK ) == DIRF_NOFS ) { + vi.in_size = 0; + vi.out_size = sizeof( buf ); + vi.out = buf; + if ( pioctl( path, VIOCGETAL, &vi, 1 ) < 0 ) { + dir->d_flags |= DIRF_UFS; + } else { + dir->d_flags |= DIRF_AFS; + } + } + + if (( dir->d_flags & DIRF_FSMASK ) != DIRF_AFS ) { + return; + } + + accessmode(vol, path, ma, dir, st ); + + return; +} + +extern struct dir *curdir; +/* + * cmd | 0 | vid | did | pathtype | pathname | 0 | acl + */ +int afp_setdiracl(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + struct ViceIoctl vi; + struct vol *vol; + struct dir *dir; + char *iend; + struct path *path; + uint32_t did; + uint16_t vid; + + *rbuflen = 0; + iend = ibuf + ibuflen; + ibuf += 2; + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( short ); + if (( vol = getvolbyvid( vid )) == NULL ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( int ); + if (( dir = dirlookup( vol, did )) == NULL ) { + *rbuflen = 0; + return afp_errno; + } + + if (( path = cname( vol, dir, &ibuf )) == NULL ) { + *rbuflen = 0; + return get_afp_errno(AFPERR_PARAM); + } + if ( *path->m_name != '\0' ) { + *rbuflen = 0; + return (path_isadir( path))? afp_errno: AFPERR_BITMAP; + } + + if ((int)ibuf & 1 ) { + ibuf++; + } + + vi.in_size = iend - ibuf; + vi.in = ibuf; + vi.out_size = 0; + + if ( pioctl( ".", VIOCSETAL, &vi, 1 ) < 0 ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + pioctl( ".AppleDouble", VIOCSETAL, &vi, 1 ); + if ( curdir->d_did == DIRDID_ROOT ) { + pioctl( ".AppleDesktop", VIOCSETAL, &vi, 1 ); + } + + return( AFP_OK ); +} + + +#ifdef UAM_AFSKRB + +#include +#include +#include +#include + +extern C_Block seskey; +extern Key_schedule seskeysched; + +int afp_afschangepw(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + char name[ MAXKTCNAMELEN ], instance[ MAXKTCNAMELEN ]; + char realm[ MAXKTCREALMLEN ]; + char oldpw[ 9 ], newpw[ 9 ]; + int len, rc; + uint16_t clen; + struct ktc_encryptionKey oldkey, newkey; + struct ktc_token adtok; + struct ubik_client *conn; + + *rbuflen = 0; + ++ibuf; + len = (unsigned char) *ibuf++; + ibuf[ len ] = '\0'; + *name = *instance = *realm = '\0'; + ka_ParseLoginName( ibuf, name, instance, realm ); + ucase( realm ); + if ( *realm == '\0' ) { + if ( krb_get_lrealm( realm, 1 ) != KSUCCESS ) { + LOG(log_error, logtype_afpd, "krb_get_lrealm failed" ); + return( AFPERR_BADUAM ); + } + } + + if ( strlen( name ) < 2 || strlen( name ) > 18 ) { + return( AFPERR_PARAM ); + } + ibuf += len; + + memcpy( &clen, ibuf, sizeof( clen )); + clen = ntohs( clen ); + if ( clen % 8 != 0 ) { + return( AFPERR_PARAM ); + } + + ibuf += sizeof( short ); + pcbc_encrypt((C_Block *)ibuf, (C_Block *)ibuf, + clen, seskeysched, seskey, DES_DECRYPT ); + + len = (unsigned char) *ibuf++; + if ( len > 8 ) { + return( AFPERR_PARAM ); + } + memset( oldpw, 0, sizeof( oldpw )); + memcpy( oldpw, ibuf, len ); + ibuf += len; + oldpw[ len ] = '\0'; + + len = (unsigned char) *ibuf++; + if ( len > 8 ) { + return( AFPERR_PARAM ); + } + memset( newpw, 0, sizeof( newpw )); + memcpy( newpw, ibuf, len ); + ibuf += len; + newpw[ len ] = '\0'; + + LOG(log_info, logtype_afpd, + "changing password for <%s>.<%s>@<%s>", name, instance, realm ); + + ka_StringToKey( oldpw, realm, &oldkey ); + memset( oldpw, 0, sizeof( oldpw )); + ka_StringToKey( newpw, realm, &newkey ); + memset( newpw, 0, sizeof( newpw )); + + rc = ka_GetAdminToken( name, instance, realm, &oldkey, 60, &adtok, 0 ); + memset( &oldkey, 0, sizeof( oldkey )); + switch ( rc ) { + case 0: + break; + case KABADREQUEST: + memset( &newkey, 0, sizeof( newkey )); + return( AFPERR_NOTAUTH ); + default: + memset( &newkey, 0, sizeof( newkey )); + return( AFPERR_BADUAM ); + } + if ( ka_AuthServerConn( realm, KA_MAINTENANCE_SERVICE, &adtok, &conn ) + != 0 ) { + memset( &newkey, 0, sizeof( newkey )); + return( AFPERR_BADUAM ); + } + + rc = ka_ChangePassword( name, instance, conn, 0, &newkey ); + memset( &newkey, 0, sizeof( newkey )); + if ( rc != 0 ) { + return( AFPERR_BADUAM ); + } + + LOG(log_debug, logtype_afpd, "password changed succeeded" ); + return( AFP_OK ); +} + +#endif /* UAM_AFSKRB */ +#endif /* AFS */ diff --git a/etc/afpd/appl.c b/etc/afpd/appl.c new file mode 100644 index 0000000..f53803e --- /dev/null +++ b/etc/afpd/appl.c @@ -0,0 +1,503 @@ +/* + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "volume.h" +#include "directory.h" +#include "file.h" +#include "desktop.h" + +static struct savedt sa = { { 0, 0, 0, 0 }, -1, 0, 0}; + +static int pathcmp(char *p, int plen, char *q, int qlen) +{ + return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 ); +} + +static int applopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode) +{ + char *dtf, *adt, *adts; + + if ( sa.sdt_fd != -1 ) { + if ( !(flags & ( O_RDWR | O_WRONLY )) && + memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 && + sa.sdt_vid == vol->v_vid ) { + return( AFP_OK ); + } + close( sa.sdt_fd ); + sa.sdt_fd = -1; + } + + dtf = dtfile( vol, creator, ".appl" ); + + if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) { + if ( errno == ENOENT && ( flags & O_CREAT )) { + if (( adts = strrchr( dtf, '/' )) == NULL ) { + return( AFPERR_PARAM ); + } + *adts = '\0'; + if (( adt = strrchr( dtf, '/' )) == NULL ) { + return( AFPERR_PARAM ); + } + *adt = '\0'; + (void) ad_mkdir( dtf, DIRBITS | 0777 ); + *adt = '/'; + (void) ad_mkdir( dtf, DIRBITS | 0777 ); + *adts = '/'; + + if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) { + return( AFPERR_PARAM ); + } + } else { + return( AFPERR_PARAM ); + } + } + memcpy( sa.sdt_creator, creator, sizeof( CreatorType )); + sa.sdt_vid = vol->v_vid; + sa.sdt_index = 0; + return( AFP_OK ); +} + +/* + * copy appls to new file, deleting any matching (old) appl entries + */ +static int copyapplfile(int sfd, int dfd, char *mpath, u_short mplen) +{ + int cc; + char *p; + uint16_t len; + unsigned char appltag[ 4 ]; + char buf[ MAXPATHLEN ]; + + while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) { + p = buf + sizeof(appltag); + memcpy( &len, p, sizeof(len)); + len = ntohs( len ); + p += sizeof( len ); + if (( cc = read( sa.sdt_fd, p, len )) < len ) { + break; + } + if ( pathcmp( mpath, mplen, p, len ) != 0 ) { + p += len; + if ( write( dfd, buf, p - buf ) != p - buf ) { + cc = -1; + break; + } + } + } + return( cc ); +} + +/* + * build mac. path (backwards) by traversing the directory tree + * + * The old way: dir and path refer to an app, path is a mac format + * pathname. makemacpath() builds something that looks like a cname, + * but uses upaths instead of mac format paths. + * + * The new way: dir and path refer to an app, path is a mac format + * pathname. makemacpath() builds a cname. (zero is a path separator + * and it's not \0 terminated). + * + * See afp_getappl() for the backward compatiblity code. + */ +static char * +makemacpath(const struct vol *vol, char *mpath, int mpathlen, struct dir *dir, char *path) +{ + char *p; + + p = mpath + mpathlen; + p -= strlen( path ); + memcpy( p, path, strlen( path )); + + while ( dir->d_did != DIRDID_ROOT ) { + p -= blength(dir->d_m_name) + 1; + if (p < mpath) { + /* FIXME: pathname too long */ + return NULL; + } + memcpy(p, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1); + if ((dir = dirlookup(vol, dir->d_pdid)) == NULL) + return NULL; + } + return( p ); + + +#if 0 + char buffer[12 + MAXPATHLEN + 1]; + int buflen = 12 + MAXPATHLEN + 1; + char *ret = mpath; + char *path = name; + char *uname = NULL; + struct bstrList *pathlist = NULL; + cnid_t cnid = dir->d_pdid; + + /* Create list for path elements, request 16 list elements for now*/ + if ((pathlist = bstListCreateMin(16)) == NULL) { + LOG(log_error, logtype_afpd, "makemacpath: OOM: %s", strerror(errno)); + return NULL; + } + + while ( cnid != DIRDID_ROOT ) { + + /* construct path, copy already found uname to path element list*/ + if ((bstrListPush(pathlist, bfromcstr(path))) != BSTR_OK) { + afp_errno = AFPERR_MISC; + ret = NULL; + goto exit; + } + + /* next part */ + AFP_CNID_START("cnid_resolve"); + uname = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen); + AFP_CNID_DONE(); + + if (uname == NULL) { + afp_errno = AFPERR_NOOBJ; + ret = NULL; + goto exit; + } + + if ((path = utompath(vol, uname, cnid, utf8_encoding())) == NULL) { + afp_errno = AFPERR_MISC; + ret = NULL; + goto exit; + } + } + + + +exit: + if (pathlist) + bstrListDestroy(pathlist); + + return(ret); +#endif +} + + +int afp_addappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + int tfd, cc; + uint32_t did; + uint16_t vid, mplen; + struct path *path; + char *dtf, *p, *mp; + unsigned char creator[ 4 ]; + unsigned char appltag[ 4 ]; + char *mpath, *tempfile; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid ))) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + memcpy( creator, ibuf, sizeof( creator )); + ibuf += sizeof( creator ); + + memcpy( appltag, ibuf, sizeof( appltag )); + ibuf += sizeof( appltag ); + + if (NULL == ( path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_PARAM); + } + if ( path_isadir(path) ) { + return( AFPERR_BADTYPE ); + } + + if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) { + return( AFPERR_PARAM ); + } + if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { + return( AFPERR_PARAM ); + } + dtf = dtfile( vol, creator, ".appl.temp" ); + tempfile = obj->oldtmp; + strcpy( tempfile, dtf ); + if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) { + return( AFPERR_PARAM ); + } + mpath = obj->newtmp; + mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name ); + if (!mp) { + close(tfd); + return AFPERR_PARAM; + } + mplen = mpath + AFPOBJ_TMPSIZ - mp; + + /* write the new appl entry at start of temporary file */ + p = mp - sizeof( u_short ); + mplen = htons( mplen ); + memcpy( p, &mplen, sizeof( mplen )); + mplen = ntohs( mplen ); + p -= sizeof( appltag ); + memcpy(p, appltag, sizeof( appltag )); + cc = mpath + AFPOBJ_TMPSIZ - p; + if ( write( tfd, p, cc ) != cc ) { + close(tfd); + unlink( tempfile ); + return( AFPERR_PARAM ); + } + cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen ); + close( tfd ); + close( sa.sdt_fd ); + sa.sdt_fd = -1; + + if ( cc < 0 ) { + unlink( tempfile ); + return( AFPERR_PARAM ); + } + if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) { + return( AFPERR_PARAM ); + } + return( AFP_OK ); +} + +int afp_rmvappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + int tfd, cc; + uint32_t did; + uint16_t vid, mplen; + struct path *path; + char *dtf, *mp; + unsigned char creator[ 4 ]; + char *tempfile, *mpath; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid ))) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + memcpy( creator, ibuf, sizeof( creator )); + ibuf += sizeof( creator ); + + if (NULL == ( path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_PARAM); + } + if ( path_isadir(path) ) { + return( AFPERR_BADTYPE ); + } + + if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) { + return( AFPERR_NOOBJ ); + } + if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { + return( AFPERR_PARAM ); + } + dtf = dtfile( vol, creator, ".appl.temp" ); + tempfile = obj->oldtmp; + strcpy( tempfile, dtf ); + if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) { + return( AFPERR_PARAM ); + } + mpath = obj->newtmp; + mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name ); + if (!mp) { + close(tfd); + return AFPERR_PARAM ; + } + + mplen = mpath + AFPOBJ_TMPSIZ - mp; + cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen ); + close( tfd ); + close( sa.sdt_fd ); + sa.sdt_fd = -1; + + if ( cc < 0 ) { + unlink( tempfile ); + return( AFPERR_PARAM ); + } + if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) { + return( AFPERR_PARAM ); + } + return( AFP_OK ); +} + +int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + char *p, *q; + int cc; + size_t buflen; + uint16_t vid, aindex, bitmap, len; + unsigned char creator[ 4 ]; + unsigned char appltag[ 4 ]; + char *buf, *cbuf; + struct path *path; + + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + + memcpy( creator, ibuf, sizeof( creator )); + ibuf += sizeof( creator ); + + memcpy( &aindex, ibuf, sizeof( aindex )); + ibuf += sizeof( aindex ); + aindex = ntohs( aindex ); + if ( aindex ) { /* index 0 == index 1 */ + --aindex; + } + + memcpy( &bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + + if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) { + *rbuflen = 0; + return( AFPERR_NOITEM ); + } + if ( aindex < sa.sdt_index ) { + if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + sa.sdt_index = 0; + } + + /* position to correct spot within appl file */ + buf = obj->oldtmp; + while (( cc = read( sa.sdt_fd, buf, sizeof( appltag ) + + sizeof( u_short ))) > 0 ) { + p = buf + sizeof( appltag ); + memcpy( &len, p, sizeof( len )); + len = ntohs( len ); + p += sizeof( u_short ); + if (( cc = read( sa.sdt_fd, p, len )) < len ) { + break; + } + if ( sa.sdt_index == aindex ) { + break; + } + sa.sdt_index++; + } + if ( cc <= 0 || sa.sdt_index != aindex ) { + *rbuflen = 0; + return( AFPERR_NOITEM ); + } + sa.sdt_index++; + +#ifdef APPLCNAME + /* + * Check to see if this APPL mapping has an mpath or a upath. If + * there are any ':'s in the name, it is a upath and must be converted + * to an mpath. Hopefully, this code will go away. + */ + { +#define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' ) +#define islxdigit(x) (!isupper(x)&&isxdigit(x)) + + char utomname[ MAXPATHLEN + 1]; + char *u, *m; + int i, h; + + u = p; + m = utomname; + i = len; + while ( i ) { + if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) && + *(u+2) != '\0' && islxdigit( *(u+2))) { + ++u, --i; + h = hextoint( *u ) << 4; + ++u, --i; + h |= hextoint( *u ); + *m++ = h; + } else { + *m++ = *u; + } + ++u, --i; + } + + len = m - utomname; + p = utomname; + + if ( p[ len - 1 ] == '\0' ) { + len--; + } + } +#endif /* APPLCNAME */ + + /* fake up a cname */ + cbuf = obj->newtmp; + q = cbuf; + *q++ = 2; /* long path type */ + *q++ = (unsigned char)len; + memcpy( q, p, len ); + q = cbuf; + + if (( path = cname( vol, vol->v_root, &q )) == NULL ) { + *rbuflen = 0; + return( AFPERR_NOITEM ); + } + + if ( path_isadir(path) || path->st_errno ) { + *rbuflen = 0; + return( AFPERR_NOITEM ); + } + buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag ); + if ( getfilparams(obj, vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) + + sizeof( appltag ), &buflen, 0) != AFP_OK ) { + *rbuflen = 0; + return( AFPERR_BITMAP ); + } + + *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag ); + bitmap = htons( bitmap ); + memcpy( rbuf, &bitmap, sizeof( bitmap )); + rbuf += sizeof( bitmap ); + memcpy( rbuf, appltag, sizeof( appltag )); + rbuf += sizeof( appltag ); + return( AFP_OK ); +} + diff --git a/etc/afpd/auth.c b/etc/afpd/auth.c new file mode 100644 index 0000000..dc4dd8b --- /dev/null +++ b/etc/afpd/auth.c @@ -0,0 +1,1087 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef TRU64 +#include +#include +#include +#include + +extern void afp_get_cmdline( int *ac, char ***av ); +#endif /* TRU64 */ + +#include +#include +#include +#include +#include +#include +#include + +#include "auth.h" +#include "uam_auth.h" +#include "switch.h" +#include "status.h" +#include "fork.h" +#include "extattrs.h" +#ifdef HAVE_ACLS +#include "acls.h" +#endif + +static int afp_version_index; +static struct uam_mod uam_modules = {NULL, NULL, &uam_modules, &uam_modules}; +static struct uam_obj uam_login = {"", "", 0, {{NULL, NULL, NULL, NULL }}, &uam_login, + &uam_login}; +static struct uam_obj uam_changepw = {"", "", 0, {{NULL, NULL, NULL, NULL}}, &uam_changepw, + &uam_changepw}; + +static struct uam_obj *afp_uam = NULL; + + +void status_versions( char *data, const DSI *dsi) +{ + char *start = data; + uint16_t status; + int len, num, i, count = 0; + + memcpy(&status, start + AFPSTATUS_VERSOFF, sizeof(status)); + num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] ); + + for ( i = 0; i < num; i++ ) { + if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue; + count++; + } + data += ntohs( status ); + *data++ = count; + + for ( i = 0; i < num; i++ ) { + if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue; + len = strlen( afp_versions[ i ].av_name ); + *data++ = len; + memcpy( data, afp_versions[ i ].av_name , len ); + data += len; + } + status = htons( data - start ); + memcpy(start + AFPSTATUS_UAMSOFF, &status, sizeof(status)); +} + +void status_uams(char *data, const char *authlist) +{ + char *start = data; + uint16_t status; + struct uam_obj *uams; + int len, num = 0; + + memcpy(&status, start + AFPSTATUS_UAMSOFF, sizeof(status)); + uams = &uam_login; + while ((uams = uams->uam_prev) != &uam_login) { + if (strstr(authlist, uams->uam_path)) + num++; + } + + data += ntohs( status ); + *data++ = num; + while ((uams = uams->uam_prev) != &uam_login) { + if (strstr(authlist, uams->uam_path)) { + LOG(log_info, logtype_afpd, "uam: \"%s\" available", uams->uam_name); + len = strlen( uams->uam_name); + *data++ = len; + memcpy( data, uams->uam_name, len ); + data += len; + } + } + + /* icon offset */ + status = htons(data - start); + memcpy(start + AFPSTATUS_ICONOFF, &status, sizeof(status)); +} + +/* handle errors by closing the connection. this is only needed + * by the afp_* functions. */ +static int send_reply(const AFPObj *obj, const int err) +{ + if ((err == AFP_OK) || (err == AFPERR_AUTHCONT)) + return err; + + obj->reply(obj->dsi, err); + obj->exit(0); + + return AFP_OK; +} + +static int afp_errpwdexpired(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen) +{ + *rbuflen = 0; + return AFPERR_PWDEXPR; +} + +static int afp_null_nolog(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen) +{ + *rbuflen = 0; + return( AFPERR_NOOP ); +} + +static int set_auth_switch(const AFPObj *obj, int expired) +{ + int i; + + if (expired) { + /* + * BF: expired password handling + * to allow the user to change his/her password we have to allow login + * but every following call except for FPChangePassword will be thrown + * away with an AFPERR_PWDEXPR error. (thanks to Leland Wallace from Apple + * for clarifying this) + */ + + for (i=0; i<=0xff; i++) { + uam_afpserver_action(i, UAM_AFPSERVER_PREAUTH, afp_errpwdexpired, NULL); + } + uam_afpserver_action(AFP_LOGOUT, UAM_AFPSERVER_PREAUTH, afp_logout, NULL); + uam_afpserver_action(AFP_CHANGEPW, UAM_AFPSERVER_PREAUTH, afp_changepw, NULL); + } + else { + afp_switch = postauth_switch; + switch (obj->afp_version) { + + case 34: + case 33: + case 32: +#ifdef HAVE_ACLS + uam_afpserver_action(AFP_GETACL, UAM_AFPSERVER_POSTAUTH, afp_getacl, NULL); + uam_afpserver_action(AFP_SETACL, UAM_AFPSERVER_POSTAUTH, afp_setacl, NULL); + uam_afpserver_action(AFP_ACCESS, UAM_AFPSERVER_POSTAUTH, afp_access, NULL); +#endif /* HAVE_ACLS */ + uam_afpserver_action(AFP_GETEXTATTR, UAM_AFPSERVER_POSTAUTH, afp_getextattr, NULL); + uam_afpserver_action(AFP_SETEXTATTR, UAM_AFPSERVER_POSTAUTH, afp_setextattr, NULL); + uam_afpserver_action(AFP_REMOVEATTR, UAM_AFPSERVER_POSTAUTH, afp_remextattr, NULL); + uam_afpserver_action(AFP_LISTEXTATTR, UAM_AFPSERVER_POSTAUTH, afp_listextattr, NULL); + + case 31: + uam_afpserver_action(AFP_SYNCDIR, UAM_AFPSERVER_POSTAUTH, afp_syncdir, NULL); + uam_afpserver_action(AFP_SYNCFORK, UAM_AFPSERVER_POSTAUTH, afp_syncfork, NULL); +#ifdef HAVE_TRACKER + uam_afpserver_action(AFP_SPOTLIGHT_PRIVATE, UAM_AFPSERVER_POSTAUTH, afp_spotlight_rpc, NULL); +#endif + uam_afpserver_action(AFP_ENUMERATE_EXT2, UAM_AFPSERVER_POSTAUTH, afp_enumerate_ext2, NULL); + + case 30: + uam_afpserver_action(AFP_ENUMERATE_EXT, UAM_AFPSERVER_POSTAUTH, afp_enumerate_ext, NULL); + uam_afpserver_action(AFP_BYTELOCK_EXT, UAM_AFPSERVER_POSTAUTH, afp_bytelock_ext, NULL); + /* catsearch_ext uses the same packet as catsearch FIXME double check this, it wasn't true for enue + enumerate_ext */ + uam_afpserver_action(AFP_CATSEARCH_EXT, UAM_AFPSERVER_POSTAUTH, afp_catsearch_ext, NULL); + uam_afpserver_action(AFP_GETSESSTOKEN, UAM_AFPSERVER_POSTAUTH, afp_getsession, NULL); + uam_afpserver_action(AFP_READ_EXT, UAM_AFPSERVER_POSTAUTH, afp_read_ext, NULL); + uam_afpserver_action(AFP_WRITE_EXT, UAM_AFPSERVER_POSTAUTH, afp_write_ext, NULL); + uam_afpserver_action(AFP_DISCTOLDSESS, UAM_AFPSERVER_POSTAUTH, afp_disconnect, NULL); + + case 22: + /* + * If first connection to a server is done in classic AFP2.2 version is used + * but OSX uses AFP3.x FPzzz command ! + */ + uam_afpserver_action(AFP_ZZZ, UAM_AFPSERVER_POSTAUTH, afp_zzz, NULL); + break; + } + } + + return AFP_OK; +} + +static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expired) +{ +#ifdef ADMIN_GRP + int admin = 0; +#endif /* ADMIN_GRP */ + + if ( pwd->pw_uid == 0 ) { /* don't allow root login */ + LOG(log_error, logtype_afpd, "login: root login denied!" ); + return AFPERR_NOTAUTH; + } + + if (obj->cnx_cnt > obj->cnx_max) { + LOG(log_error, logtype_dsi, "login: too many connections, limit: %d", obj->cnx_max); + return AFPERR_MAXSESS; + } + + LOG(log_note, logtype_afpd, "Login by %s (%s)", + pwd->pw_name, afp_versions[afp_version_index].av_name); + + if (set_groups(obj, pwd) != 0) + return AFPERR_BADUAM; + +#ifdef ADMIN_GRP + LOG(log_debug, logtype_afpd, "obj->options.admingid == %d", obj->options.admingid); + + if (obj->options.admingid != 0) { + int i; + for (i = 0; i < obj->ngroups; i++) { + if (obj->groups[i] == obj->options.admingid) admin = 1; + } + } + if (admin) { + ad_setfuid(0); + LOG(log_info, logtype_afpd, "admin login -- %s", pwd->pw_name ); + } + if (!admin) +#endif /* ADMIN_GRP */ +#ifdef TRU64 + { + struct DSI *dsi = obj->handle; + struct hostent *hp; + char *clientname; + int argc; + char **argv; + char hostname[256]; + + afp_get_cmdline( &argc, &argv ); + + hp = gethostbyaddr( (char *) &dsi->client.sin_addr, + sizeof( struct in_addr ), + dsi->client.sin_family ); + + if( hp ) + clientname = hp->h_name; + else + clientname = inet_ntoa( dsi->client.sin_addr ); + + sprintf( hostname, "%s@%s", pwd->pw_name, clientname ); + + if( sia_become_user( NULL, argc, argv, hostname, pwd->pw_name, + NULL, FALSE, NULL, NULL, + SIA_BEU_REALLOGIN ) != SIASUCCESS ) + return AFPERR_BADUAM; + + LOG(log_info, logtype_afpd, "session from %s (%s)", hostname, + inet_ntoa( dsi->client.sin_addr ) ); + + if (setegid( pwd->pw_gid ) < 0 || seteuid( pwd->pw_uid ) < 0) { + LOG(log_error, logtype_afpd, "login: %s %s", pwd->pw_name, strerror(errno) ); + return AFPERR_BADUAM; + } + } +#else /* TRU64 */ + if (setegid( pwd->pw_gid ) < 0 || seteuid( pwd->pw_uid ) < 0) { + LOG(log_error, logtype_afpd, "login: %s %s", pwd->pw_name, strerror(errno) ); + return AFPERR_BADUAM; + } +#endif /* TRU64 */ + + LOG(log_debug, logtype_afpd, "login: supplementary groups: %s", print_groups(obj->ngroups, obj->groups)); + + /* There's probably a better way to do this, but for now, we just play root */ +#ifdef ADMIN_GRP + if (admin) + obj->uid = 0; + else +#endif /* ADMIN_GRP */ + obj->uid = geteuid(); + + set_auth_switch(obj, expired); + /* save our euid, we need it for preexec_close */ + obj->uid = geteuid(); + obj->logout = logout; + + /* pam_umask or similar might have changed our umask */ + (void)umask(obj->options.umask); + + /* Some PAM module might have reset our signal handlers and timer, so we need to reestablish them */ + afp_over_dsi_sighandlers(obj); + + /* Send FCE login event */ + fce_register(obj, FCE_LOGIN, "", NULL); + + return( AFP_OK ); +} + +/* ---------------------- */ +int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + uint32_t data; + DSI *dsi = (DSI *)AFPobj->dsi; + + *rbuflen = 0; + ibuf += 2; + ibuflen -= 2; + + if (ibuflen < 4) + return AFPERR_MISC; + memcpy(&data, ibuf, 4); /* flag */ + data = ntohl(data); + + /* + * Possible sleeping states: + * 1) normal sleep: DSI_SLEEPING (up to 10.3) + * 2) extended sleep: DSI_SLEEPING | DSI_EXTSLEEP (starting with 10.4) + */ + + if (data & AFPZZZ_EXT_WAKEUP) { + /* wakeup request from exetended sleep */ + if (dsi->flags & DSI_EXTSLEEP) { + LOG(log_note, logtype_afpd, "afp_zzz: waking up from extended sleep"); + dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP); + ipc_child_state(obj, DSI_RUNNING); + } + } else { + /* sleep request */ + dsi->flags |= DSI_SLEEPING; + if (data & AFPZZZ_EXT_SLEEP) { + LOG(log_note, logtype_afpd, "afp_zzz: entering extended sleep"); + dsi->flags |= DSI_EXTSLEEP; + ipc_child_state(obj, DSI_EXTSLEEP); + } else { + LOG(log_note, logtype_afpd, "afp_zzz: entering normal sleep"); + ipc_child_state(obj, DSI_SLEEPING); + } + } + + /* + * According to AFP 3.3 spec we should not return anything, + * but eg 10.5.8 server still returns the numbers of hours + * the server is keeping the sessino (ie max sleeptime). + */ + data = obj->options.sleep / 120; /* hours */ + if (!data) { + data = 1; + } + *rbuflen = sizeof(data); + data = htonl(data); + memcpy(rbuf, &data, sizeof(data)); + rbuf += sizeof(data); + + return AFP_OK; +} + +/* ---------------------- */ +static int create_session_token(AFPObj *obj) +{ + pid_t pid; + + /* use 8 bytes for token as OSX, don't know if it helps */ + if ( sizeof(pid_t) > SESSIONTOKEN_LEN) { + LOG(log_error, logtype_afpd, "sizeof(pid_t) > %u", SESSIONTOKEN_LEN ); + return AFPERR_MISC; + } + + if ( NULL == (obj->sinfo.sessiontoken = malloc(SESSIONTOKEN_LEN)) ) + return AFPERR_MISC; + + memset(obj->sinfo.sessiontoken, 0, SESSIONTOKEN_LEN); + obj->sinfo.sessiontoken_len = SESSIONTOKEN_LEN; + pid = getpid(); + memcpy(obj->sinfo.sessiontoken, &pid, sizeof(pid_t)); + + return 0; +} + +static int create_session_key(AFPObj *obj) +{ + /* create session key */ + if (obj->sinfo.sessionkey == NULL) { + if (NULL == (obj->sinfo.sessionkey = malloc(SESSIONKEY_LEN)) ) + return AFPERR_MISC; + uam_random_string(obj, obj->sinfo.sessionkey, SESSIONKEY_LEN); + obj->sinfo.sessionkey_len = SESSIONKEY_LEN; + } + return AFP_OK; +} + + +/* ---------------------- */ +int afp_getsession( + AFPObj *obj, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + uint16_t type; + uint32_t idlen = 0; + uint32_t boottime; + uint32_t tklen, tp; + char *token; + char *p; + + *rbuflen = 0; + tklen = 0; + + if (ibuflen < 2 + sizeof(type)) { + return AFPERR_PARAM; + } + + ibuf += 2; + ibuflen -= 2; + + memcpy(&type, ibuf, sizeof(type)); + type = ntohs(type); + ibuf += sizeof(type); + ibuflen -= sizeof(type); + + if ( obj->sinfo.sessiontoken == NULL ) { + if ( create_session_token( obj ) ) + return AFPERR_MISC; + } + + /* + * + */ + switch (type) { + case 0: /* old version ?*/ + tklen = obj->sinfo.sessiontoken_len; + token = obj->sinfo.sessiontoken; + break; + case 1: /* disconnect */ + case 2: /* reconnect update id */ + if (ibuflen >= sizeof(idlen)) { + memcpy(&idlen, ibuf, sizeof(idlen)); + idlen = ntohl(idlen); + ibuf += sizeof(idlen); + ibuflen -= sizeof(idlen); + if (ibuflen < idlen) { + return AFPERR_PARAM; + } + /* memcpy (id, ibuf, idlen) */ + tklen = obj->sinfo.sessiontoken_len; + token = obj->sinfo.sessiontoken; + } + break; + case 3: + case 4: + if (ibuflen >= 8 ) { + p = ibuf; + memcpy( &idlen, ibuf, sizeof(idlen)); + idlen = ntohl(idlen); + ibuf += sizeof(idlen); + ibuflen -= sizeof(idlen); + ibuf += sizeof(boottime); + ibuflen -= sizeof(boottime); + if (ibuflen < idlen || idlen > (90-10)) { + return AFPERR_PARAM; + } + if (!obj->sinfo.clientid) { + obj->sinfo.clientid = malloc(idlen + 8); + memcpy(obj->sinfo.clientid, p, idlen + 8); + obj->sinfo.clientid_len = idlen + 8; + } + if (ipc_child_write(obj->ipc_fd, IPC_GETSESSION, idlen+8, p) != 0) + return AFPERR_MISC; + tklen = obj->sinfo.sessiontoken_len; + token = obj->sinfo.sessiontoken; + } + break; + case 8: /* Panther Kerberos Token */ + tklen = obj->sinfo.cryptedkey_len; + token = obj->sinfo.cryptedkey; + break; + default: + return AFPERR_NOOP; + break; + + } + + if (tklen == 0) + return AFPERR_MISC; + + tp = htonl(tklen); + memcpy(rbuf, &tp, sizeof(tklen)); + rbuf += sizeof(tklen); + *rbuflen += sizeof(tklen); + + memcpy(rbuf, token, tklen); + *rbuflen += tklen; + + return AFP_OK; +} + +/* ---------------------- */ +int afp_disconnect(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + DSI *dsi = (DSI *)obj->dsi; + uint16_t type; + uint32_t tklen; + pid_t token; + int i; + + *rbuflen = 0; + ibuf += 2; + +#if 0 + /* check for guest user */ + if ( 0 == (strcasecmp(obj->username, obj->options.guest)) ) { + return AFPERR_MISC; + } +#endif + + memcpy(&type, ibuf, sizeof(type)); + type = ntohs(type); + ibuf += sizeof(type); + + memcpy(&tklen, ibuf, sizeof(tklen)); + tklen = ntohl(tklen); + ibuf += sizeof(tklen); + + if ( sizeof(pid_t) > SESSIONTOKEN_LEN) { + LOG(log_error, logtype_afpd, "sizeof(pid_t) > %u", SESSIONTOKEN_LEN ); + return AFPERR_MISC; + } + if (tklen != SESSIONTOKEN_LEN) { + return AFPERR_MISC; + } + tklen = sizeof(pid_t); + memcpy(&token, ibuf, tklen); + + /* our stuff is pid + zero pad */ + ibuf += tklen; + for (i = tklen; i < SESSIONTOKEN_LEN; i++, ibuf++) { + if (*ibuf != 0) { + return AFPERR_MISC; + } + } + + LOG(log_note, logtype_afpd, "afp_disconnect: trying primary reconnect"); + dsi->flags |= DSI_RECONINPROG; + + /* Deactivate tickle timer */ + const struct itimerval none = {{0, 0}, {0, 0}}; + setitimer(ITIMER_REAL, &none, NULL); + + /* check for old session, possibly transfering session from here to there */ + if (ipc_child_write(obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) != 0) + goto exit; + /* write uint16_t DSI request ID */ + if (writet(obj->ipc_fd, &dsi->header.dsi_requestID, 2, 0, 2) != 2) { + LOG(log_error, logtype_afpd, "afp_disconnect: couldn't send DSI request ID"); + goto exit; + } + /* now send our connected AFP client socket */ + if (send_fd(obj->ipc_fd, dsi->socket) != 0) + goto exit; + /* Now see what happens: either afpd master sends us SIGTERM because our session */ + /* has been transfered to a old disconnected session, or we continue */ + sleep(5); + + if (!(dsi->flags & DSI_RECONINPROG)) { /* deleted in SIGTERM handler */ + /* Reconnect succeeded, we exit now after sleeping some more */ + sleep(2); /* sleep some more to give the recon. session time */ + LOG(log_note, logtype_afpd, "afp_disconnect: primary reconnect succeeded"); + exit(0); + } + +exit: + /* Reinstall tickle timer */ + setitimer(ITIMER_REAL, &dsi->timer, NULL); + + LOG(log_error, logtype_afpd, "afp_disconnect: primary reconnect failed"); + return AFPERR_MISC; +} + +/* ---------------------- */ +static int get_version(AFPObj *obj, char *ibuf, size_t ibuflen, size_t len) +{ + int num,i; + + if (!len || len > ibuflen) + return AFPERR_BADVERS; + + num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ]); + for ( i = 0; i < num; i++ ) { + if ( strncmp( ibuf, afp_versions[ i ].av_name , len ) == 0 ) { + obj->afp_version = afp_versions[ i ].av_number; + afp_version_index = i; + break; + } + } + if ( i == num ) /* An inappropo version */ + return AFPERR_BADVERS ; + + /* FIXME Hack */ + if (obj->afp_version >= 30 && sizeof(off_t) != 8) { + LOG(log_error, logtype_afpd, "get_version: no LARGE_FILE support recompile!" ); + return AFPERR_BADVERS ; + } + + return 0; +} + +/* ---------------------- */ +int afp_login(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + struct passwd *pwd = NULL; + size_t len; + int i; + + *rbuflen = 0; + + if ( nologin & 1) + return send_reply(obj, AFPERR_SHUTDOWN ); + + if (ibuflen < 2) + return send_reply(obj, AFPERR_BADVERS ); + + ibuf++; + len = (unsigned char) *ibuf++; + ibuflen -= 2; + + i = get_version(obj, ibuf, ibuflen, len); + if (i) + return send_reply(obj, i ); + + if (ibuflen <= len) + return send_reply(obj, AFPERR_BADUAM); + + ibuf += len; + ibuflen -= len; + + len = (unsigned char) *ibuf++; + ibuflen--; + + if (!len || len > ibuflen) + return send_reply(obj, AFPERR_BADUAM); + + if (NULL == (afp_uam = auth_uamfind(UAM_SERVER_LOGIN, ibuf, len)) ) + return send_reply(obj, AFPERR_BADUAM); + ibuf += len; + ibuflen -= len; + + if (AFP_OK != (i = create_session_key(obj)) ) + return send_reply(obj, i); + + i = afp_uam->u.uam_login.login(obj, &pwd, ibuf, ibuflen, rbuf, rbuflen); + + if (!pwd || ( i != AFP_OK && i != AFPERR_PWDEXPR)) + return send_reply(obj, i); + + return send_reply(obj, login(obj, pwd, afp_uam->u.uam_login.logout, ((i==AFPERR_PWDEXPR)?1:0))); +} + +/* ---------------------- */ +int afp_login_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + struct passwd *pwd = NULL; + size_t len; + int i; + char type; + uint16_t len16; + char *username; + + *rbuflen = 0; + + if ( nologin & 1) + return send_reply(obj, AFPERR_SHUTDOWN ); + + if (ibuflen < 5) + return send_reply(obj, AFPERR_BADVERS ); + + ibuf++; + ibuf++; /* pad */ + ibuf +=2; /* flag */ + + len = (unsigned char) *ibuf; + ibuf++; + ibuflen -= 5; + + i = get_version(obj, ibuf, ibuflen, len); + if (i) + return send_reply(obj, i ); + + if (ibuflen <= len) + return send_reply(obj, AFPERR_BADUAM); + + ibuf += len; + ibuflen -= len; + + len = (unsigned char) *ibuf; + ibuf++; + ibuflen--; + + if (!len || len > ibuflen) + return send_reply(obj, AFPERR_BADUAM); + + if ((afp_uam = auth_uamfind(UAM_SERVER_LOGIN, ibuf, len)) == NULL) + return send_reply(obj, AFPERR_BADUAM); + ibuf += len; + ibuflen -= len; + + if (!afp_uam->u.uam_login.login_ext) { + LOG(log_error, logtype_afpd, "login_ext: uam %s not AFP 3 ready!", afp_uam->uam_name ); + return send_reply(obj, AFPERR_BADUAM); + } + /* user name */ + if (ibuflen <= 1 +sizeof(len16)) + return send_reply(obj, AFPERR_PARAM); + type = *ibuf; + username = ibuf; + ibuf++; + ibuflen--; + if (type != 3) + return send_reply(obj, AFPERR_PARAM); + + memcpy(&len16, ibuf, sizeof(len16)); + ibuf += sizeof(len16); + ibuflen -= sizeof(len16); + len = ntohs(len16); + if (len > ibuflen) + return send_reply(obj, AFPERR_PARAM); + ibuf += len; + ibuflen -= len; + + /* directory service name */ + if (!ibuflen) + return send_reply(obj, AFPERR_PARAM); + type = *ibuf; + ibuf++; + ibuflen--; + + switch(type) { + case 1: + case 2: + if (!ibuflen) + return send_reply(obj, AFPERR_PARAM); + len = (unsigned char) *ibuf; + ibuf++; + ibuflen--; + break; + case 3: + /* With "No User Authen" it is equal */ + if (ibuflen < sizeof(len16)) + return send_reply(obj, AFPERR_PARAM); + memcpy(&len16, ibuf, sizeof(len16)); + ibuf += sizeof(len16); + ibuflen -= sizeof(len16); + len = ntohs(len16); + break; + default: + return send_reply(obj, AFPERR_PARAM); + } +#if 0 + if (len != 0) { + LOG(log_error, logtype_afpd, "login_ext: directory service path not null!" ); + return send_reply(obj, AFPERR_PARAM); + } +#endif + ibuf += len; + ibuflen -= len; + + /* Pad */ + if (ibuflen && ((unsigned long) ibuf & 1)) { /* pad character */ + ibuf++; + ibuflen--; + } + + if (AFP_OK != (i = create_session_key(obj)) ) { + return send_reply(obj, i); + } + + /* FIXME user name are in UTF8 */ + i = afp_uam->u.uam_login.login_ext(obj, username, &pwd, ibuf, ibuflen, rbuf, rbuflen); + + if (!pwd || ( i != AFP_OK && i != AFPERR_PWDEXPR)) + return send_reply(obj, i); + + return send_reply(obj, login(obj, pwd, afp_uam->u.uam_login.logout, ((i==AFPERR_PWDEXPR)?1:0))); +} + +/* ---------------------- */ +int afp_logincont(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + struct passwd *pwd = NULL; + int err; + + if ( afp_uam == NULL || afp_uam->u.uam_login.logincont == NULL || ibuflen < 2 ) { + *rbuflen = 0; + return send_reply(obj, AFPERR_NOTAUTH ); + } + + ibuf += 2; ibuflen -= 2; + err = afp_uam->u.uam_login.logincont(obj, &pwd, ibuf, ibuflen, + rbuf, rbuflen); + if (!pwd || ( err != AFP_OK && err != AFPERR_PWDEXPR)) + return send_reply(obj, err); + + return send_reply(obj, login(obj, pwd, afp_uam->u.uam_login.logout, ((err==AFPERR_PWDEXPR)?1:0))); +} + + +int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + DSI *dsi = (DSI *)(obj->dsi); + + LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username); + of_close_all_forks(obj); + close_all_vol(obj); + dsi->flags = DSI_AFP_LOGGED_OUT; + *rbuflen = 0; + + /* Send FCE login event */ + fce_register(obj, FCE_LOGOUT, "", NULL); + + return AFP_OK; +} + + + +/* change password -- + * NOTE: an FPLogin must already have completed successfully for this + * to work. this also does a little pre-processing before it hands + * it off to the uam. + */ +int afp_changepw(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + char username[MACFILELEN + 1], *start = ibuf; + struct uam_obj *uam; + struct passwd *pwd; + size_t len; + int ret; + + *rbuflen = 0; + ibuf += 2; + + /* check if password change is allowed, OS-X ignores the flag. + * we shouldn't trust the client on this anyway. + * not sure about the "right" error code, NOOP for now */ + if (!(obj->options.passwdbits & PASSWD_SET)) + return AFPERR_NOOP; + + /* make sure we can deal w/ this uam */ + len = (unsigned char) *ibuf++; + if ((uam = auth_uamfind(UAM_SERVER_CHANGEPW, ibuf, len)) == NULL) + return AFPERR_BADUAM; + + ibuf += len; + if ((len + 1) & 1) /* pad byte */ + ibuf++; + + if (obj->afp_version < 30) { + len = (unsigned char) *ibuf++; + if ( len > sizeof(username) - 1) { + return AFPERR_PARAM; + } + memcpy(username, ibuf, len); + username[ len ] = '\0'; + ibuf += len; + if ((len + 1) & 1) /* pad byte */ + ibuf++; + } else { + /* AFP > 3.0 doesn't pass the username, APF 3.1 specs page 124 */ + if ( ibuf[0] != '\0' || ibuf[1] != '\0') + return AFPERR_PARAM; + ibuf += 2; + len = MIN(sizeof(username) - 1, strlen(obj->username)); + memcpy(username, obj->username, len); + username[ len ] = '\0'; + } + + + LOG(log_info, logtype_afpd, "changing password for <%s>", username); + + if (( pwd = uam_getname( obj, username, sizeof(username))) == NULL ) + return AFPERR_PARAM; + + /* send it off to the uam. we really don't use ibuflen right now. */ + if (ibuflen < (size_t)(ibuf - start)) + return AFPERR_PARAM; + + ibuflen -= (ibuf - start); + ret = uam->u.uam_changepw(obj, username, pwd, ibuf, ibuflen, + rbuf, rbuflen); + LOG(log_info, logtype_afpd, "password change %s.", + (ret == AFPERR_AUTHCONT) ? "continued" : + (ret ? "failed" : "succeeded")); + if ( ret == AFP_OK ) + set_auth_switch(obj, 0); + + return ret; +} + + +/* FPGetUserInfo */ +int afp_getuserinfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + uint8_t thisuser; + uint32_t id; + uint16_t bitmap; + char *bitmapp; + + LOG(log_debug, logtype_afpd, "begin afp_getuserinfo:"); + + *rbuflen = 0; + ibuf++; + thisuser = *ibuf++; + ibuf += sizeof(id); /* userid is not used in AFP 2.0 */ + memcpy(&bitmap, ibuf, sizeof(bitmap)); + bitmap = ntohs(bitmap); + + /* deal with error cases. we don't have to worry about + * AFPERR_ACCESS or AFPERR_NOITEM as geteuid and getegid always + * succeed. */ + if (!thisuser) + return AFPERR_PARAM; + if ((bitmap & USERIBIT_ALL) != bitmap) + return AFPERR_BITMAP; + + /* remember place where we store the possibly modified bitmap later */ + memcpy(rbuf, ibuf, sizeof(bitmap)); + bitmapp = rbuf; + rbuf += sizeof(bitmap); + *rbuflen = sizeof(bitmap); + + /* copy the user/group info */ + if (bitmap & USERIBIT_USER) { + id = htonl(geteuid()); + memcpy(rbuf, &id, sizeof(id)); + rbuf += sizeof(id); + *rbuflen += sizeof(id); + } + + if (bitmap & USERIBIT_GROUP) { + id = htonl(getegid()); + memcpy(rbuf, &id, sizeof(id)); + rbuf += sizeof(id); + *rbuflen += sizeof(id); + } + + if (bitmap & USERIBIT_UUID) { + if ( ! (obj->options.flags & OPTION_UUID)) { + bitmap &= ~USERIBIT_UUID; + bitmap = htons(bitmap); + memcpy(bitmapp, &bitmap, sizeof(bitmap)); + } else { + LOG(log_debug, logtype_afpd, "afp_getuserinfo: get UUID for \'%s\'", obj->username); + int ret; + atalk_uuid_t uuid; + ret = getuuidfromname( obj->username, UUID_USER, uuid); + if (ret != 0) { + LOG(log_info, logtype_afpd, "afp_getuserinfo: error getting UUID !"); + return AFPERR_NOITEM; + } + LOG(log_debug, logtype_afpd, "afp_getuserinfo: got UUID: %s", uuid_bin2string(uuid)); + + memcpy(rbuf, uuid, UUID_BINSIZE); + rbuf += UUID_BINSIZE; + *rbuflen += UUID_BINSIZE; + } + } + + LOG(log_debug, logtype_afpd, "END afp_getuserinfo:"); + return AFP_OK; +} + +#define UAM_LIST(type) (((type) == UAM_SERVER_LOGIN || (type) == UAM_SERVER_LOGIN_EXT) ? &uam_login : \ + (((type) == UAM_SERVER_CHANGEPW) ? \ + &uam_changepw : NULL)) + +/* just do a linked list search. this could be sped up with a hashed + * list, but i doubt anyone's going to have enough uams to matter. */ +struct uam_obj *auth_uamfind(const int type, const char *name, + const int len) +{ + struct uam_obj *prev, *start; + + if (!name || !(start = UAM_LIST(type))) + return NULL; + + prev = start; + while ((prev = prev->uam_prev) != start) + if (strndiacasecmp(prev->uam_name, name, len) == 0) + return prev; + + return NULL; +} + +int auth_register(const int type, struct uam_obj *uam) +{ + struct uam_obj *start; + + if (!uam || !uam->uam_name || (*uam->uam_name == '\0')) + return -1; + + if (!(start = UAM_LIST(type))) + return 1; /* we don't know what to do with it, caller must free it */ + + uam_attach(start, uam); + return 0; +} + +/* load all of the modules */ +int auth_load(AFPObj *obj, const char *path, const char *list) +{ + char name[MAXPATHLEN + 1], buf[MAXPATHLEN + 1], *p, *last; + struct uam_mod *mod; + struct stat st; + size_t len; + + if (!path || !*path || !list || (len = strlen(path)) > sizeof(name) - 2) + return -1; + + LOG(log_debug, logtype_afpd, "auth_load: %s, %s", path, list); + + strlcpy(buf, list, sizeof(buf)); + if ((p = strtok_r(buf, ", ", &last)) == NULL) + return -1; + + strcpy(name, path); + if (name[len - 1] != '/') { + strcat(name, "/"); + len++; + } + + while (p) { + strlcpy(name + len, p, sizeof(name) - len); + LOG(log_debug, logtype_afpd, "uam: loading (%s)", name); + /* + if ((stat(name, &st) == 0) && (mod = uam_load(name, p))) { + */ + if (stat(name, &st) == 0) { + if ((mod = uam_load(obj, name, p))) { + uam_attach(&uam_modules, mod); + LOG(log_debug, logtype_afpd, "uam: %s loaded", p); + } else { + LOG(log_error, logtype_afpd, "uam: %s load failure",p); + } + } else { + LOG(log_info, logtype_afpd, "uam: uam not found (status=%d)", stat(name, &st)); + } + p = strtok_r(NULL, ", ", &last); + } + + return 0; +} + +/* get rid of all of the uams */ +void auth_unload(void) +{ + struct uam_mod *mod, *prev, *start = &uam_modules; + + prev = start->uam_prev; + while ((mod = prev) != start) { + prev = prev->uam_prev; + uam_detach(mod); + uam_unload(mod); + } +} diff --git a/etc/afpd/auth.h b/etc/afpd/auth.h new file mode 100644 index 0000000..f53513b --- /dev/null +++ b/etc/afpd/auth.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifndef AFPD_AUTH_H +#define AFPD_AUTH_H 1 + +#include + +#include + +struct afp_versions { + char *av_name; + int av_number; +}; + +static const struct afp_versions afp_versions[] = { + { "AFP2.2", 22 }, + { "AFPX03", 30 }, + { "AFP3.1", 31 }, + { "AFP3.2", 32 }, + { "AFP3.3", 33 }, + { "AFP3.4", 34 } +}; + +/* for GetUserInfo */ +#define USERIBIT_USER (1 << 0) +#define USERIBIT_GROUP (1 << 1) +#define USERIBIT_UUID (1 << 2) +#define USERIBIT_ALL (USERIBIT_USER | USERIBIT_GROUP | USERIBIT_UUID) + +extern uid_t uuid; +#if defined( sun ) && !defined( __svr4__ ) || defined( ultrix ) +extern int *groups; +#else /*sun __svr4__ ultrix*/ +extern gid_t *groups; +#endif /*sun __svr4__ ultrix*/ +extern int ngroups; + +/* FP functions */ +int afp_login (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_login_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_logincont (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_changepw (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_logout (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getuserinfo (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getsession (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_disconnect (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_zzz (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +#endif /* auth.h */ diff --git a/etc/afpd/catsearch.c b/etc/afpd/catsearch.c new file mode 100644 index 0000000..bec7b15 --- /dev/null +++ b/etc/afpd/catsearch.c @@ -0,0 +1,1094 @@ +/* + * Netatalk 2002 (c) + * Copyright (C) 1990, 1993 Regents of The University of Michigan + * Copyright (C) 2010 Frank Lahm + * All Rights Reserved. See COPYRIGHT + */ + + +/* + * This file contains FPCatSearch implementation. FPCatSearch performs + * file/directory search based on specified criteria. It is used by client + * to perform fast searches on (propably) big volumes. So, it has to be + * pretty fast. + * + * This implementation bypasses most of adouble/libatalk stuff as long as + * possible and does a standard filesystem search. It calls higher-level + * libatalk/afpd functions only when it is really needed, mainly while + * returning some non-UNIX information or filtering by non-UNIX criteria. + * + * Initial version written by Rafal Lewczuk + * + * Starting with Netatalk 2.2 searching by name criteria utilizes the + * CNID database in conjunction with an enhanced cnid_dbd. This requires + * the use of cnidscheme:dbd for the searched volume, the new functionality + * is not built into cnidscheme:cdb. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "desktop.h" +#include "directory.h" +#include "dircache.h" +#include "file.h" +#include "volume.h" +#include "filedir.h" +#include "fork.h" + + +struct finderinfo { + uint32_t f_type; + uint32_t creator; + uint16_t attrs; /* File attributes (high 8 bits)*/ + uint16_t label; /* Label (low 8 bits )*/ + char reserved[22]; /* Unknown (at least for now...) */ +}; + +typedef char packed_finder[ADEDLEN_FINDERI]; + +/* Known attributes: + * 0x04 - has a custom icon + * 0x20 - name/icon is locked + * 0x40 - is invisible + * 0x80 - is alias + * + * Known labels: + * 0x02 - project 2 + * 0x04 - project 1 + * 0x06 - personal + * 0x08 - cool + * 0x0a - in progress + * 0x0c - hot + * 0x0e - essential + */ + +/* This is our search-criteria structure. */ +struct scrit { + uint32_t rbitmap; /* Request bitmap - which values should we check ? */ + uint16_t fbitmap, dbitmap; /* file & directory bitmap - which values should we return ? */ + uint16_t attr; /* File attributes */ + time_t cdate; /* Creation date */ + time_t mdate; /* Last modification date */ + time_t bdate; /* Last backup date */ + uint32_t pdid; /* Parent DID */ + uint16_t offcnt; /* Offspring count */ + struct finderinfo finfo; /* Finder info */ + char lname[64]; /* Long name */ + char utf8name[514]; /* UTF8 or UCS2 name */ /* for convert_charset dest_len parameter +2 */ +}; + +/* + * Directory tree search is recursive by its nature. But AFP specification + * requires FPCatSearch to pause after returning n results and be able to + * resume the search later. So we have to do recursive search using flat + * (iterative) algorithm and remember all directories to look into in an + * stack-like structure. The structure below is one item of directory stack. + * + */ +struct dsitem { + cnid_t ds_did; /* CNID of this directory */ + int ds_checked; /* Have we checked this directory ? */ +}; + + +#define DS_BSIZE 128 +static int save_cidx = -1; /* Saved index of currently scanned directory. */ +static struct dsitem *dstack = NULL; /* Directory stack data... */ +static int dssize = 0; /* Directory stack (allocated) size... */ +static int dsidx = 0; /* First free item index... */ +static struct scrit c1, c2; /* search criteria */ + +/* Clears directory stack. */ +static void clearstack(void) +{ + save_cidx = -1; + while (dsidx > 0) { + dsidx--; + } +} + +/* Puts new item onto directory stack. */ +static int addstack(char *uname, struct dir *dir, int pidx) +{ + struct dsitem *ds; + struct dsitem *tmpds = NULL; + + /* check if we have some space on stack... */ + if (dsidx >= dssize) { + dssize += DS_BSIZE; + tmpds = realloc(dstack, dssize * sizeof(struct dsitem)); + if (tmpds == NULL) { + clearstack(); + free(dstack); + return -1; + } + dstack = tmpds; + } + + /* Put new element. Allocate and copy lname and path. */ + ds = dstack + dsidx++; + ds->ds_did = dir->d_did; + ds->ds_checked = 0; + return 0; +} + +/* Removes checked items from top of directory stack. Returns index of the first unchecked elements or -1. */ +static int reducestack(void) +{ + int r; + if (save_cidx != -1) { + r = save_cidx; + save_cidx = -1; + return r; + } + + while (dsidx > 0) { + if (dstack[dsidx-1].ds_checked) { + dsidx--; +// free(dstack[dsidx].path); + } else + return dsidx - 1; + } + return -1; +} + +/* Looks up for an opened adouble structure, opens resource fork of selected file. + * FIXME What about noadouble? +*/ +static struct adouble *adl_lkup(struct vol *vol, struct path *path, struct adouble *adp) +{ + static struct adouble ad; + + struct ofork *of; + int isdir; + + if (adp) + return adp; + + isdir = S_ISDIR(path->st.st_mode); + + if (!isdir && (of = of_findname(vol, path))) { + adp = of->of_ad; + } else { + ad_init(&ad, vol); + adp = &ad; + } + + if ( ad_metadata( path->u_name, ((isdir) ? ADFLAGS_DIR : 0), adp) < 0 ) { + adp = NULL; /* FIXME without resource fork adl_lkup will be call again */ + } + + return adp; +} + +/* -------------------- */ +static struct finderinfo *unpack_buffer(struct finderinfo *finfo, char *buffer) +{ + memcpy(&finfo->f_type, buffer +FINDERINFO_FRTYPEOFF, sizeof(finfo->f_type)); + memcpy(&finfo->creator, buffer +FINDERINFO_FRCREATOFF, sizeof(finfo->creator)); + memcpy(&finfo->attrs, buffer +FINDERINFO_FRFLAGOFF, sizeof(finfo->attrs)); + memcpy(&finfo->label, buffer +FINDERINFO_FRFLAGOFF, sizeof(finfo->label)); + finfo->attrs &= 0xff00; /* high 8 bits */ + finfo->label &= 0xff; /* low 8 bits */ + + return finfo; +} + +/* -------------------- */ +static struct finderinfo * +unpack_finderinfo(struct vol *vol, struct path *path, struct adouble **adp, struct finderinfo *finfo, int islnk) +{ + packed_finder buf; + void *ptr; + + *adp = adl_lkup(vol, path, *adp); + ptr = get_finderinfo(vol, path->u_name, *adp, &buf,islnk); + return unpack_buffer(finfo, ptr); +} + +/* -------------------- */ +#define CATPBIT_PARTIAL 31 +/* Criteria checker. This function returns a 2-bit value. */ +/* bit 0 means if checked file meets given criteria. */ +/* bit 1 means if it is a directory and we should descent into it. */ +/* uname - UNIX name + * fname - our fname (translated to UNIX) + * cidx - index in directory stack + */ +static int crit_check(struct vol *vol, struct path *path) { + int result = 0; + uint16_t attr, flags = CONV_PRECOMPOSE; + struct finderinfo *finfo = NULL, finderinfo; + struct adouble *adp = NULL; + time_t c_date, b_date; + uint32_t ac_date, ab_date; + static char convbuf[514]; /* for convert_charset dest_len parameter +2 */ + size_t len; + int islnk; + islnk=S_ISLNK(path->st.st_mode); + + if (S_ISDIR(path->st.st_mode)) { + if (!c1.dbitmap) + return 0; + } + else { + if (!c1.fbitmap) + return 0; + + /* compute the Mac name + * first try without id (it's slow to find it) + * An other option would be to call get_id in utompath but + * we need to pass parent dir + */ + if (!(path->m_name = utompath(vol, path->u_name, 0 , utf8_encoding(vol->v_obj)) )) { + /*retry with the right id */ + + cnid_t id; + + adp = adl_lkup(vol, path, adp); + id = get_id(vol, adp, &path->st, path->d_dir->d_did, path->u_name, strlen(path->u_name)); + if (!id) { + /* FIXME */ + return 0; + } + /* save the id for getfilparm */ + path->id = id; + if (!(path->m_name = utompath(vol, path->u_name, id , utf8_encoding(vol->v_obj)))) { + return 0; + } + } + } + + /* Kind of optimization: + * -- first check things we've already have - filename + * -- last check things we get from ad_open() + * FIXME strmcp strstr (icase) + */ + + /* Check for filename */ + if ((c1.rbitmap & (1<v_maccharset, CH_UCS2, path->m_name, -1, convbuf, 512)) ) + goto crit_check_ret; + + if ((c1.rbitmap & (1<m_name, strlen(path->m_name), convbuf, 512, &flags))) { + goto crit_check_ret; + } + + if (c1.rbitmap & (1< 0x7fffffff) + c2.mdate = 0x7fffffff; + if ((unsigned)c2.cdate > 0x7fffffff) + c2.cdate = 0x7fffffff; + if ((unsigned)c2.bdate > 0x7fffffff) + c2.bdate = 0x7fffffff; + + /* Check for modification date */ + if ((c1.rbitmap & (1<st.st_mtime < c1.mdate || path->st.st_mtime > c2.mdate) + goto crit_check_ret; + } + + /* Check for creation date... */ + if ((c1.rbitmap & (1<st.st_mtime; + adp = adl_lkup(vol, path, adp); + if (adp && ad_getdate(adp, AD_DATE_CREATE, &ac_date) >= 0) + c_date = AD_DATE_TO_UNIX(ac_date); + + if (c_date < c1.cdate || c_date > c2.cdate) + goto crit_check_ret; + } + + /* Check for backup date... */ + if ((c1.rbitmap & (1<st.st_mtime; + adp = adl_lkup(vol, path, adp); + if (adp && ad_getdate(adp, AD_DATE_BACKUP, &ab_date) >= 0) + b_date = AD_DATE_TO_UNIX(ab_date); + + if (b_date < c1.bdate || b_date > c2.bdate) + goto crit_check_ret; + } + + /* Check attributes */ + if ((c1.rbitmap & (1<f_type != c1.finfo.f_type) + goto crit_check_ret; + } + + /* Check creator ID */ + if ((c1.rbitmap & (1<creator != c1.finfo.creator) + goto crit_check_ret; + } + + /* Check finder info attributes */ + if ((c1.rbitmap & (1<attrs & c2.finfo.attrs) != c1.finfo.attrs) + goto crit_check_ret; + } + + /* Check label */ + if ((c1.rbitmap & (1<label & c2.finfo.label) != c1.finfo.label) + goto crit_check_ret; + } + /* FIXME: Attributes check ! */ + + /* All criteria are met. */ + result |= 1; +crit_check_ret: + if (adp != NULL) + ad_close(adp, ADFLAGS_HF); + return result; +} + +/* ------------------------------ */ +static int rslt_add (const AFPObj *obj, struct vol *vol, struct path *path, char **buf, int ext) +{ + + char *p = *buf; + int ret; + size_t tbuf =0; + uint16_t resultsize; + int isdir = S_ISDIR(path->st.st_mode); + + /* Skip resultsize */ + if (ext) { + p += sizeof(resultsize); + } + else { + p++; + } + *p++ = isdir ? FILDIRBIT_ISDIR : FILDIRBIT_ISFILE; /* IsDir ? */ + + if (ext) { + *p++ = 0; /* Pad */ + } + + if ( isdir ) { + ret = getdirparams(obj, vol, c1.dbitmap, path, path->d_dir, p , &tbuf ); + } + else { + /* FIXME slow if we need the file ID, we already know it, done ? */ + ret = getfilparams (obj, vol, c1.fbitmap, path, path->d_dir, p, &tbuf, 0); + } + + if ( ret != AFP_OK ) + return 0; + + /* Make sure entry length is even */ + if ((tbuf & 1)) { + *p++ = 0; + tbuf++; + } + + if (ext) { + resultsize = htons(tbuf); + memcpy ( *buf, &resultsize, sizeof(resultsize) ); + *buf += tbuf + 4; + } + else { + **buf = tbuf; + *buf += tbuf + 2; + } + + return 1; +} + +#define VETO_STR \ + "./../.AppleDouble/.AppleDB/Network Trash Folder/TheVolumeSettingsFolder/TheFindByContentFolder/.AppleDesktop/.Parent/" + +/*! + * This function performs a filesystem search + * + * Uses globals c1, c2, the search criteria + * + * @param vol (r) volume we are searching on ... + * @param dir (rw) directory we are starting from ... + * @param rmatches (r) maximum number of matches we can return + * @param pos (r) position we've stopped recently + * @param rbuf (w) output buffer + * @param nrecs (w) number of matches + * @param rsize (w) length of data written to output buffer + * @param ext (r) extended search flag + */ +#define NUM_ROUNDS 200 +static int catsearch(const AFPObj *obj, + struct vol *vol, + struct dir *dir, + int rmatches, + uint32_t *pos, + char *rbuf, + uint32_t *nrecs, + int *rsize, + int ext) +{ + static uint32_t cur_pos; /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */ + static DIR *dirpos; /* UNIX structure describing currently opened directory. */ + struct dir *currentdir; /* struct dir of current directory */ + int cidx, r; + struct dirent *entry; + int result = AFP_OK; + int ccr; + struct path path; + char *vpath = vol->v_path; + char *rrbuf = rbuf; + time_t start_time; + int num_rounds = NUM_ROUNDS; + int cwd = -1; + int error; + int unlen; + + if (*pos != 0 && *pos != cur_pos) { + result = AFPERR_CATCHNG; + goto catsearch_end; + } + + /* FIXME: Category "offspring count ! */ + + + /* We need to initialize all mandatory structures/variables and change working directory appropriate... */ + if (*pos == 0) { + clearstack(); + if (dirpos != NULL) { + closedir(dirpos); + dirpos = NULL; + } + + if (addstack(vpath, dir, -1) == -1) { + result = AFPERR_MISC; + goto catsearch_end; + } + /* FIXME: Sometimes DID is given by client ! (correct this one above !) */ + } + + /* Save current path */ + if ((cwd = open(".", O_RDONLY)) < 0) { + result = AFPERR_MISC; + goto catsearch_end; + } + + /* So we are beginning... */ + start_time = time(NULL); + + while ((cidx = reducestack()) != -1) { + if ((currentdir = dirlookup(vol, dstack[cidx].ds_did)) == NULL) { + result = AFPERR_MISC; + goto catsearch_end; + } + LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath)); + + error = movecwd(vol, currentdir); + + if (!error && dirpos == NULL) + dirpos = opendir("."); + + if (dirpos == NULL) + dirpos = opendir(cfrombstr(currentdir->d_fullpath)); + + if (error || dirpos == NULL) { + switch (errno) { + case EACCES: + dstack[cidx].ds_checked = 1; + continue; + case EMFILE: + case ENFILE: + case ENOENT: + result = AFPERR_NFILE; + break; + case ENOMEM: + case ENOTDIR: + default: + result = AFPERR_MISC; + } /* switch (errno) */ + goto catsearch_end; + } + + + while ((entry = readdir(dirpos)) != NULL) { + (*pos)++; + + if (!check_dirent(vol, entry->d_name)) + continue; + + LOG(log_debug, logtype_afpd, "catsearch(\"%s\"): dirent: \"%s\"", + cfrombstr(currentdir->d_fullpath), entry->d_name); + + memset(&path, 0, sizeof(path)); + path.u_name = entry->d_name; + if (of_stat(vol, &path) != 0) { + switch (errno) { + case EACCES: + case ELOOP: + case ENOENT: + continue; + case ENOTDIR: + case EFAULT: + case ENOMEM: + case ENAMETOOLONG: + default: + result = AFPERR_MISC; + goto catsearch_end; + } + } + switch (S_IFMT & path.st.st_mode) { + case S_IFDIR: + /* here we can short cut + ie if in the same loop the parent dir wasn't in the cache + ALL dirsearch_byname will fail. + */ + unlen = strlen(path.u_name); + path.d_dir = dircache_search_by_name(vol, + currentdir, + path.u_name, + unlen); + if (path.d_dir == NULL) { + /* path.m_name is set by adddir */ + if ((path.d_dir = dir_add(vol, + currentdir, + &path, + unlen)) == NULL) { + result = AFPERR_MISC; + goto catsearch_end; + } + } + path.m_name = cfrombstr(path.d_dir->d_m_name); + + if (addstack(path.u_name, path.d_dir, cidx) == -1) { + result = AFPERR_MISC; + goto catsearch_end; + } + break; + case S_IFREG: + path.d_dir = currentdir; + break; + default: + continue; + } + + ccr = crit_check(vol, &path); + + /* bit 0 means that criteria has been met */ + if ((ccr & 1)) { + r = rslt_add (obj, vol, &path, &rrbuf, ext); + + if (r == 0) { + result = AFPERR_MISC; + goto catsearch_end; + } + *nrecs += r; + /* Number of matches limit */ + if (--rmatches == 0) + goto catsearch_pause; + /* Block size limit */ + if (rrbuf - rbuf >= 448) + goto catsearch_pause; + } + /* MacOS 9 doesn't like servers executing commands longer than few seconds */ + if (--num_rounds <= 0) { + if (start_time != time(NULL)) { + result=AFP_OK; + goto catsearch_pause; + } + num_rounds = NUM_ROUNDS; + } + } /* while ((entry=readdir(dirpos)) != NULL) */ + closedir(dirpos); + dirpos = NULL; + dstack[cidx].ds_checked = 1; + } /* while (current_idx = reducestack()) != -1) */ + + /* We have finished traversing our tree. Return EOF here. */ + result = AFPERR_EOF; + goto catsearch_end; + +catsearch_pause: + cur_pos = *pos; + save_cidx = cidx; + +catsearch_end: /* Exiting catsearch: error condition */ + *rsize = rrbuf - rbuf; + if (cwd != -1) { + if ((fchdir(cwd)) != 0) { + LOG(log_debug, logtype_afpd, "error chdiring back: %s", strerror(errno)); + } + close(cwd); + } + return result; +} /* catsearch() */ + +/*! + * This function performs a CNID db search + * + * Uses globals c1, c2, the search criteria + * + * @param vol (r) volume we are searching on ... + * @param dir (rw) directory we are starting from ... + * @param uname (r) UNIX name of object to search + * @param rmatches (r) maximum number of matches we can return + * @param pos (r) position we've stopped recently + * @param rbuf (w) output buffer + * @param nrecs (w) number of matches + * @param rsize (w) length of data written to output buffer + * @param ext (r) extended search flag + */ +static int catsearch_db(const AFPObj *obj, + struct vol *vol, + struct dir *dir, + const char *uname, + int rmatches, + uint32_t *pos, + char *rbuf, + uint32_t *nrecs, + int *rsize, + int ext) +{ + static char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)]; + static uint32_t cur_pos; + static int num_matches; + int ccr ,r; + int result = AFP_OK; + struct path path; + char *rrbuf = rbuf; + char buffer[MAXPATHLEN +2]; + uint16_t flags = CONV_TOLOWER; + + LOG(log_debug, logtype_afpd, "catsearch_db(req pos: %u): {pos: %u, name: %s}", + *pos, cur_pos, uname); + + if (*pos != 0 && *pos != cur_pos) { + result = AFPERR_CATCHNG; + goto catsearch_end; + } + + if (cur_pos == 0 || *pos == 0) { + if (convert_charset(vol->v_volcharset, + vol->v_volcharset, + vol->v_maccharset, + uname, + strlen(uname), + buffer, + MAXPATHLEN, + &flags) == (size_t)-1) { + LOG(log_error, logtype_afpd, "catsearch_db: conversion error"); + result = AFPERR_MISC; + goto catsearch_end; + } + + LOG(log_debug, logtype_afpd, "catsearch_db: %s", buffer); + + AFP_CNID_START("cnid_find"); + num_matches = cnid_find(vol->v_cdb, + buffer, + strlen(uname), + resbuf, + sizeof(resbuf)); + AFP_CNID_DONE(); + if (num_matches == -1) { + result = AFPERR_MISC; + goto catsearch_end; + } + } + + while (cur_pos < num_matches) { + char *name; + cnid_t cnid, did; + char resolvebuf[12 + MAXPATHLEN + 1]; + struct dir *dir; + + /* Next CNID to process from buffer */ + memcpy(&cnid, resbuf + cur_pos * sizeof(cnid_t), sizeof(cnid_t)); + did = cnid; + + AFP_CNID_START("cnid_resolve"); + name = cnid_resolve(vol->v_cdb, &did, resolvebuf, 12 + MAXPATHLEN + 1); + AFP_CNID_DONE(); + if (name == NULL) + goto next; + + LOG(log_debug, logtype_afpd, "catsearch_db: {pos: %u, name:%s, cnid: %u}", + cur_pos, name, ntohl(cnid)); + if ((dir = dirlookup(vol, did)) == NULL) + goto next; + if (movecwd(vol, dir) < 0 ) + goto next; + + memset(&path, 0, sizeof(path)); + path.u_name = name; + path.m_name = utompath(vol, name, cnid, utf8_encoding(vol->v_obj)); + + if (of_stat(vol, &path) != 0) { + switch (errno) { + case EACCES: + case ELOOP: + goto next; + case ENOENT: + + default: + result = AFPERR_MISC; + goto catsearch_end; + } + } + /* For files path.d_dir is the parent dir, for dirs its the dir itself */ + if (S_ISDIR(path.st.st_mode)) + if ((dir = dirlookup(vol, cnid)) == NULL) + goto next; + path.d_dir = dir; + + LOG(log_maxdebug, logtype_afpd,"catsearch_db: dir: %s, cwd: %s, name: %s", + cfrombstr(dir->d_fullpath), getcwdpath(), path.u_name); + + /* At last we can check the search criteria */ + ccr = crit_check(vol, &path); + if ((ccr & 1)) { + LOG(log_debug, logtype_afpd,"catsearch_db: match: %s/%s", + getcwdpath(), path.u_name); + /* bit 1 means that criteria has been met */ + r = rslt_add(obj, vol, &path, &rrbuf, ext); + if (r == 0) { + result = AFPERR_MISC; + goto catsearch_end; + } + *nrecs += r; + /* Number of matches limit */ + if (--rmatches == 0) + goto catsearch_pause; + /* Block size limit */ + if (rrbuf - rbuf >= 448) + goto catsearch_pause; + } + next: + cur_pos++; + } /* while */ + + /* finished */ + result = AFPERR_EOF; + cur_pos = 0; + goto catsearch_end; + +catsearch_pause: + *pos = cur_pos; + +catsearch_end: /* Exiting catsearch: error condition */ + *rsize = rrbuf - rbuf; + LOG(log_debug, logtype_afpd, "catsearch_db(req pos: %u): {pos: %u}", *pos, cur_pos); + return result; +} + +/* -------------------------- */ +static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen, int ext) +{ + struct vol *vol; + uint16_t vid; + uint16_t spec_len; + uint32_t rmatches, reserved; + uint32_t catpos[4]; + uint32_t pdid = 0; + int ret, rsize; + uint32_t nrecs = 0; + unsigned char *spec1, *spec2, *bspec1, *bspec2; + size_t len; + uint16_t namelen; + uint16_t flags; + char tmppath[256]; + char *uname; + + *rbuflen = 0; + + /* min header size */ + if (ibuflen < 32) { + return AFPERR_PARAM; + } + + memset(&c1, 0, sizeof(c1)); + memset(&c2, 0, sizeof(c2)); + + ibuf += 2; + memcpy(&vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + + if ((vol = getvolbyvid(vid)) == NULL) { + return AFPERR_PARAM; + } + + memcpy(&rmatches, ibuf, sizeof(rmatches)); + rmatches = ntohl(rmatches); + ibuf += sizeof(rmatches); + + /* FIXME: (rl) should we check if reserved == 0 ? */ + ibuf += sizeof(reserved); + + memcpy(catpos, ibuf, sizeof(catpos)); + ibuf += sizeof(catpos); + + memcpy(&c1.fbitmap, ibuf, sizeof(c1.fbitmap)); + c1.fbitmap = c2.fbitmap = ntohs(c1.fbitmap); + ibuf += sizeof(c1.fbitmap); + + memcpy(&c1.dbitmap, ibuf, sizeof(c1.dbitmap)); + c1.dbitmap = c2.dbitmap = ntohs(c1.dbitmap); + ibuf += sizeof(c1.dbitmap); + + memcpy(&c1.rbitmap, ibuf, sizeof(c1.rbitmap)); + c1.rbitmap = c2.rbitmap = ntohl(c1.rbitmap); + ibuf += sizeof(c1.rbitmap); + + if (! (c1.fbitmap || c1.dbitmap)) { + return AFPERR_BITMAP; + } + + if ( ext) { + memcpy(&spec_len, ibuf, sizeof(spec_len)); + spec_len = ntohs(spec_len); + } + else { + /* with catsearch only name and parent id are allowed */ + c1.fbitmap &= (1<v_maccharset, CH_UCS2, tmppath, -1, c1.lname, sizeof(c1.lname)); + if (len == (size_t)(-1)) + return AFPERR_PARAM; + +#if 0 + /* FIXME: do we need it ? It's always null ! */ + memcpy(c2.lname, bspec2 + spec2[1] + 1, (bspec2 + spec2[1])[0]); + c2.lname[(bspec2 + spec2[1])[0]]= 0; +#endif + } + /* UTF8 Name */ + if (c1.rbitmap & (1 << FILPBIT_PDINFO)) { + + /* offset */ + memcpy(&namelen, spec1, sizeof(namelen)); + namelen = ntohs (namelen); + + spec1 = bspec1+namelen+4; /* Skip Unicode Hint */ + + /* length */ + memcpy(&namelen, spec1, sizeof(namelen)); + namelen = ntohs (namelen); + if (namelen > UTF8FILELEN_EARLY) /* Safeguard */ + namelen = UTF8FILELEN_EARLY; + + memcpy (c1.utf8name, spec1+2, namelen); + c1.utf8name[namelen] = 0; + if ((uname = mtoupath(vol, c1.utf8name, 0, utf8_encoding(obj))) == NULL) + return AFPERR_PARAM; + + /* convert charset */ + flags = CONV_PRECOMPOSE; + len = convert_charset(CH_UTF8_MAC, CH_UCS2, CH_UTF8, c1.utf8name, namelen, c1.utf8name, 512, &flags); + if (len == (size_t)(-1)) + return AFPERR_PARAM; + } + + /* Call search */ + *rbuflen = 24; + if ((c1.rbitmap & (1 << FILPBIT_PDINFO)) + && !(c1.rbitmap & (1<v_cnidscheme, "dbd") == 0) + && (vol->v_flags & AFPVOL_SEARCHDB)) + /* we've got a name and it's a dbd volume, so search CNID database */ + ret = catsearch_db(obj, vol, vol->v_root, uname, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext); + else + /* perform a slow filesystem tree search */ + ret = catsearch(obj, vol, vol->v_root, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext); + + memcpy(rbuf, catpos, sizeof(catpos)); + rbuf += sizeof(catpos); + + c1.fbitmap = htons(c1.fbitmap); + memcpy(rbuf, &c1.fbitmap, sizeof(c1.fbitmap)); + rbuf += sizeof(c1.fbitmap); + + c1.dbitmap = htons(c1.dbitmap); + memcpy(rbuf, &c1.dbitmap, sizeof(c1.dbitmap)); + rbuf += sizeof(c1.dbitmap); + + nrecs = htonl(nrecs); + memcpy(rbuf, &nrecs, sizeof(nrecs)); + rbuf += sizeof(nrecs); + *rbuflen += rsize; + + return ret; +} /* catsearch_afp */ + +/* -------------------------- */ +int afp_catsearch (AFPObj *obj, char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + return catsearch_afp( obj, ibuf, ibuflen, rbuf, rbuflen, 0); +} + + +int afp_catsearch_ext (AFPObj *obj, char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + return catsearch_afp( obj, ibuf, ibuflen, rbuf, rbuflen, 1); +} + +/* FIXME: we need a clean separation between afp stubs and 'real' implementation */ +/* (so, all buffer packing/unpacking should be done in stub, everything else + should be done in other functions) */ diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c new file mode 100644 index 0000000..5c56977 --- /dev/null +++ b/etc/afpd/desktop.c @@ -0,0 +1,1056 @@ +/* + * See COPYRIGHT. + * + * bug: + * afp_XXXcomment are (the only) functions able to open + * a ressource fork when there's no data fork, eg after + * it was removed with samba. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "volume.h" +#include "directory.h" +#include "fork.h" +#include "desktop.h" +#include "mangle.h" + +#define EXEC_MODE (S_IXGRP | S_IXUSR | S_IXOTH) + +int setdeskmode(const struct vol *vol, const mode_t mode) +{ + EC_INIT; + char wd[ MAXPATHLEN + 1]; + struct stat st; + char modbuf[ 12 + 1], *m; + struct dirent *deskp, *subp; + DIR *desk, *sub; + + if (!dir_rx_set(mode)) { + /* want to remove read and search access to owner it will screw the volume */ + return -1 ; + } + if ( getcwd( wd , MAXPATHLEN) == NULL ) { + return( -1 ); + } + + bstring dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); + + EC_NEG1( chdir(cfrombstr(dtpath)) ); + + if (( desk = opendir( "." )) == NULL ) { + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) ); + } + EC_FAIL; + } + for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) { + if ( strcmp( deskp->d_name, "." ) == 0 || + strcmp( deskp->d_name, ".." ) == 0 || strlen( deskp->d_name ) > 2 ) { + continue; + } + strcpy( modbuf, deskp->d_name ); + strcat( modbuf, "/" ); + m = strchr( modbuf, '\0' ); + if (( sub = opendir( deskp->d_name )) == NULL ) { + continue; + } + for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) { + if ( strcmp( subp->d_name, "." ) == 0 || + strcmp( subp->d_name, ".." ) == 0 ) { + continue; + } + *m = '\0'; + strcat( modbuf, subp->d_name ); + /* XXX: need to preserve special modes */ + if (lstat(modbuf, &st) < 0) { + LOG(log_error, logtype_afpd, "setdeskmode: stat %s: %s",fullpathname(modbuf), strerror(errno) ); + continue; + } + + if (S_ISDIR(st.st_mode)) { + if (ochmod(modbuf, + DIRBITS | mode, + &st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) ); + } + } else if (ochmod(modbuf, + mode & ~EXEC_MODE, + &st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) ); + } + + } + closedir( sub ); + /* XXX: need to preserve special modes */ + if (ochmod(deskp->d_name, + DIRBITS | mode, + NULL, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) ); + } + } + closedir( desk ); + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) ); + EC_FAIL; + } + /* XXX: need to preserve special modes */ + if (ochmod(bdata(dtpath), + DIRBITS | mode, + NULL, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno)); + } + +EC_CLEANUP: + bdestroy(dtpath); + EC_EXIT; +} + +int setdeskowner(const struct vol *vol, uid_t uid, gid_t gid) +{ + EC_INIT; + char wd[ MAXPATHLEN + 1]; + char modbuf[12 + 1], *m; + struct dirent *deskp, *subp; + DIR *desk, *sub; + + if ( getcwd( wd, MAXPATHLEN ) == NULL ) { + return( -1 ); + } + + bstring dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); + + EC_NEG1( chdir(cfrombstr(dtpath)) ); + + if (( desk = opendir( "." )) == NULL ) { + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) ); + } + EC_FAIL; + } + for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) { + if ( strcmp( deskp->d_name, "." ) == 0 || + strcmp( deskp->d_name, ".." ) == 0 || + strlen( deskp->d_name ) > 2 ) { + continue; + } + strcpy( modbuf, deskp->d_name ); + strcat( modbuf, "/" ); + m = strchr( modbuf, '\0' ); + if (( sub = opendir( deskp->d_name )) == NULL ) { + continue; + } + for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) { + if ( strcmp( subp->d_name, "." ) == 0 || + strcmp( subp->d_name, ".." ) == 0 ) { + continue; + } + *m = '\0'; + strcat( modbuf, subp->d_name ); + /* XXX: add special any uid, ignore group bits */ + if ( chown( modbuf, uid, gid ) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskown: chown %s: %s", fullpathname(modbuf), strerror(errno) ); + } + } + closedir( sub ); + /* XXX: add special any uid, ignore group bits */ + if ( chown( deskp->d_name, uid, gid ) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", + deskp->d_name, strerror(errno) ); + } + } + closedir( desk ); + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) ); + EC_FAIL; + } + if (chown(cfrombstr(dtpath), uid, gid ) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", fullpathname(".AppleDouble"), strerror(errno) ); + } + +EC_CLEANUP: + bdestroy(dtpath); + EC_EXIT; +} + +static void create_appledesktop_folder(const struct vol * vol) +{ + bstring olddtpath = NULL, dtpath = NULL; + struct stat st; + char *cmd_argv[4]; + + olddtpath = bfromcstr(vol->v_path); + bcatcstr(olddtpath, "/" APPLEDESKTOP); + + dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); + + if (lstat(cfrombstr(dtpath), &st) != 0) { + + become_root(); + + if (lstat(cfrombstr(olddtpath), &st) == 0) { + cmd_argv[0] = "mv"; + cmd_argv[1] = bdata(olddtpath); + cmd_argv[2] = bdata(dtpath); + cmd_argv[3] = NULL; + if (run_cmd("mv", cmd_argv) != 0) { + LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed", + bdata(olddtpath), bdata(dtpath)); + mkdir(cfrombstr(dtpath), 0777); + } + } else { + mkdir(cfrombstr(dtpath), 0777); + } + + unbecome_root(); + } + + bdestroy(dtpath); + bdestroy(olddtpath); +} + +int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + uint16_t vid; + + ibuf += 2; + + memcpy( &vid, ibuf, sizeof(vid)); + if (NULL == ( vol = getvolbyvid( vid )) ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + + create_appledesktop_folder(vol); + + memcpy( rbuf, &vid, sizeof(vid)); + *rbuflen = sizeof(vid); + return( AFP_OK ); +} + +int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + *rbuflen = 0; + return( AFP_OK ); +} + +static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 }; + +static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ]) +{ + return dtfile( vol, creator, ".icon" ); +} + +static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode) +{ + char *dtf, *adt, *adts; + + if ( si.sdt_fd != -1 ) { + if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 && + si.sdt_vid == vol->v_vid ) { + return 0; + } + close( si.sdt_fd ); + si.sdt_fd = -1; + } + + dtf = icon_dtfile( vol, creator); + + if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) { + if ( errno == ENOENT && ( flags & O_CREAT )) { + if (( adts = strrchr( dtf, '/' )) == NULL ) { + return -1; + } + *adts = '\0'; + if (( adt = strrchr( dtf, '/' )) == NULL ) { + return -1; + } + *adt = '\0'; + (void) ad_mkdir( dtf, DIRBITS | 0777 ); + *adt = '/'; + (void) ad_mkdir( dtf, DIRBITS | 0777 ); + *adts = '/'; + + if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) { + LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) ); + return -1; + } + } else { + return -1; + } + } + + memcpy( si.sdt_creator, creator, sizeof( CreatorType )); + si.sdt_vid = vol->v_vid; + si.sdt_index = 1; + return 0; +} + +int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p; + int itype, cc = AFP_OK, iovcnt = 0; + size_t buflen; + uint32_t ftype, itag; + uint16_t bsize, rsize, vid; + + buflen = *rbuflen; + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + cc = AFPERR_PARAM; + goto addicon_err; + } + + memcpy( fcreator, ibuf, sizeof( fcreator )); + ibuf += sizeof( fcreator ); + + memcpy( &ftype, ibuf, sizeof( ftype )); + ibuf += sizeof( ftype ); + + itype = (unsigned char) *ibuf; + ibuf += 2; + + memcpy( &itag, ibuf, sizeof( itag )); + ibuf += sizeof( itag ); + + memcpy( &bsize, ibuf, sizeof( bsize )); + bsize = ntohs( bsize ); + + if ( si.sdt_fd != -1 ) { + (void)close( si.sdt_fd ); + si.sdt_fd = -1; + } + + if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) { + cc = AFPERR_NOITEM; + goto addicon_err; + } + + if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) { + close(si.sdt_fd); + si.sdt_fd = -1; + LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) ); + cc = AFPERR_PARAM; + goto addicon_err; + } + + /* + * Read icon elements until we find a match to replace, or + * we get to the end to insert. + */ + p = imh; + memcpy( p, &itag, sizeof( itag )); + p += sizeof( itag ); + memcpy( p, &ftype, sizeof( ftype )); + p += sizeof( ftype ); + *p++ = itype; + *p++ = 0; + bsize = htons( bsize ); + memcpy( p, &bsize, sizeof( bsize )); + bsize = ntohs( bsize ); + while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) { + memcpy( &rsize, irh + 10, sizeof( rsize )); + rsize = ntohs( rsize ); + /* + * Is this our set of headers? + */ + if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) { + /* + * Is the size correct? + */ + if ( bsize != rsize ) + cc = AFPERR_ITYPE; + break; + } + + if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) ); + cc = AFPERR_PARAM; + } + } + + /* + * Some error occurred, return. + */ +addicon_err: + if ( cc < 0 ) { + dsi_writeinit(obj->dsi, rbuf, buflen); + dsi_writeflush(obj->dsi); + return cc; + } + + DSI *dsi = obj->dsi; + + iovcnt = dsi_writeinit(dsi, rbuf, buflen); + + /* add headers at end of file */ + if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) { + LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); + dsi_writeflush(dsi); + return AFPERR_PARAM; + } + + if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) { + LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); + dsi_writeflush(dsi); + return AFPERR_PARAM; + } + + while ((iovcnt = dsi_write(dsi, rbuf, buflen))) { + if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) { + LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); + dsi_writeflush(dsi); + return AFPERR_PARAM; + } + } + + close( si.sdt_fd ); + si.sdt_fd = -1; + return( AFP_OK ); +} + +static const u_char utag[] = { 0, 0, 0, 0 }; +static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/ +static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/ +static const short usize = 256; + +#if 0 +static const u_char uicon[] = { + 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00, + 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80, + 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20, + 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10, + 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, + 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10, + 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90, + 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50, + 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50, + 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90, + 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90, + 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50, + 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50, + 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50, + 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90, + 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80, + 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, +}; +#endif + +int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + unsigned char fcreator[ 4 ], ih[ 12 ]; + uint16_t vid, iindex, bsize; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy( fcreator, ibuf, sizeof( fcreator )); + ibuf += sizeof( fcreator ); + memcpy( &iindex, ibuf, sizeof( iindex )); + iindex = ntohs( iindex ); + + if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) { + if ( iindex > 1 ) { + return( AFPERR_NOITEM ); + } + memcpy( ih, utag, sizeof( utag )); + memcpy( ih + sizeof( utag ), utype, sizeof( utype )); + *( ih + sizeof( utag ) + sizeof( utype )) = 1; + *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0; + memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize, + sizeof( usize )); + memcpy( rbuf, ih, sizeof( ih )); + *rbuflen = sizeof( ih ); + return( AFP_OK ); + } + + if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) { + return( AFPERR_NOITEM ); + } + + if ( iindex < si.sdt_index ) { + if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) { + return( AFPERR_PARAM ); + } + si.sdt_index = 1; + } + + /* + * Position to the correct spot. + */ + for (;;) { + if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) { + close( si.sdt_fd ); + si.sdt_fd = -1; + return( AFPERR_NOITEM ); + } + memcpy( &bsize, ih + 10, sizeof( bsize )); + bsize = ntohs(bsize); + if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) ); + return( AFPERR_PARAM ); + } + if ( si.sdt_index == iindex ) { + memcpy( rbuf, ih, sizeof( ih )); + *rbuflen = sizeof( ih ); + return( AFP_OK ); + } + si.sdt_index++; + } +} + + +int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + off_t offset; + ssize_t rc, buflen; + u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ]; + uint16_t vid, bsize, rsize; + + buflen = *rbuflen; + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy( fcreator, ibuf, sizeof( fcreator )); + ibuf += sizeof( fcreator ); + memcpy( ftype, ibuf, sizeof( ftype )); + ibuf += sizeof( ftype ); + itype = (unsigned char) *ibuf++; + ibuf++; + memcpy( &bsize, ibuf, sizeof( bsize )); + bsize = ntohs( bsize ); + +#if 0 + if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 && + memcmp( ftype, utype, sizeof( utype )) == 0 && + itype == 1 && + bsize <= usize ) { + memcpy( rbuf, uicon, bsize); + *rbuflen = bsize; + return( AFP_OK ); + } +#endif + + if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) { + return( AFPERR_NOITEM ); + } + + if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) { + close(si.sdt_fd); + si.sdt_fd = -1; + LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno)); + return( AFPERR_PARAM ); + } + + si.sdt_index = 1; + offset = 0; + while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) { + si.sdt_index++; + offset += sizeof(ih); + if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 && + *(ih + sizeof( int ) + sizeof( ftype )) == itype ) { + break; + } + memcpy( &rsize, ih + 10, sizeof( rsize )); + rsize = ntohs( rsize ); + if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) ); + return( AFPERR_PARAM ); + } + offset += rsize; + } + + if ( rc < 0 ) { + LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno)); + return( AFPERR_PARAM ); + } + + if ( rc == 0 ) { + return( AFPERR_NOITEM ); + } + + memcpy( &rsize, ih + 10, sizeof( rsize )); + rsize = ntohs( rsize ); +#define min(a,b) ((a)<(b)?(a):(b)) + rc = min( bsize, rsize ); + + if (buflen < rc) { + DSI *dsi = obj->dsi; + struct stat st; + off_t size; + + size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size; + if (size < rc + offset) { + return AFPERR_PARAM; + } + +#ifndef WITH_SENDFILE + if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0) + goto geticon_exit; +#endif + + *rbuflen = buflen; + /* do to the streaming nature, we have to exit if we encounter + * a problem. much confusion results otherwise. */ + while (*rbuflen > 0) { +#ifdef WITH_SENDFILE + if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize, AFP_OK) < 0) { + switch (errno) { + case ENOSYS: + case EINVAL: /* there's no guarantee that all fs support sendfile */ + break; + default: + goto geticon_exit; + } + } + else { + dsi_readdone(dsi); + return AFP_OK; + } +#endif + buflen = read(si.sdt_fd, rbuf, *rbuflen); + if (buflen < 0) + goto geticon_exit; + + /* dsi_read() also returns buffer size of next allocation */ + buflen = dsi_read(dsi, rbuf, buflen); /* send it off */ + if (buflen < 0) + goto geticon_exit; + + *rbuflen = buflen; + } + + dsi_readdone(dsi); + return AFP_OK; + +geticon_exit: + LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno)); + dsi_readdone(dsi); + obj->exit(EXITERR_SYS); + return AFP_OK; + + } else { + if ( read( si.sdt_fd, rbuf, rc ) < rc ) { + return( AFPERR_PARAM ); + } + *rbuflen = rc; + } + return AFP_OK; +} + +/* ---------------------- */ +static const char hexdig[] = "0123456789abcdef"; +char *dtfile(const struct vol *vol, u_char creator[], char *ext ) +{ + static char path[ MAXPATHLEN + 1]; + char *p; + unsigned int i; + + strcpy( path, vol->v_dbpath ); + strcat( path, "/" APPLEDESKTOP "/" ); + for ( p = path; *p != '\0'; p++ ) + ; + + if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) { + *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ]; + *p++ = hexdig[ creator[ 0 ] & 0x0f ]; + } else { + *p++ = creator[ 0 ]; + } + + *p++ = '/'; + + for ( i = 0; i < sizeof( CreatorType ); i++ ) { + if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) { + *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ]; + *p++ = hexdig[ creator[ i ] & 0x0f ]; + } else { + *p++ = creator[ i ]; + } + } + *p = '\0'; + strcat( path, ext ); + + return( path ); +} + +/* --------------------------- + * mpath is only a filename + * did filename parent directory ID. +*/ + +char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8) +{ + static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */ + char *m, *u; + size_t inplen; + size_t outlen; + uint16_t flags; + + if ( *mpath == '\0' ) { + strcpy(upath, "."); + return upath; + } + + /* set conversion flags */ + flags = vol->v_mtou_flags; + + m = demangle(vol, mpath, did); + if (m != mpath) { + return m; + } + + m = mpath; + u = upath; + + inplen = strlen(m); + outlen = MAXPATHLEN; + + if ((size_t)-1 == (outlen = convert_charset ( (utf8)?CH_UTF8_MAC:vol->v_maccharset, vol->v_volcharset, vol->v_maccharset, m, inplen, u, outlen, &flags)) ) { + LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath); + return NULL; + } + +#ifdef DEBUG + LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath); +#endif /* DEBUG */ + return( upath ); +} + +/* --------------- + * id filename ID +*/ +char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8) +{ + static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */ + char *m, *u; + uint16_t flags; + size_t outlen; + + m = mpath; + outlen = strlen(upath); + + flags = vol->v_utom_flags; + + u = upath; + + /* convert charsets */ + if ((size_t)-1 == ( outlen = convert_charset ( vol->v_volcharset, (utf8)?CH_UTF8_MAC:vol->v_maccharset, vol->v_maccharset, u, outlen, mpath, MAXPATHLEN, &flags)) ) { + LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id)); + goto utompath_error; + } + + flags = !!(flags & CONV_REQMANGLE); + + if (utf8) + flags |= 2; + + m = mangle(vol, mpath, outlen, upath, id, flags); + +#ifdef DEBUG + LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id)); +#endif /* DEBUG */ + return(m); + +utompath_error: + u = "???"; + m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1); + return(m); +} + +/* ------------------------- */ +static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf) +{ + struct ofork *of; + char *name, *upath; + int isadir; + int clen; + struct adouble ad, *adp; + + clen = (u_char)*ibuf++; + clen = min( clen, 199 ); + + upath = path->u_name; + if (check_access(obj, vol, upath, OPENACC_WR ) < 0) { + return AFPERR_ACCESS; + } + + isadir = path_isadir(path); + if (isadir || !(of = of_findname(vol, path))) { + ad_init(&ad, vol); + adp = &ad; + } else + adp = of->of_ad; + + if (ad_open(adp, upath, + ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR, + 0666) < 0 ) { + return( AFPERR_ACCESS ); + } + + if (ad_getentryoff(adp, ADEID_COMMENT)) { + if ( (ad_get_MD_flags( adp ) & O_CREAT) ) { + if ( *path->m_name == '\0' ) { + name = (char *)curdir->d_m_name->data; + } else { + name = path->m_name; + } + ad_setname(adp, name); + } + ad_setentrylen( adp, ADEID_COMMENT, clen ); + memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen ); + ad_flush( adp ); + } + ad_close(adp, ADFLAGS_HF); + return( AFP_OK ); +} + +/* ----------------------------- */ +int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + struct path *path; + uint32_t did; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + if (NULL == ( path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + if ((u_long)ibuf & 1 ) { + ibuf++; + } + + return ad_addcomment(obj, vol, path, ibuf); +} + +/* -------------------- */ +static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen) +{ + struct adouble ad, *adp; + struct ofork *of; + char *upath; + int isadir; + int clen; + + upath = path->u_name; + isadir = path_isadir(path); + if (isadir || !(of = of_findname(vol, path))) { + ad_init(&ad, vol); + adp = &ad; + } else + adp = of->of_ad; + + if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) { + return( AFPERR_NOITEM ); + } + + if (!ad_getentryoff(adp, ADEID_COMMENT)) { + ad_close(adp, ADFLAGS_HF); + return AFPERR_NOITEM; + } + /* + * Make sure the AD file is not bogus. + */ + if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 || + ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) { + ad_close(adp, ADFLAGS_HF); + return( AFPERR_NOITEM ); + } + + clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */ + *rbuf++ = clen; + memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen); + *rbuflen = clen + 1; + ad_close(adp, ADFLAGS_HF); + + return( AFP_OK ); +} + +/* -------------------- */ +int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + struct path *s_path; + uint32_t did; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + return ad_getcomment(vol, s_path, rbuf, rbuflen); +} + +/* ----------------------- */ +static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path) +{ + struct adouble ad, *adp; + struct ofork *of; + int isadir; + char *upath; + + upath = path->u_name; + if (check_access(obj, vol, upath, OPENACC_WR ) < 0) { + return AFPERR_ACCESS; + } + + isadir = path_isadir(path); + if (isadir || !(of = of_findname(vol, path))) { + ad_init(&ad, vol); + adp = &ad; + } else + adp = of->of_ad; + + if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) { + switch ( errno ) { + case ENOENT : + return( AFPERR_NOITEM ); + case EACCES : + return( AFPERR_ACCESS ); + default : + return( AFPERR_PARAM ); + } + } + + if (ad_getentryoff(adp, ADEID_COMMENT)) { + ad_setentrylen( adp, ADEID_COMMENT, 0 ); + ad_flush( adp ); + } + ad_close(adp, ADFLAGS_HF); + return( AFP_OK ); +} + +/* ----------------------- */ +int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + struct path *s_path; + uint32_t did; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + if (NULL == ( s_path = cname( vol, dir, &ibuf ))) { + return get_afp_errno(AFPERR_NOOBJ); + } + + return ad_rmvcomment(obj, vol, s_path); +} diff --git a/etc/afpd/desktop.h b/etc/afpd/desktop.h new file mode 100644 index 0000000..5f82424 --- /dev/null +++ b/etc/afpd/desktop.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifndef AFPD_DESKTOP_H +#define AFPD_DESKTOP_H 1 + +#include + +#include "volume.h" + +#define APPLEDESKTOP ".AppleDesktop" + +struct savedt { + u_char sdt_creator[ 4 ]; + int sdt_fd; + int sdt_index; + short sdt_vid; +}; + +typedef unsigned char CreatorType[4]; + +extern char *dtfile (const struct vol *, u_char [], char *); +extern char *mtoupath (const struct vol *, char *, cnid_t, int utf8); +extern char *utompath (const struct vol *, char *, cnid_t, int utf8); + +extern int setdeskmode(const struct vol *vol, const mode_t mode); +extern int setdeskowner(const struct vol *vol, uid_t uid, gid_t gid); + +/* FP functions */ +int afp_opendt (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_addcomment (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getcomment (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_rmvcomment (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_addappl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_rmvappl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getappl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_closedt (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_addicon (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_geticoninfo (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_geticon (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +#endif diff --git a/etc/afpd/dircache.c b/etc/afpd/dircache.c new file mode 100644 index 0000000..c145616 --- /dev/null +++ b/etc/afpd/dircache.c @@ -0,0 +1,697 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dircache.h" +#include "directory.h" +#include "hash.h" + + +/* + * Directory Cache + * =============== + * + * Cache files and directories in a LRU cache. + * + * The directory cache caches directories and files(!). The main reason for having the cache + * is avoiding recursive walks up the path, querying the CNID database each time, when + * we have to calculate the location of eg directory with CNID 30, which is located in a dir with + * CNID 25, next CNID 20 and then CNID 2 (the volume root as per AFP spec). + * If all these dirs where in the cache, each database look up can be avoided. Additionally there's + * the element "fullpath" in struct dir, which is used to avoid the recursion in any case. Wheneveer + * a struct dir is initialized, the fullpath to the directory is stored there. + * + * In order to speed up the CNID query for files too, which eg happens when a directory is enumerated, + * files are stored too in the dircache. In order to differentiate between files and dirs, we set + * the flag DIRF_ISFILE in struct dir.d_flags for files. + * + * The most frequent codepatch that leads to caching is directory enumeration (cf enumerate.c): + * - if a element is a directory: + * (1) the cache is searched by dircache_search_by_name() + * (2) if it wasn't found a new struct dir is created and cached both from within dir_add() + * - for files the caching happens a little bit down the call chain: + * (3) first getfilparams() is called, which calls + * (4) getmetadata() where the cache is searched with dircache_search_by_name() + * (5) if the element is not found + * (6) get_id() queries the CNID from the database + * (7) then a struct dir is initialized via dir_new() (note the fullpath arg is NULL) + * (8) finally added to the cache with dircache_add() + * (2) of course does contain the steps 6,7 and 8. + * + * The dircache is a LRU cache, whenever it fills up we call dircache_evict internally which removes + * DIRCACHE_FREE_QUANTUM elements from the cache. + * + * There is only one cache for all volumes, so of course we use the volume id in hashing calculations. + * + * In order to avoid cache poisoning, we store the cached entries st_ctime from stat in + * struct dir.ctime_dircache. Later when we search the cache we compare the stored + * value with the result of a fresh stat. If the times differ, we remove the cached + * entry and return "no entry found in cache". + * A elements ctime changes when + * 1) the element is renamed + * (we loose the cached entry here, but it will expire when the cache fills) + * 2) its a directory and an object has been created therein + * 3) the element is deleted and recreated under the same name + * Using ctime leads to cache eviction in case 2) where it wouldn't be necessary, because + * the dir itself (name, CNID, ...) hasn't changed, but there's no other way. + * + * Indexes + * ======= + * + * The maximum dircache size is: + * max(DEFAULT_MAX_DIRCACHE_SIZE, min(size, MAX_POSSIBLE_DIRCACHE_SIZE)). + * It is a hashtable which we use to store "struct dir"s in. If the cache get full, oldest + * entries are evicted in chunks of DIRCACHE_FREE. + * + * We have/need two indexes: + * - a DID/name index on the main dircache, another hashtable + * - a queue index on the dircache, for evicting the oldest entries + * + * Debugging + * ========= + * + * Sending SIGINT to a afpd child causes it to dump the dircache to a file "/tmp/dircache.PID". + */ + +/******************************************************** + * Local funcs and variables + ********************************************************/ + +/***************************** + * the dircache */ + +static hash_t *dircache; /* The actual cache */ +static unsigned int dircache_maxsize; /* cache maximum size */ + +static struct dircache_stat { + unsigned long long lookups; + unsigned long long hits; + unsigned long long misses; + unsigned long long added; + unsigned long long removed; + unsigned long long expunged; + unsigned long long evicted; +} dircache_stat; + +/* FNV 1a */ +static hash_val_t hash_vid_did(const void *key) +{ + const struct dir *k = (const struct dir *)key; + hash_val_t hash = 2166136261; + + hash ^= k->d_vid >> 8; + hash *= 16777619; + hash ^= k->d_vid; + hash *= 16777619; + + hash ^= k->d_did >> 24; + hash *= 16777619; + hash ^= (k->d_did >> 16) & 0xff; + hash *= 16777619; + hash ^= (k->d_did >> 8) & 0xff; + hash *= 16777619; + hash ^= (k->d_did >> 0) & 0xff; + hash *= 16777619; + + return hash; +} + +static int hash_comp_vid_did(const void *key1, const void *key2) +{ + const struct dir *k1 = key1; + const struct dir *k2 = key2; + + return !(k1->d_did == k2->d_did && k1->d_vid == k2->d_vid); +} + +/************************************************** + * DID/name index on dircache (another hashtable) */ + +static hash_t *index_didname; + +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif + +static hash_val_t hash_didname(const void *p) +{ + const struct dir *key = (const struct dir *)p; + const unsigned char *data = key->d_u_name->data; + int len = key->d_u_name->slen; + hash_val_t hash = key->d_pdid + key->d_vid; + hash_val_t tmp; + + int rem = len & 3; + len >>= 2; + + /* Main loop */ + for (;len > 0; len--) { + hash += get16bits (data); + tmp = (get16bits (data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2*sizeof (uint16_t); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) { + case 3: hash += get16bits (data); + hash ^= hash << 16; + hash ^= data[sizeof (uint16_t)] << 18; + hash += hash >> 11; + break; + case 2: hash += get16bits (data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += *data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; +} + +static int hash_comp_didname(const void *k1, const void *k2) +{ + const struct dir *key1 = (const struct dir *)k1; + const struct dir *key2 = (const struct dir *)k2; + + return ! (key1->d_vid == key2->d_vid + && key1->d_pdid == key2->d_pdid + && (bstrcmp(key1->d_u_name, key2->d_u_name) == 0) ); +} + +/*************************** + * queue index on dircache */ + +static q_t *index_queue; /* the index itself */ +static unsigned long queue_count; + +/*! + * @brief Remove a fixed number of (oldest) entries from the cache and indexes + * + * The default is to remove the 256 oldest entries from the cache. + * 1. Get the oldest entry + * 2. If it's in use ie open forks reference it or it's curdir requeue it, + * dont remove it + * 3. Remove the dir from the main cache and the didname index + * 4. Free the struct dir structure and all its members + */ +static void dircache_evict(void) +{ + int i = DIRCACHE_FREE_QUANTUM; + struct dir *dir; + + LOG(log_debug, logtype_afpd, "dircache: {starting cache eviction}"); + + while (i--) { + if ((dir = (struct dir *)dequeue(index_queue)) == NULL) { /* 1 */ + dircache_dump(); + AFP_PANIC("dircache_evict"); + } + queue_count--; + + if (curdir == dir) { /* 2 */ + if ((dir->qidx_node = enqueue(index_queue, dir)) == NULL) { + dircache_dump(); + AFP_PANIC("dircache_evict"); + } + queue_count++; + continue; + } + + dircache_remove(NULL, dir, DIRCACHE | DIDNAME_INDEX); /* 3 */ + dir_free(dir); /* 4 */ + } + + AFP_ASSERT(queue_count == dircache->hash_nodecount); + dircache_stat.evicted += DIRCACHE_FREE_QUANTUM; + LOG(log_debug, logtype_afpd, "dircache: {finished cache eviction}"); +} + + +/******************************************************** + * Interface + ********************************************************/ + +/*! + * @brief Search the dircache via a CNID for a directory + * + * Found cache entries are expunged if both the parent directory st_ctime and the objects + * st_ctime are modified. + * This func builds on the fact, that all our code only ever needs to and does search + * the dircache by CNID expecting directories to be returned, but not files. + * Thus + * (1) if we find a file for a given CNID we + * (1a) remove it from the cache + * (1b) return NULL indicating nothing found + * (2) we can then use d_fullpath to stat the directory + * + * @param vol (r) pointer to struct vol + * @param cnid (r) CNID of the directory to search + * + * @returns Pointer to struct dir if found, else NULL + */ +struct dir *dircache_search_by_did(const struct vol *vol, cnid_t cnid) +{ + struct dir *cdir = NULL; + struct dir key; + struct stat st; + hnode_t *hn; + + AFP_ASSERT(vol); + AFP_ASSERT(ntohl(cnid) >= CNID_START); + + dircache_stat.lookups++; + key.d_vid = vol->v_vid; + key.d_did = cnid; + if ((hn = hash_lookup(dircache, &key))) + cdir = hnode_get(hn); + + if (cdir) { + if (cdir->d_flags & DIRF_ISFILE) { /* (1) */ + LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {not a directory:\"%s\"}", + ntohl(cnid), cfrombstr(cdir->d_u_name)); + (void)dir_remove(vol, cdir); /* (1a) */ + dircache_stat.expunged++; + return NULL; /* (1b) */ + + } + if (ostat(cfrombstr(cdir->d_fullpath), &st, vol_syml_opt(vol)) != 0) { + LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {missing:\"%s\"}", + ntohl(cnid), cfrombstr(cdir->d_fullpath)); + (void)dir_remove(vol, cdir); + dircache_stat.expunged++; + return NULL; + } + if ((cdir->dcache_ctime != st.st_ctime) || (cdir->dcache_ino != st.st_ino)) { + LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {modified:\"%s\"}", + ntohl(cnid), cfrombstr(cdir->d_u_name)); + (void)dir_remove(vol, cdir); + dircache_stat.expunged++; + return NULL; + } + LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {cached: path:\"%s\"}", + ntohl(cnid), cfrombstr(cdir->d_fullpath)); + dircache_stat.hits++; + } else { + LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {not in cache}", ntohl(cnid)); + dircache_stat.misses++; + } + + return cdir; +} + +/*! + * @brief Search the cache via did/name hashtable + * + * Found cache entries are expunged if both the parent directory st_ctime and the objects + * st_ctime are modified. + * + * @param vol (r) volume + * @param dir (r) directory + * @param name (r) name (server side encoding) + * @parma len (r) strlen of name + * + * @returns pointer to struct dir if found in cache, else NULL + */ +struct dir *dircache_search_by_name(const struct vol *vol, + const struct dir *dir, + char *name, + int len) +{ + struct dir *cdir = NULL; + struct dir key; + struct stat st; + + hnode_t *hn; + static_bstring uname = {-1, len, (unsigned char *)name}; + + AFP_ASSERT(vol); + AFP_ASSERT(dir); + AFP_ASSERT(name); + AFP_ASSERT(len == strlen(name)); + AFP_ASSERT(len < 256); + + dircache_stat.lookups++; + LOG(log_debug, logtype_afpd, "dircache_search_by_name(did:%u, \"%s\")", + ntohl(dir->d_did), name); + + if (dir->d_did != DIRDID_ROOT_PARENT) { + key.d_vid = vol->v_vid; + key.d_pdid = dir->d_did; + key.d_u_name = &uname; + + if ((hn = hash_lookup(index_didname, &key))) + cdir = hnode_get(hn); + } + + if (cdir) { + if (ostat(cfrombstr(cdir->d_fullpath), &st, vol_syml_opt(vol)) != 0) { + LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {missing:\"%s\"}", + ntohl(dir->d_did), name, cfrombstr(cdir->d_fullpath)); + (void)dir_remove(vol, cdir); + dircache_stat.expunged++; + return NULL; + } + + /* Remove modified directories and files */ + if ((cdir->dcache_ctime != st.st_ctime) || (cdir->dcache_ino != st.st_ino)) { + LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {modified}", + ntohl(dir->d_did), name); + (void)dir_remove(vol, cdir); + dircache_stat.expunged++; + return NULL; + } + LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {found in cache}", + ntohl(dir->d_did), name); + dircache_stat.hits++; + } else { + LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {not in cache}", + ntohl(dir->d_did), name); + dircache_stat.misses++; + } + + return cdir; +} + +/*! + * @brief create struct dir from struct path + * + * Add a struct dir to the cache and its indexes. + * + * @param dir (r) pointer to parrent directory + * + * @returns 0 on success, -1 on error which should result in an abort + */ +int dircache_add(const struct vol *vol, + struct dir *dir) +{ + struct dir key; + hnode_t *hn; + + AFP_ASSERT(dir); + AFP_ASSERT(ntohl(dir->d_pdid) >= 2); + AFP_ASSERT(ntohl(dir->d_did) >= CNID_START); + AFP_ASSERT(dir->d_u_name); + AFP_ASSERT(dir->d_vid); + AFP_ASSERT(dircache->hash_nodecount <= dircache_maxsize); + + /* Check if cache is full */ + if (dircache->hash_nodecount == dircache_maxsize) + dircache_evict(); + + /* + * Make sure we don't add duplicates + */ + + /* Search primary cache by CNID */ + key.d_vid = dir->d_vid; + key.d_did = dir->d_did; + if ((hn = hash_lookup(dircache, &key))) { + /* Found an entry with the same CNID, delete it */ + dir_remove(vol, hnode_get(hn)); + dircache_stat.expunged++; + } + key.d_vid = vol->v_vid; + key.d_pdid = dir->d_pdid; + key.d_u_name = dir->d_u_name; + if ((hn = hash_lookup(index_didname, &key))) { + /* Found an entry with the same DID/name, delete it */ + dir_remove(vol, hnode_get(hn)); + dircache_stat.expunged++; + } + + /* Add it to the main dircache */ + if (hash_alloc_insert(dircache, dir, dir) == 0) { + dircache_dump(); + exit(EXITERR_SYS); + } + + /* Add it to the did/name index */ + if (hash_alloc_insert(index_didname, dir, dir) == 0) { + dircache_dump(); + exit(EXITERR_SYS); + } + + /* Add it to the fifo queue index */ + if ((dir->qidx_node = enqueue(index_queue, dir)) == NULL) { + dircache_dump(); + exit(EXITERR_SYS); + } else { + queue_count++; + } + + dircache_stat.added++; + LOG(log_debug, logtype_afpd, "dircache(did:%u,'%s'): {added}", + ntohl(dir->d_did), cfrombstr(dir->d_u_name)); + + AFP_ASSERT(queue_count == index_didname->hash_nodecount + && queue_count == dircache->hash_nodecount); + + return 0; +} + +/*! + * @brief Remove an entry from the dircache + * + * Callers outside of dircache.c should call this with + * flags = QUEUE_INDEX | DIDNAME_INDEX | DIRCACHE. + */ +void dircache_remove(const struct vol *vol _U_, struct dir *dir, int flags) +{ + hnode_t *hn; + + AFP_ASSERT(dir); + AFP_ASSERT((flags & ~(QUEUE_INDEX | DIDNAME_INDEX | DIRCACHE)) == 0); + + if (flags & QUEUE_INDEX) { + /* remove it from the queue index */ + dequeue(dir->qidx_node->prev); /* this effectively deletes the dequeued node */ + queue_count--; + } + + if (flags & DIDNAME_INDEX) { + if ((hn = hash_lookup(index_didname, dir)) == NULL) { + LOG(log_error, logtype_afpd, "dircache_remove(%u,\"%s\"): not in didname index", + ntohl(dir->d_did), cfrombstr(dir->d_u_name)); + dircache_dump(); + AFP_PANIC("dircache_remove"); + } + hash_delete_free(index_didname, hn); + } + + if (flags & DIRCACHE) { + if ((hn = hash_lookup(dircache, dir)) == NULL) { + LOG(log_error, logtype_afpd, "dircache_remove(%u,\"%s\"): not in dircache", + ntohl(dir->d_did), cfrombstr(dir->d_u_name)); + dircache_dump(); + AFP_PANIC("dircache_remove"); + } + hash_delete_free(dircache, hn); + } + + LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {removed}", + ntohl(dir->d_did), cfrombstr(dir->d_u_name)); + + dircache_stat.removed++; + AFP_ASSERT(queue_count == index_didname->hash_nodecount + && queue_count == dircache->hash_nodecount); +} + +/*! + * @brief Initialize the dircache and indexes + * + * This is called in child afpd initialisation. The maximum cache size will be + * max(DEFAULT_MAX_DIRCACHE_SIZE, min(size, MAX_POSSIBLE_DIRCACHE_SIZE)). + * It initializes a hashtable which we use to store a directory cache in. + * It also initializes two indexes: + * - a DID/name index on the main dircache + * - a queue index on the dircache + * + * @param size (r) requested maximum size from afp.conf + * + * @return 0 on success, -1 on error + */ +int dircache_init(int reqsize) +{ + dircache_maxsize = DEFAULT_MAX_DIRCACHE_SIZE; + + /* Initialize the main dircache */ + if (reqsize > DEFAULT_MAX_DIRCACHE_SIZE && reqsize < MAX_POSSIBLE_DIRCACHE_SIZE) { + while ((dircache_maxsize < MAX_POSSIBLE_DIRCACHE_SIZE) && (dircache_maxsize < reqsize)) + dircache_maxsize *= 2; + } + if ((dircache = hash_create(dircache_maxsize, hash_comp_vid_did, hash_vid_did)) == NULL) + return -1; + + LOG(log_debug, logtype_afpd, "dircache_init: done. max dircache size: %u", dircache_maxsize); + + /* Initialize did/name index hashtable */ + if ((index_didname = hash_create(dircache_maxsize, hash_comp_didname, hash_didname)) == NULL) + return -1; + + /* Initialize index queue */ + if ((index_queue = queue_init()) == NULL) + return -1; + else + queue_count = 0; + + /* Initialize index queue */ + if ((invalid_dircache_entries = queue_init()) == NULL) + return -1; + + /* As long as directory.c hasn't got its own initializer call, we do it for it */ + rootParent.d_did = DIRDID_ROOT_PARENT; + rootParent.d_fullpath = bfromcstr("ROOT_PARENT"); + rootParent.d_m_name = bfromcstr("ROOT_PARENT"); + rootParent.d_u_name = rootParent.d_m_name; + rootParent.d_rights_cache = 0xffffffff; + + return 0; +} + +/*! + * Log dircache statistics + */ +void log_dircache_stat(void) +{ + LOG(log_info, logtype_afpd, "dircache statistics: " + "entries: %lu, lookups: %llu, hits: %llu, misses: %llu, added: %llu, removed: %llu, expunged: %llu, evicted: %llu", + queue_count, + dircache_stat.lookups, + dircache_stat.hits, + dircache_stat.misses, + dircache_stat.added, + dircache_stat.removed, + dircache_stat.expunged, + dircache_stat.evicted); +} + +/*! + * @brief Dump dircache to /tmp/dircache.PID + */ +void dircache_dump(void) +{ + char tmpnam[64]; + FILE *dump; + qnode_t *n = index_queue->next; + hnode_t *hn; + hscan_t hs; + const struct dir *dir; + int i; + + LOG(log_warning, logtype_afpd, "Dumping directory cache..."); + + sprintf(tmpnam, "/tmp/dircache.%u", getpid()); + if ((dump = fopen(tmpnam, "w+")) == NULL) { + LOG(log_error, logtype_afpd, "dircache_dump: %s", strerror(errno)); + return; + } + setbuf(dump, NULL); + + fprintf(dump, "Number of cache entries in LRU queue: %lu\n", queue_count); + fprintf(dump, "Configured maximum cache size: %u\n\n", dircache_maxsize); + + fprintf(dump, "Primary CNID index:\n"); + fprintf(dump, " VID DID CNID STAT PATH\n"); + fprintf(dump, "====================================================================\n"); + hash_scan_begin(&hs, dircache); + i = 1; + while ((hn = hash_scan_next(&hs))) { + dir = hnode_get(hn); + fprintf(dump, "%05u: %3u %6u %6u %s %s\n", + i++, + ntohs(dir->d_vid), + ntohl(dir->d_pdid), + ntohl(dir->d_did), + dir->d_flags & DIRF_ISFILE ? "f" : "d", + cfrombstr(dir->d_fullpath)); + } + + fprintf(dump, "\nSecondary DID/name index:\n"); + fprintf(dump, " VID DID CNID STAT PATH\n"); + fprintf(dump, "====================================================================\n"); + hash_scan_begin(&hs, index_didname); + i = 1; + while ((hn = hash_scan_next(&hs))) { + dir = hnode_get(hn); + fprintf(dump, "%05u: %3u %6u %6u %s %s\n", + i++, + ntohs(dir->d_vid), + ntohl(dir->d_pdid), + ntohl(dir->d_did), + dir->d_flags & DIRF_ISFILE ? "f" : "d", + cfrombstr(dir->d_fullpath)); + } + + fprintf(dump, "\nLRU Queue:\n"); + fprintf(dump, " VID DID CNID STAT PATH\n"); + fprintf(dump, "====================================================================\n"); + + for (i = 1; i <= queue_count; i++) { + if (n == index_queue) + break; + dir = (struct dir *)n->data; + fprintf(dump, "%05u: %3u %6u %6u %s %s\n", + i, + ntohs(dir->d_vid), + ntohl(dir->d_pdid), + ntohl(dir->d_did), + dir->d_flags & DIRF_ISFILE ? "f" : "d", + cfrombstr(dir->d_fullpath)); + n = n->next; + } + + fprintf(dump, "\n"); + fflush(dump); + fclose(dump); + return; +} diff --git a/etc/afpd/dircache.h b/etc/afpd/dircache.h new file mode 100644 index 0000000..0b79da0 --- /dev/null +++ b/etc/afpd/dircache.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. + */ + +#ifndef DIRCACHE_H +#define DIRCACHE_H + +#include + +#include +#include + +/* Maximum size of the dircache hashtable */ +#define MAX_POSSIBLE_DIRCACHE_SIZE 131072 +#define DIRCACHE_FREE_QUANTUM 256 + +/* flags for dircache_remove */ +#define DIRCACHE (1 << 0) +#define DIDNAME_INDEX (1 << 1) +#define QUEUE_INDEX (1 << 2) +#define DIRCACHE_ALL (DIRCACHE|DIDNAME_INDEX|QUEUE_INDEX) + +extern int dircache_init(int reqsize); +extern int dircache_add(const struct vol *, struct dir *); +extern void dircache_remove(const struct vol *, struct dir *, int flag); +extern struct dir *dircache_search_by_did(const struct vol *vol, cnid_t did); +extern struct dir *dircache_search_by_name(const struct vol *, const struct dir *dir, char *name, int len); +extern void dircache_dump(void); +extern void log_dircache_stat(void); +#endif /* DIRCACHE_H */ diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c new file mode 100644 index 0000000..470cfb0 --- /dev/null +++ b/etc/afpd/directory.c @@ -0,0 +1,2637 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "directory.h" +#include "dircache.h" +#include "desktop.h" +#include "volume.h" +#include "fork.h" +#include "file.h" +#include "filedir.h" +#include "unix.h" +#include "mangle.h" +#include "hash.h" + +/* + * FIXMEs, loose ends after the dircache rewrite: + * o merge dircache_search_by_name and dir_add ?? + * o case-insensitivity is gone from cname + */ + + +/******************************************************************************************* + * Globals + ******************************************************************************************/ + +int afp_errno; +/* As long as directory.c hasn't got its own init call, this get initialized in dircache_init */ +struct dir rootParent = { + NULL, NULL, NULL, NULL, /* path, d_m_name, d_u_name, d_m_name_ucs2 */ + NULL, 0, 0, /* qidx_node, ctime, d_flags */ + 0, 0, 0, 0 /* pdid, did, offcnt, d_vid */ +}; +struct dir *curdir = &rootParent; +struct path Cur_Path = { + 0, + "", /* mac name */ + ".", /* unix name */ + 0, /* id */ + NULL,/* struct dir * */ + 0, /* stat is not set */ + 0, /* errno */ + {0} /* struct stat */ +}; + +/* + * dir_remove queues struct dirs to be freed here. We can't just delete them immeidately + * eg in dircache_search_by_id, because a caller somewhere up the stack might be + * referencing it. + * So instead: + * - we mark it as invalid by setting d_did to CNID_INVALID (ie 0) + * - queue it in "invalid_dircache_entries" queue + * - which is finally freed at the end of every AFP func in afp_dsi.c. + */ +q_t *invalid_dircache_entries; + + +/******************************************************************************************* + * Locals + ******************************************************************************************/ + + +/* ------------------------- + appledouble mkdir afp error code. +*/ +static int netatalk_mkdir(const struct vol *vol, const char *name) +{ + int ret; + struct stat st; + + if (vol->v_flags & AFPVOL_UNIX_PRIV) { + if (lstat(".", &st) < 0) + return AFPERR_MISC; + int mode = (DIRBITS & (~S_ISGID & st.st_mode)) | (0777 & ~vol->v_umask); + LOG(log_maxdebug, logtype_afpd, "netatalk_mkdir(\"%s\") {parent mode: %04o, vol umask: %04o}", + name, st.st_mode, vol->v_umask); + + ret = mkdir(name, mode); + } else { + ret = ad_mkdir(name, DIRBITS | 0777); + } + + if (ret < 0) { + switch ( errno ) { + case ENOENT : + return( AFPERR_NOOBJ ); + case EROFS : + return( AFPERR_VLOCK ); + case EPERM: + case EACCES : + return( AFPERR_ACCESS ); + case EEXIST : + return( AFPERR_EXIST ); + case ENOSPC : + case EDQUOT : + return( AFPERR_DFULL ); + default : + return( AFPERR_PARAM ); + } + } + return AFP_OK; +} + +/* ------------------- */ +static int deletedir(const struct vol *vol, int dirfd, char *dir) +{ + char path[MAXPATHLEN + 1]; + DIR *dp; + struct dirent *de; + struct stat st; + size_t len; + int err = AFP_OK; + size_t remain; + + if ((len = strlen(dir)) +2 > sizeof(path)) + return AFPERR_PARAM; + + /* already gone */ + if ((dp = opendirat(dirfd, dir)) == NULL) + return AFP_OK; + + strcpy(path, dir); + strcat(path, "/"); + len++; + remain = sizeof(path) -len -1; + while ((de = readdir(dp)) && err == AFP_OK) { + /* skip this and previous directory */ + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + + if (strlen(de->d_name) > remain) { + err = AFPERR_PARAM; + break; + } + strcpy(path + len, de->d_name); + if (ostatat(dirfd, path, &st, vol_syml_opt(vol))) { + continue; + } + if (S_ISDIR(st.st_mode)) { + err = deletedir(vol, dirfd, path); + } else { + err = netatalk_unlinkat(dirfd, path); + } + } + closedir(dp); + + /* okay. the directory is empty. delete it. note: we already got rid + of .AppleDouble. */ + if (err == AFP_OK) { + err = netatalk_rmdir(dirfd, dir); + } + return err; +} + +/* do a recursive copy. */ +static int copydir(struct vol *vol, struct dir *ddir, int dirfd, char *src, char *dst) +{ + char spath[MAXPATHLEN + 1], dpath[MAXPATHLEN + 1]; + DIR *dp; + struct dirent *de; + struct stat st; + struct utimbuf ut; + size_t slen, dlen; + size_t srem, drem; + int err; + + /* doesn't exist or the path is too long. */ + if (((slen = strlen(src)) > sizeof(spath) - 2) || + ((dlen = strlen(dst)) > sizeof(dpath) - 2) || + ((dp = opendirat(dirfd, src)) == NULL)) + return AFPERR_PARAM; + + /* try to create the destination directory */ + if (AFP_OK != (err = netatalk_mkdir(vol, dst)) ) { + closedir(dp); + return err; + } + + /* set things up to copy */ + strcpy(spath, src); + strcat(spath, "/"); + slen++; + srem = sizeof(spath) - slen -1; + + strcpy(dpath, dst); + strcat(dpath, "/"); + dlen++; + drem = sizeof(dpath) - dlen -1; + + err = AFP_OK; + while ((de = readdir(dp))) { + /* skip this and previous directory */ + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + + if (strlen(de->d_name) > srem) { + err = AFPERR_PARAM; + break; + } + strcpy(spath + slen, de->d_name); + + if (ostatat(dirfd, spath, &st, vol_syml_opt(vol)) == 0) { + if (strlen(de->d_name) > drem) { + err = AFPERR_PARAM; + break; + } + strcpy(dpath + dlen, de->d_name); + + if (S_ISDIR(st.st_mode)) { + if (AFP_OK != (err = copydir(vol, ddir, dirfd, spath, dpath))) + goto copydir_done; + } else if (AFP_OK != (err = copyfile(vol, vol, ddir, dirfd, spath, dpath, NULL, NULL))) { + goto copydir_done; + + } else { + /* keep the same time stamp. */ + ut.actime = ut.modtime = st.st_mtime; + utime(dpath, &ut); + } + } + } + + /* keep the same time stamp. */ + if (ostatat(dirfd, src, &st, vol_syml_opt(vol)) == 0) { + ut.actime = ut.modtime = st.st_mtime; + utime(dst, &ut); + } + +copydir_done: + closedir(dp); + return err; +} + +/* --------------------- + * is our cached offspring count valid? + */ +static int diroffcnt(struct dir *dir, struct stat *st) +{ + return st->st_ctime == dir->d_ctime; +} + +/* --------------------- */ +static int invisible_dots(const struct vol *vol, const char *name) +{ + return vol_inv_dots(vol) && *name == '.' && strcmp(name, ".") && strcmp(name, ".."); +} + +/* ------------------ */ +static int set_dir_errors(struct path *path, const char *where, int err) +{ + switch ( err ) { + case EPERM : + case EACCES : + return AFPERR_ACCESS; + case EROFS : + return AFPERR_VLOCK; + } + LOG(log_error, logtype_afpd, "setdirparam(%s): %s: %s", fullpathname(path->u_name), where, strerror(err) ); + return AFPERR_PARAM; +} + +/*! + * @brief Convert name in client encoding to server encoding + * + * Convert ret->m_name to ret->u_name from client encoding to server encoding. + * This only gets called from cname(). + * + * @returns 0 on success, -1 on error + * + * @note If the passed ret->m_name is mangled, we'll demangle it + */ +static int cname_mtouname(const struct vol *vol, struct dir *dir, struct path *ret, int toUTF8) +{ + static char temp[ MAXPATHLEN + 1]; + char *t; + cnid_t fileid = 0; + + if (vol->v_obj->afp_version >= 30) { + if (toUTF8) { + if (dir->d_did == DIRDID_ROOT_PARENT) { + /* + * With uft8 volume name is utf8-mac, but requested path may be a mangled longname. See #2611981. + * So we compare it with the longname from the current volume and if they match + * we overwrite the requested path with the utf8 volume name so that the following + * strcmp can match. + */ + ucs2_to_charset(vol->v_maccharset, vol->v_macname, temp, AFPVOL_MACNAMELEN + 1); + if (strcasecmp(ret->m_name, temp) == 0) + ucs2_to_charset(CH_UTF8_MAC, vol->v_u8mname, ret->m_name, AFPVOL_U8MNAMELEN); + } else { + /* toUTF8 */ + if (mtoUTF8(vol, ret->m_name, strlen(ret->m_name), temp, MAXPATHLEN) == (size_t)-1) { + afp_errno = AFPERR_PARAM; + return -1; + } + strcpy(ret->m_name, temp); + } + } + + /* check for OS X mangled filename :( */ + t = demangle_osx(vol, ret->m_name, dir->d_did, &fileid); + + if (curdir == NULL) { + /* demangle_osx() calls dirlookup() which might have clobbered curdir */ + movecwd(vol, dir); + } + + LOG(log_maxdebug, logtype_afpd, "cname_mtouname('%s',did:%u) {demangled:'%s', fileid:%u}", + ret->m_name, ntohl(dir->d_did), t, ntohl(fileid)); + + if (t != ret->m_name) { + ret->u_name = t; + /* duplicate work but we can't reuse all convert_char we did in demangle_osx + * flags weren't the same + */ + if ( (t = utompath(vol, ret->u_name, fileid, utf8_encoding(vol->v_obj))) ) { + /* at last got our view of mac name */ + strcpy(ret->m_name, t); + } + } + } /* afp_version >= 30 */ + + /* If we haven't got it by now, get it */ + if (ret->u_name == NULL) { + if ((ret->u_name = mtoupath(vol, ret->m_name, dir->d_did, utf8_encoding(vol->v_obj))) == NULL) { + afp_errno = AFPERR_PARAM; + return -1; + } + } + + return 0; +} + +/*! + * @brief Build struct path from struct dir + * + * The final movecwd in cname failed, possibly with EPERM or ENOENT. We: + * 1. move cwd into parent dir (we're often already there, but not always) + * 2. set struct path to the dirname + * 3. in case of + * AFPERR_ACCESS: the dir is there, we just cant chdir into it + * AFPERR_NOOBJ: the dir was there when we stated it in cname, so we have a race + * 4. indicate there's no dir for this path + * 5. remove the dir + */ +static struct path *path_from_dir(struct vol *vol, struct dir *dir, struct path *ret) +{ + if (dir->d_did == DIRDID_ROOT_PARENT || dir->d_did == DIRDID_ROOT) + return NULL; + + switch (afp_errno) { + + case AFPERR_ACCESS: + if (movecwd( vol, dirlookup(vol, dir->d_pdid)) < 0 ) /* 1 */ + return NULL; + + memcpy(ret->m_name, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1); /* 3 */ + if (dir->d_m_name == dir->d_u_name) { + ret->u_name = ret->m_name; + } else { + ret->u_name = ret->m_name + blength(dir->d_m_name) + 1; + memcpy(ret->u_name, cfrombstr(dir->d_u_name), blength(dir->d_u_name) + 1); + } + + ret->d_dir = dir; + + LOG(log_debug, logtype_afpd, "cname('%s') {path-from-dir: AFPERR_ACCESS. curdir:'%s', path:'%s'}", + cfrombstr(dir->d_fullpath), + cfrombstr(curdir->d_fullpath), + ret->u_name); + + return ret; + + case AFPERR_NOOBJ: + if (movecwd(vol, dirlookup(vol, dir->d_pdid)) < 0 ) /* 1 */ + return NULL; + + memcpy(ret->m_name, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1); + if (dir->d_m_name == dir->d_u_name) { + ret->u_name = ret->m_name; + } else { + ret->u_name = ret->m_name + blength(dir->d_m_name) + 1; + memcpy(ret->u_name, cfrombstr(dir->d_u_name), blength(dir->d_u_name) + 1); + } + + ret->d_dir = NULL; /* 4 */ + dir_remove(vol, dir); /* 5 */ + return ret; + + default: + return NULL; + } + + /* DEADC0DE: never get here */ + return NULL; +} + + +/********************************************************************************************* + * Interface + ********************************************************************************************/ + +int get_afp_errno(const int param) +{ + if (afp_errno != AFPERR_DID1) + return afp_errno; + return param; +} + +/*! + * Resolve struct dir for an absolute path + * + * Given a path like "/Volumes/volume/dir/subdir" in a volume "/Volumes/volume" return + * a pointer to struct dir of "subdir". + * 1. Remove volue path from absolute path + * 2. start path + * 3. loop through all elements of the remaining path from 1. + * 4. we only allow dirs + * 5. search dircache + * 6. if not found in the dircache query the CNID database for the DID + * 7. and use dirlookup to resolve the DID to a it's struct dir * + * + * @param vol (r) volume the path is in, must be known + * @param path (r) absoule path + * + * @returns pointer to struct dir or NULL on error + */ +struct dir *dirlookup_bypath(const struct vol *vol, const char *path) +{ + EC_INIT; + + struct dir *dir = NULL; + cnid_t cnid, did; + bstring rpath = NULL; + bstring statpath = NULL; + struct bstrList *l = NULL; + struct stat st; + + cnid = htonl(2); + dir = vol->v_root; + + LOG(log_debug, logtype_afpd, "dirlookup_bypath(\"%s\")", path); + + if (strcmp(vol->v_path, path) == 0) + return dir; + + EC_NULL(rpath = rel_path_in_vol(path, vol->v_path)); /* 1. */ + + LOG(log_debug, logtype_afpd, "dirlookup_bypath: rpath: \"%s\"", cfrombstr(rpath)); + + EC_NULL(statpath = bfromcstr(vol->v_path)); /* 2. */ + + l = bsplit(rpath, '/'); + for (int i = 0; i < l->qty ; i++) { /* 3. */ + did = cnid; + EC_ZERO(bcatcstr(statpath, "/")); + EC_ZERO(bconcat(statpath, l->entry[i])); + + LOG(log_debug, logtype_afpd, "dirlookup_bypath: statpath: \"%s\"", cfrombstr(statpath)); + + EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st), + "lstat(rpath: %s, elem: %s): %s: %s", + cfrombstr(rpath), cfrombstr(l->entry[i]), + cfrombstr(statpath), strerror(errno)); + + if (!(S_ISDIR(st.st_mode))) /* 4. */ + EC_FAIL; + + if ((dir = dircache_search_by_name(vol, /* 5. */ + dir, + cfrombstr(l->entry[i]), + blength(l->entry[i]))) == NULL) { + + AFP_CNID_START("cnid_add"); + cnid = cnid_add(vol->v_cdb, /* 6. */ + &st, + did, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + 0); + AFP_CNID_DONE(); + if (cnid == CNID_INVALID) + EC_FAIL; + + if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */ + EC_FAIL; + } + } + +EC_CLEANUP: + bdestroy(rpath); + bstrListDestroy(l); + bdestroy(statpath); + if (ret != 0) + return NULL; + + LOG(log_debug, logtype_afpd, "dirlookup_bypath: result: \"%s\"", + cfrombstr(dir->d_fullpath)); + + return dir; +} + +/*! + * @brief Resolve a DID + * + * Resolve a DID, allocate a struct dir for it + * 1. Check for special CNIDs 0 (invalid), 1 and 2. + * 2a. Check if the DID is in the cache. + * 2b. Check if it's really a dir because we cache files too. + * 3. If it's not in the cache resolve it via the database. + * 4. Build complete server-side path to the dir. + * 5. Check if it exists and is a directory. + * 6. Create the struct dir and populate it. + * 7. Add it to the cache. + * + * @param vol (r) pointer to struct vol + * @param did (r) DID to resolve + * + * @returns pointer to struct dir + */ +struct dir *dirlookup(const struct vol *vol, cnid_t did) +{ + static char buffer[12 + MAXPATHLEN + 1]; + struct stat st; + struct dir *ret = NULL, *pdir; + bstring fullpath = NULL; + char *upath = NULL, *mpath; + cnid_t cnid, pdid; + size_t maxpath; + int buflen = 12 + MAXPATHLEN + 1; + int utf8; + int err = 0; + + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): START", ntohl(did)); + + /* check for did 0, 1 and 2 */ + if (did == 0 || vol == NULL) { /* 1 */ + afp_errno = AFPERR_PARAM; + ret = NULL; + goto exit; + } else if (did == DIRDID_ROOT_PARENT) { + rootParent.d_vid = vol->v_vid; + ret = &rootParent; + goto exit; + } else if (did == DIRDID_ROOT) { + ret = vol->v_root; + goto exit; + } + + /* Search the cache */ + if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */ + if (ret->d_flags & DIRF_ISFILE) { /* 2b */ + afp_errno = AFPERR_BADTYPE; + ret = NULL; + goto exit; + } + if (lstat(cfrombstr(ret->d_fullpath), &st) != 0) { + LOG(log_debug, logtype_afpd, "dirlookup(did: %u, path: \"%s\"): lstat: %s", + ntohl(did), cfrombstr(ret->d_fullpath), strerror(errno)); + switch (errno) { + case ENOENT: + case ENOTDIR: + /* It's not there anymore, so remove it */ + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): calling dir_remove", ntohl(did)); + dir_remove(vol, ret); + afp_errno = AFPERR_NOOBJ; + ret = NULL; + goto exit; + default: + ret = ret; + goto exit; + } + /* DEADC0DE */ + ret = NULL; + goto exit; + } + ret = ret; + goto exit; + } + + utf8 = utf8_encoding(vol->v_obj); + maxpath = (utf8) ? MAXPATHLEN - 7 : 255; + + /* Get it from the database */ + cnid = did; + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): querying CNID database", ntohl(did)); + + AFP_CNID_START("cnid_resolve"); + upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen); + AFP_CNID_DONE(); + if (upath == NULL) { + afp_errno = AFPERR_NOOBJ; + err = 1; + goto exit; + } + if ((upath = strdup(upath)) == NULL) { /* 3 */ + afp_errno = AFPERR_NOOBJ; + err = 1; + goto exit; + } + pdid = cnid; + + /* + * Recurse up the tree, terminates in dirlookup when either + * - DIRDID_ROOT is hit + * - a cached entry is found + */ + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): recursion for did: %u", + ntohl(did), ntohl(pdid)); + if ((pdir = dirlookup(vol, pdid)) == NULL) { + err = 1; + goto exit; + } + + /* build the fullpath */ + if ((fullpath = bstrcpy(pdir->d_fullpath)) == NULL + || bconchar(fullpath, '/') != BSTR_OK + || bcatcstr(fullpath, upath) != BSTR_OK) { + err = 1; + goto exit; + } + + /* stat it and check if it's a dir */ + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): stating \"%s\"", + ntohl(did), cfrombstr(fullpath)); + + if (ostat(cfrombstr(fullpath), &st, vol_syml_opt(vol)) != 0) { /* 5a */ + switch (errno) { + case ENOENT: + afp_errno = AFPERR_NOOBJ; + err = 1; + goto exit; + case EPERM: + afp_errno = AFPERR_ACCESS; + err = 1; + goto exit; + default: + afp_errno = AFPERR_MISC; + err = 1; + goto exit; + } + } else { + if ( ! S_ISDIR(st.st_mode)) { /* 5b */ + afp_errno = AFPERR_BADTYPE; + err = 1; + goto exit; + } + } + + /* Get macname from unix name */ + if ( (mpath = utompath(vol, upath, did, utf8)) == NULL ) { + afp_errno = AFPERR_NOOBJ; + err = 1; + goto exit; + } + + /* Create struct dir */ + if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, &st)) == NULL) { /* 6 */ + LOG(log_error, logtype_afpd, "dirlookup(did: %u) {%s, %s}: %s", ntohl(did), mpath, upath, strerror(errno)); + err = 1; + goto exit; + } + + /* Add it to the cache only if it's a dir */ + if (dircache_add(vol, ret) != 0) { /* 7 */ + err = 1; + goto exit; + } + +exit: + if (upath) free(upath); + if (err) { + LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {exit_error: %s}", + ntohl(did), AfpErr2name(afp_errno)); + if (fullpath) + bdestroy(fullpath); + if (ret) { + dir_free(ret); + ret = NULL; + } + } + if (ret) + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): RESULT: pdid: %u, path: \"%s\"", + ntohl(ret->d_did), ntohl(ret->d_pdid), cfrombstr(ret->d_fullpath)); + + return ret; +} + +#define ENUMVETO "./../Network Trash Folder/TheVolumeSettingsFolder/TheFindByContentFolder/:2eDS_Store/Contents/Desktop Folder/Trash/Benutzer/" + +/*! + * @brief Construct struct dir + * + * Construct struct dir from parameters. + * + * @param m_name (r) directory name in UTF8-dec + * @param u_name (r) directory name in server side encoding + * @param vol (r) pointer to struct vol + * @param pdid (r) Parent CNID + * @param did (r) CNID + * @param path (r) Full unix path to object + * @param st (r) struct stat of object + * + * @returns pointer to new struct dir or NULL on error + * + * @note Most of the time mac name and unix name are the same. + */ +struct dir *dir_new(const char *m_name, + const char *u_name, + const struct vol *vol, + cnid_t pdid, + cnid_t did, + bstring path, + struct stat *st) +{ + struct dir *dir; + + dir = (struct dir *) calloc(1, sizeof( struct dir )); + if (!dir) + return NULL; + + if ((dir->d_m_name = bfromcstr(m_name)) == NULL) { + free(dir); + return NULL; + } + + if (convert_string_allocate( (utf8_encoding(vol->v_obj)) ? CH_UTF8_MAC : vol->v_maccharset, + CH_UCS2, + m_name, + -1, (char **)&dir->d_m_name_ucs2) == (size_t)-1 ) { + LOG(log_error, logtype_afpd, "dir_new(did: %u) {%s, %s}: couldn't set UCS2 name", ntohl(did), m_name, u_name); + dir->d_m_name_ucs2 = NULL; + } + + if (m_name == u_name || !strcmp(m_name, u_name)) { + dir->d_u_name = dir->d_m_name; + } + else if ((dir->d_u_name = bfromcstr(u_name)) == NULL) { + bdestroy(dir->d_m_name); + free(dir); + return NULL; + } + + dir->d_did = did; + dir->d_pdid = pdid; + dir->d_vid = vol->v_vid; + dir->d_fullpath = path; + dir->dcache_ctime = st->st_ctime; + dir->dcache_ino = st->st_ino; + if (!S_ISDIR(st->st_mode)) + dir->d_flags = DIRF_ISFILE; + dir->d_rights_cache = 0xffffffff; + return dir; +} + +/*! + * @brief Free a struct dir and all its members + * + * @param (rw) pointer to struct dir + */ +void dir_free(struct dir *dir) +{ + if (dir->d_u_name != dir->d_m_name) { + bdestroy(dir->d_u_name); + } + if (dir->d_m_name_ucs2) + free(dir->d_m_name_ucs2); + bdestroy(dir->d_m_name); + bdestroy(dir->d_fullpath); + free(dir); +} + +/*! + * @brief Create struct dir from struct path + * + * Create a new struct dir from struct path. Then add it to the cache. + * + * 1. Open adouble file, get CNID from it. + * 2. Search the database, hinting with the CNID from (1). + * 3. Build fullpath and create struct dir. + * 4. Add it to the cache. + * + * @param vol (r) pointer to struct vol, possibly modified in callee + * @param dir (r) pointer to parrent directory + * @param path (rw) pointer to struct path with valid path->u_name + * @param len (r) strlen of path->u_name + * + * @returns Pointer to new struct dir or NULL on error. + * + * @note Function also assigns path->m_name from path->u_name. + */ +struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, int len) +{ + int err = 0; + struct dir *cdir = NULL; + cnid_t id; + struct adouble ad; + struct adouble *adp = NULL; + bstring fullpath = NULL; + + AFP_ASSERT(vol); + AFP_ASSERT(dir); + AFP_ASSERT(path); + AFP_ASSERT(len > 0); + + if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name))) != NULL) { + /* there's a stray entry in the dircache */ + LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {stray cache entry: did:%u,'%s', removing}", + ntohl(dir->d_did), cfrombstr(dir->d_fullpath), path->u_name, + ntohl(cdir->d_did), cfrombstr(dir->d_fullpath)); + if (dir_remove(vol, cdir) != 0) { + dircache_dump(); + AFP_PANIC("dir_add"); + } + } + + /* get_id needs adp for reading CNID from adouble file */ + ad_init(&ad, vol); + if ((ad_open(&ad, path->u_name, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDONLY)) == 0) /* 1 */ + adp = &ad; + + /* Get CNID */ + if ((id = get_id(vol, adp, &path->st, dir->d_did, path->u_name, len)) == 0) { /* 2 */ + err = 1; + goto exit; + } + + if (adp) + ad_close(adp, ADFLAGS_HF); + + /* Get macname from unixname */ + if (path->m_name == NULL) { + if ((path->m_name = utompath(vol, path->u_name, id, utf8_encoding(vol->v_obj))) == NULL) { + LOG(log_error, logtype_afpd, "dir_add(\"%s\"): can't assign macname", path->u_name); + err = 2; + goto exit; + } + } + + /* Build fullpath */ + if ( ((fullpath = bstrcpy(dir->d_fullpath)) == NULL) /* 3 */ + || (bconchar(fullpath, '/') != BSTR_OK) + || (bcatcstr(fullpath, path->u_name)) != BSTR_OK) { + LOG(log_error, logtype_afpd, "dir_add: fullpath: %s", strerror(errno) ); + err = 3; + goto exit; + } + + /* Allocate and initialize struct dir */ + if ((cdir = dir_new(path->m_name, + path->u_name, + vol, + dir->d_did, + id, + fullpath, + &path->st)) == NULL) { /* 3 */ + err = 4; + goto exit; + } + + if ((dircache_add(vol, cdir)) != 0) { /* 4 */ + LOG(log_error, logtype_afpd, "dir_add: fatal dircache error: %s", cfrombstr(fullpath)); + exit(EXITERR_SYS); + } + +exit: + if (err != 0) { + LOG(log_debug, logtype_afpd, "dir_add('%s/%s'): error: %u", + cfrombstr(dir->d_u_name), path->u_name, err); + + if (adp) + ad_close(adp, ADFLAGS_HF); + if (!cdir && fullpath) + bdestroy(fullpath); + if (cdir) + dir_free(cdir); + cdir = NULL; + } else { + /* no error */ + LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {cached: %u,'%s'}", + ntohl(dir->d_did), cfrombstr(dir->d_fullpath), path->u_name, + ntohl(cdir->d_did), cfrombstr(cdir->d_fullpath)); + } + + return(cdir); +} + +/*! + * Free the queue with invalid struct dirs + * + * This gets called at the end of every AFP func. + */ +void dir_free_invalid_q(void) +{ + struct dir *dir; + while ((dir = (struct dir *)dequeue(invalid_dircache_entries))) + dir_free(dir); +} + +/*! + * @brief Remove a dir from a cache and queue it for freeing + * + * 1. Check if the dir is locked or has opened forks + * 2. Remove it from the cache + * 3. Queue it for removal + * 4. If it's a request to remove curdir, mark curdir as invalid + * 5. Mark it as invalid + * + * @param (r) pointer to struct vol + * @param (rw) pointer to struct dir + */ +int dir_remove(const struct vol *vol, struct dir *dir) +{ + AFP_ASSERT(vol); + AFP_ASSERT(dir); + + if (dir->d_did == DIRDID_ROOT_PARENT || dir->d_did == DIRDID_ROOT) + return 0; + + LOG(log_debug, logtype_afpd, "dir_remove(did:%u,'%s'): {removing}", + ntohl(dir->d_did), cfrombstr(dir->d_u_name)); + + dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 2 */ + enqueue(invalid_dircache_entries, dir); /* 3 */ + + if (curdir == dir) /* 4 */ + curdir = NULL; + + dir->d_did = CNID_INVALID; /* 5 */ + + return 0; +} + +#if 0 /* unused */ +/*! + * @brief Modify a struct dir, adjust cache + * + * Any value that is 0 or NULL is not changed. If new_uname is NULL it is set to new_mname. + * If given new_uname == new_mname, new_uname will point to new_mname. + * + * @param vol (r) pointer to struct vol + * @param dir (rw) pointer to struct dir + * @param pdid (r) new parent DID + * @param did (r) new DID + * @param new_mname (r) new mac-name + * @param new_uname (r) new unix-name + * @param pdir_fullpath (r) new fullpath of parent dir + */ +int dir_modify(const struct vol *vol, + struct dir *dir, + cnid_t pdid, + cnid_t did, + const char *new_mname, + const char *new_uname, + bstring pdir_fullpath) +{ + int ret = 0; + + /* Remove it from the cache */ + dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); + + if (pdid) + dir->d_pdid = pdid; + if (did) + dir->d_did = did; + + if (new_mname) { + /* free uname if it's not the same as mname */ + if (dir->d_m_name != dir->d_u_name) + bdestroy(dir->d_u_name); + + if (new_uname == NULL) + new_uname = new_mname; + + /* assign new name */ + if ((bassigncstr(dir->d_m_name, new_mname)) != BSTR_OK) { + LOG(log_error, logtype_afpd, "dir_modify: bassigncstr: %s", strerror(errno) ); + return -1; + } + + if (new_mname == new_uname || (strcmp(new_mname, new_uname) == 0)) { + dir->d_u_name = dir->d_m_name; + } else { + if ((dir->d_u_name = bfromcstr(new_uname)) == NULL) { + LOG(log_error, logtype_afpd, "dir_modify: bassigncstr: %s", strerror(errno) ); + return -1; + } + } + } + + if (pdir_fullpath) { + if (bassign(dir->d_fullpath, pdir_fullpath) != BSTR_OK) + return -1; + if (bcatcstr(dir->d_fullpath, "/") != BSTR_OK) + return -1; + if (bcatcstr(dir->d_fullpath, new_uname) != BSTR_OK) + return -1; + } + + if (dir->d_m_name_ucs2) + free(dir->d_m_name_ucs2); + if ((size_t)-1 == convert_string_allocate((utf8_encoding())?CH_UTF8_MAC:vol->v_maccharset, CH_UCS2, dir->d_m_name, -1, (char**)&dir->d_m_name_ucs2)) + dir->d_m_name_ucs2 = NULL; + + /* Re-add it to the cache */ + if ((dircache_add(vol, dir)) != 0) { + dircache_dump(); + AFP_PANIC("dir_modify"); + } + + return ret; +} +#endif + +/*! + * @brief Resolve a catalog node name path + * + * 1. Evaluate path type + * 2. Move to start dir, if we cant, it might eg because of EACCES, build + * path from dirname, so eg getdirparams has sth it can chew on. curdir + * is dir parent then. All this is done in path_from_dir(). + * 3. Parse next cnode name in path, cases: + * 4. single "\0" -> do nothing + * 5. two or more consecutive "\0" -> chdir("..") one or more times + * 6. cnode name -> copy it to path.m_name + * 7. Get unix name from mac name + * 8. Special handling of request with did 1 + * 9. stat the cnode name + * 10. If it's not there, it's probably an afp_createfile|dir, + * return with curdir = dir parent, struct path = dirname + * 11. If it's there and it's a file, it must should be the last element of the requested + * path. Return with curdir = cnode name parent dir, struct path = filename + * 12. Treat symlinks like files, dont follow them + * 13. If it's a dir: + * 14. Search the dircache for it + * 15. If it's not in the cache, create a struct dir for it and add it to the cache + * 16. chdir into the dir and + * 17. set m_name to the mac equivalent of "." + * 18. goto 3 + */ +struct path *cname(struct vol *vol, struct dir *dir, char **cpath) +{ + static char path[ MAXPATHLEN + 1]; + static struct path ret; + + struct dir *cdir; + char *data, *p; + int len; + uint32_t hint; + uint16_t len16; + int size = 0; + int toUTF8 = 0; + + LOG(log_maxdebug, logtype_afpd, "cname('%s'): {start}", cfrombstr(dir->d_fullpath)); + + data = *cpath; + afp_errno = AFPERR_NOOBJ; + memset(&ret, 0, sizeof(ret)); + + switch (ret.m_type = *data) { /* 1 */ + case 2: + data++; + len = (unsigned char) *data++; + size = 2; + if (vol->v_obj->afp_version >= 30) { + ret.m_type = 3; + toUTF8 = 1; + } + break; + case 3: + if (vol->v_obj->afp_version >= 30) { + data++; + memcpy(&hint, data, sizeof(hint)); + hint = ntohl(hint); + data += sizeof(hint); + + memcpy(&len16, data, sizeof(len16)); + len = ntohs(len16); + data += 2; + size = 7; + break; + } + /* else it's an error */ + default: + afp_errno = AFPERR_PARAM; + return( NULL ); + } + *cpath += len + size; + + path[0] = 0; + ret.m_name = path; + + if (movecwd(vol, dir) < 0 ) { + LOG(log_debug, logtype_afpd, "cname(did:%u): failed to chdir to '%s'", + ntohl(dir->d_did), cfrombstr(dir->d_fullpath)); + if (len == 0) + return path_from_dir(vol, dir, &ret); + else + return NULL; + } + + while (len) { /* 3 */ + if (*data == 0) { /* 4 or 5 */ + data++; + len--; + while (len > 0 && *data == 0) { /* 5 */ + /* chdir to parrent dir */ + if ((dir = dirlookup(vol, dir->d_pdid)) == NULL) + return NULL; + if (movecwd( vol, dir ) < 0 ) { + dir_remove(vol, dir); + return NULL; + } + data++; + len--; + } + continue; + } + + /* 6*/ + for ( p = path; *data != 0 && len > 0; len-- ) { + *p++ = *data++; + if (p > &path[UTF8FILELEN_EARLY]) { /* FIXME safeguard, limit of early Mac OS X */ + afp_errno = AFPERR_PARAM; + return NULL; + } + } + *p = 0; /* Terminate string */ + ret.u_name = NULL; + + if (cname_mtouname(vol, dir, &ret, toUTF8) != 0) { /* 7 */ + LOG(log_error, logtype_afpd, "cname('%s'): error from cname_mtouname", path); + return NULL; + } + + LOG(log_maxdebug, logtype_afpd, "came('%s'): {node: '%s}", cfrombstr(dir->d_fullpath), ret.u_name); + + /* Prevent access to our special folders like .AppleDouble */ + if (check_name(vol, ret.u_name)) { + /* the name is illegal */ + LOG(log_info, logtype_afpd, "cname: illegal path: '%s'", ret.u_name); + afp_errno = AFPERR_PARAM; + if (vol->v_obj->options.flags & OPTION_VETOMSG) { + bstring message = bformat("Attempt to access vetoed file or directory \"%s\" in directory \"%s\"", + ret.u_name, bdata(dir->d_u_name)); + if (setmessage(bdata(message)) == 0) + /* Client may make multiple attempts, only send the message the first time */ + kill(getpid(), SIGUSR2); + bdestroy(message); + } + return NULL; + } + + if (dir->d_did == DIRDID_ROOT_PARENT) { /* 8 */ + /* + * Special case: CNID 1 + * root parent (did 1) has one child: the volume. Requests for did=1 with + * some must check against the volume name. + */ + if ((strcmp(cfrombstr(vol->v_root->d_m_name), ret.m_name)) == 0) + cdir = vol->v_root; + else + return NULL; + } else { + /* + * CNID != 1, eg. most of the times we take this way. + * Now check if current path-part is a file or dir: + * o if it's dir we have to step into it + * o if it's a file we expect it to be the last part of the requested path + * and thus call continue which should terminate the while loop because + * len = 0. Ok? + */ + if (of_stat(vol, &ret) != 0) { /* 9 */ + /* + * ret.u_name doesn't exist, might be afp_createfile|dir + * that means it should have been the last part + */ + if (len > 0) { + /* it wasn't the last part, so we have a bogus path request */ + afp_errno = AFPERR_NOOBJ; + return NULL; + } + /* + * this will terminate clean in while (1) because len == 0, + * probably afp_createfile|dir + */ + LOG(log_maxdebug, logtype_afpd, "came('%s'): {leave-cnode ENOENT (possile create request): '%s'}", + cfrombstr(dir->d_fullpath), ret.u_name); + continue; /* 10 */ + } + + switch (ret.st.st_mode & S_IFMT) { + case S_IFREG: /* 11 */ + LOG(log_debug, logtype_afpd, "came('%s'): {file: '%s'}", + cfrombstr(dir->d_fullpath), ret.u_name); + if (len > 0) { + /* it wasn't the last part, so we have a bogus path request */ + afp_errno = AFPERR_PARAM; + return NULL; + } + continue; /* continues while loop */ + case S_IFLNK: /* 12 */ + LOG(log_debug, logtype_afpd, "came('%s'): {link: '%s'}", + cfrombstr(dir->d_fullpath), ret.u_name); + if (len > 0) { + LOG(log_warning, logtype_afpd, "came('%s'): {symlinked dir: '%s'}", + cfrombstr(dir->d_fullpath), ret.u_name); + afp_errno = AFPERR_PARAM; + return NULL; + } + continue; /* continues while loop */ + case S_IFDIR: /* 13 */ + break; + default: + LOG(log_info, logtype_afpd, "cname: special file: '%s'", ret.u_name); + afp_errno = AFPERR_NODIR; + return NULL; + } + + /* Search the cache */ + int unamelen = strlen(ret.u_name); + cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen); /* 14 */ + if (cdir == NULL) { + /* Not in cache, create one */ + if ((cdir = dir_add(vol, dir, &ret, unamelen)) == NULL) { /* 15 */ + LOG(log_error, logtype_afpd, "cname(did:%u, name:'%s', cwd:'%s'): failed to add dir", + ntohl(dir->d_did), ret.u_name, getcwdpath()); + return NULL; + } + } + } /* if/else cnid==1 */ + + /* Now chdir to the evaluated dir */ + if (movecwd( vol, cdir ) < 0 ) { /* 16 */ + LOG(log_debug, logtype_afpd, "cname(cwd:'%s'): failed to chdir to new subdir '%s': %s", + cfrombstr(curdir->d_fullpath), cfrombstr(cdir->d_fullpath), strerror(errno)); + if (len == 0) + return path_from_dir(vol, cdir, &ret); + else + return NULL; + } + dir = cdir; + ret.m_name[0] = 0; /* 17, so we later know last token was a dir */ + } /* while (len) */ + + if (curdir->d_did == DIRDID_ROOT_PARENT) { + afp_errno = AFPERR_DID1; + return NULL; + } + + if (ret.m_name[0] == 0) { + /* Last part was a dir */ + ret.u_name = mtoupath(vol, ret.m_name, 0, 1); /* Force "." into a useable static buffer */ + ret.d_dir = dir; + } + + LOG(log_debug, logtype_afpd, "cname('%s') {end: curdir:'%s', path:'%s'}", + cfrombstr(dir->d_fullpath), + cfrombstr(curdir->d_fullpath), + ret.u_name); + + return &ret; +} + +/* + * @brief chdir() to dir + * + * @param vol (r) pointer to struct vol + * @param dir (r) pointer to struct dir + * + * @returns 0 on success, -1 on error with afp_errno set appropiately + */ +int movecwd(const struct vol *vol, struct dir *dir) +{ + int ret; + + AFP_ASSERT(vol); + AFP_ASSERT(dir); + + LOG(log_maxdebug, logtype_afpd, "movecwd: from: curdir:\"%s\", cwd:\"%s\"", + curdir ? cfrombstr(curdir->d_fullpath) : "INVALID", getcwdpath()); + + if (dir->d_did == DIRDID_ROOT_PARENT) { + curdir = &rootParent; + return 0; + } + + LOG(log_debug, logtype_afpd, "movecwd(to: did: %u, \"%s\")", + ntohl(dir->d_did), cfrombstr(dir->d_fullpath)); + + if ((ret = ochdir(cfrombstr(dir->d_fullpath), vol_syml_opt(vol))) != 0 ) { + LOG(log_debug, logtype_afpd, "movecwd(\"%s\"): %s", + cfrombstr(dir->d_fullpath), strerror(errno)); + if (ret == 1) { + /* p is a symlink or getcwd failed */ + afp_errno = AFPERR_BADTYPE; + + if (chdir(vol->v_path ) < 0) { + LOG(log_error, logtype_afpd, "can't chdir back'%s': %s", vol->v_path, strerror(errno)); + /* XXX what do we do here? */ + } + curdir = vol->v_root; + return -1; + } + + switch (errno) { + case EACCES: + case EPERM: + afp_errno = AFPERR_ACCESS; + break; + default: + afp_errno = AFPERR_NOOBJ; + } + return( -1 ); + } + + curdir = dir; + return( 0 ); +} + +/* + * We can't use unix file's perm to support Apple's inherited protection modes. + * If we aren't the file's owner we can't change its perms when moving it and smb + * nfs,... don't even try. + */ +int check_access(const AFPObj *obj, struct vol *vol, char *path, int mode) +{ + struct maccess ma; + char *p; + + p = ad_dir(path); + if (!p) + return -1; + + accessmode(obj, vol, p, &ma, curdir, NULL); + if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) + return -1; + if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) + return -1; + + return 0; +} + +/* --------------------- */ +int file_access(const AFPObj *obj, struct vol *vol, struct path *path, int mode) +{ + struct maccess ma; + + accessmode(obj, vol, path->u_name, &ma, curdir, &path->st); + + LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x", + path->u_name, ma.ma_user); + + if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) { + LOG(log_debug, logtype_afpd, "file_access(\"%s\"): write access denied", path->u_name); + return -1; + } + if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) { + LOG(log_debug, logtype_afpd, "file_access(\"%s\"): read access denied", path->u_name); + return -1; + } + return 0; + +} + +/* --------------------- */ +void setdiroffcnt(struct dir *dir, struct stat *st, uint32_t count) +{ + dir->d_offcnt = count; + dir->d_ctime = st->st_ctime; + dir->d_flags &= ~DIRF_CNID; +} + + +/* --------------------- + * is our cached also for reenumerate id? + */ +int dirreenumerate(struct dir *dir, struct stat *st) +{ + return st->st_ctime == dir->d_ctime && (dir->d_flags & DIRF_CNID); +} + +/* ------------------------------ + (".", curdir) + (name, dir) with curdir:name == dir, from afp_enumerate +*/ + +int getdirparams(const AFPObj *obj, + const struct vol *vol, + uint16_t bitmap, struct path *s_path, + struct dir *dir, + char *buf, size_t *buflen ) +{ + struct maccess ma; + struct adouble ad; + char *data, *l_nameoff = NULL, *utf_nameoff = NULL; + int bit = 0, isad = 0; + uint32_t aint; + uint16_t ashort; + int ret; + uint32_t utf8 = 0; + cnid_t pdid; + struct stat *st = &s_path->st; + char *upath = s_path->u_name; + + if ((bitmap & ((1 << DIRPBIT_ATTR) | + (1 << DIRPBIT_CDATE) | + (1 << DIRPBIT_MDATE) | + (1 << DIRPBIT_BDATE) | + (1 << DIRPBIT_FINFO)))) { + + ad_init(&ad, vol); + if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) ) { + isad = 1; + if (ad.ad_mdp->adf_flags & O_CREAT) { + /* We just created it */ + if (s_path->m_name == NULL) { + if ((s_path->m_name = utompath(vol, + upath, + dir->d_did, + utf8_encoding(obj))) == NULL) { + LOG(log_error, logtype_afpd, + "getdirparams(\"%s\"): can't assign macname", + cfrombstr(dir->d_fullpath)); + return AFPERR_MISC; + } + } + ad_setname(&ad, s_path->m_name); + ad_setid( &ad, + s_path->st.st_dev, + s_path->st.st_ino, + dir->d_did, + dir->d_pdid, + vol->v_stamp); + ad_flush( &ad); + } + } + } + + pdid = dir->d_pdid; + + data = buf; + while ( bitmap != 0 ) { + while (( bitmap & 1 ) == 0 ) { + bitmap = bitmap>>1; + bit++; + } + + switch ( bit ) { + case DIRPBIT_ATTR : + if ( isad ) { + ad_getattr(&ad, &ashort); + } else if (invisible_dots(vol, cfrombstr(dir->d_u_name))) { + ashort = htons(ATTRBIT_INVISIBLE); + } else + ashort = 0; + ashort &= ~htons(vol->v_ignattr); + memcpy( data, &ashort, sizeof( ashort )); + data += sizeof( ashort ); + break; + + case DIRPBIT_PDID : + memcpy( data, &pdid, sizeof( pdid )); + data += sizeof( pdid ); + LOG(log_debug, logtype_afpd, "metadata('%s'): Parent DID: %u", + s_path->u_name, ntohl(pdid)); + break; + + case DIRPBIT_CDATE : + if (!isad || (ad_getdate(&ad, AD_DATE_CREATE, &aint) < 0)) + aint = AD_DATE_FROM_UNIX(st->st_mtime); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case DIRPBIT_MDATE : + aint = AD_DATE_FROM_UNIX(st->st_mtime); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case DIRPBIT_BDATE : + if (!isad || (ad_getdate(&ad, AD_DATE_BACKUP, &aint) < 0)) + aint = AD_DATE_START; + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case DIRPBIT_FINFO : + if ( isad ) { + memcpy( data, ad_entry( &ad, ADEID_FINDERI ), 32 ); + } else { /* no appledouble */ + memset( data, 0, 32 ); + /* dot files are by default visible */ + if (invisible_dots(vol, cfrombstr(dir->d_u_name))) { + ashort = htons(FINDERINFO_INVISIBLE); + memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort)); + } + } + data += 32; + break; + + case DIRPBIT_LNAME : + if (dir->d_m_name) /* root of parent can have a null name */ + l_nameoff = data; + else + memset(data, 0, sizeof(uint16_t)); + data += sizeof( uint16_t ); + break; + + case DIRPBIT_SNAME : + memset(data, 0, sizeof(uint16_t)); + data += sizeof( uint16_t ); + break; + + case DIRPBIT_DID : + memcpy( data, &dir->d_did, sizeof( aint )); + data += sizeof( aint ); + LOG(log_debug, logtype_afpd, "metadata('%s'): DID: %u", + s_path->u_name, ntohl(dir->d_did)); + break; + + case DIRPBIT_OFFCNT : + ashort = 0; + /* this needs to handle current directory access rights */ + if (diroffcnt(dir, st)) { + ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt; + } + else if ((ret = for_each_dirent(vol, upath, NULL,NULL)) >= 0) { + setdiroffcnt(dir, st, ret); + ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt; + } + ashort = htons( ashort ); + memcpy( data, &ashort, sizeof( ashort )); + data += sizeof( ashort ); + break; + + case DIRPBIT_UID : + aint = htonl(st->st_uid); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case DIRPBIT_GID : + aint = htonl(st->st_gid); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case DIRPBIT_ACCESS : + accessmode(obj, vol, upath, &ma, dir , st); + + *data++ = ma.ma_user; + *data++ = ma.ma_world; + *data++ = ma.ma_group; + *data++ = ma.ma_owner; + break; + + /* Client has requested the ProDOS information block. + Just pass back the same basic block for all + directories. */ + case DIRPBIT_PDINFO : + if (obj->afp_version >= 30) { /* UTF8 name */ + utf8 = kTextEncodingUTF8; + if (dir->d_m_name) /* root of parent can have a null name */ + utf_nameoff = data; + else + memset(data, 0, sizeof(uint16_t)); + data += sizeof( uint16_t ); + aint = 0; + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + } + else { /* ProDOS Info Block */ + *data++ = 0x0f; + *data++ = 0; + ashort = htons( 0x0200 ); + memcpy( data, &ashort, sizeof( ashort )); + data += sizeof( ashort ); + memset( data, 0, sizeof( ashort )); + data += sizeof( ashort ); + } + break; + + case DIRPBIT_UNIXPR : + /* accessmode may change st_mode with ACLs */ + accessmode(obj, vol, upath, &ma, dir, st); + + aint = htonl(st->st_uid); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + aint = htonl(st->st_gid); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + + aint = st->st_mode; + aint = htonl ( aint & ~S_ISGID ); /* Remove SGID, OSX doesn't like it ... */ + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + + *data++ = ma.ma_user; + *data++ = ma.ma_world; + *data++ = ma.ma_group; + *data++ = ma.ma_owner; + break; + + default : + if ( isad ) { + ad_close(&ad, ADFLAGS_HF); + } + return( AFPERR_BITMAP ); + } + bitmap = bitmap>>1; + bit++; + } + if ( l_nameoff ) { + ashort = htons( data - buf ); + memcpy( l_nameoff, &ashort, sizeof( ashort )); + data = set_name(vol, data, pdid, cfrombstr(dir->d_m_name), dir->d_did, 0); + } + if ( utf_nameoff ) { + ashort = htons( data - buf ); + memcpy( utf_nameoff, &ashort, sizeof( ashort )); + data = set_name(vol, data, pdid, cfrombstr(dir->d_m_name), dir->d_did, utf8); + } + if ( isad ) { + ad_close(&ad, ADFLAGS_HF); + } + *buflen = data - buf; + return( AFP_OK ); +} + +/* ----------------------------- */ +int path_error(struct path *path, int error) +{ +/* - a dir with access error + * - no error it's a file + * - file not found + */ + if (path_isadir(path)) + return afp_errno; + if (path->st_valid && path->st_errno) + return error; + return AFPERR_BADTYPE ; +} + +/* ----------------------------- */ +int afp_setdirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + struct path *path; + uint16_t vid, bitmap; + uint32_t did; + int rc; + + *rbuflen = 0; + ibuf += 2; + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( int ); + + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + memcpy( &bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + + if (NULL == ( path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + if ( *path->m_name != '\0' ) { + rc = path_error(path, AFPERR_NOOBJ); + /* maybe we are trying to set perms back */ + if (rc != AFPERR_ACCESS) + return rc; + } + + /* + * If ibuf is odd, make it even. + */ + if ((u_long)ibuf & 1 ) { + ibuf++; + } + + if (AFP_OK == ( rc = setdirparams(vol, path, bitmap, ibuf )) ) { + setvoltime(obj, vol ); + } + return( rc ); +} + +/* + * assume path == '\0' eg. it's a directory in canonical form + */ +int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *buf ) +{ + struct maccess ma; + struct adouble ad; + struct utimbuf ut; + struct timeval tv; + + char *upath; + struct dir *dir; + int bit, isad = 0; + int cdate, bdate; + int owner, group; + uint16_t ashort, bshort, oshort; + int err = AFP_OK; + int change_mdate = 0; + int change_parent_mdate = 0; + int newdate = 0; + uint16_t bitmap = d_bitmap; + u_char finder_buf[32]; + uint32_t upriv; + mode_t mpriv = 0; + bool set_upriv = false, set_maccess = false; + + LOG(log_debug, logtype_afpd, "setdirparams(\"%s\", bitmap: %02x)", path->u_name, bitmap); + + bit = 0; + upath = path->u_name; + dir = path->d_dir; + while ( bitmap != 0 ) { + while (( bitmap & 1 ) == 0 ) { + bitmap = bitmap>>1; + bit++; + } + + switch( bit ) { + case DIRPBIT_ATTR : + change_mdate = 1; + memcpy( &ashort, buf, sizeof( ashort )); + buf += sizeof( ashort ); + break; + case DIRPBIT_CDATE : + change_mdate = 1; + memcpy(&cdate, buf, sizeof(cdate)); + buf += sizeof( cdate ); + break; + case DIRPBIT_MDATE : + memcpy(&newdate, buf, sizeof(newdate)); + buf += sizeof( newdate ); + break; + case DIRPBIT_BDATE : + change_mdate = 1; + memcpy(&bdate, buf, sizeof(bdate)); + buf += sizeof( bdate ); + break; + case DIRPBIT_FINFO : + change_mdate = 1; + memcpy( finder_buf, buf, 32 ); + buf += 32; + break; + case DIRPBIT_UID : /* What kind of loser mounts as root? */ + memcpy( &owner, buf, sizeof(owner)); + buf += sizeof( owner ); + break; + case DIRPBIT_GID : + memcpy( &group, buf, sizeof( group )); + buf += sizeof( group ); + break; + case DIRPBIT_ACCESS : + set_maccess = true; + change_mdate = 1; + ma.ma_user = *buf++; + ma.ma_world = *buf++; + ma.ma_group = *buf++; + ma.ma_owner = *buf++; + mpriv = mtoumode( &ma ) | vol->v_dperm; + break; + /* Ignore what the client thinks we should do to the + ProDOS information block. Skip over the data and + report nothing amiss. */ + case DIRPBIT_PDINFO : + if (vol->v_obj->afp_version < 30) { + buf += 6; + } + else { + err = AFPERR_BITMAP; + bitmap = 0; + } + break; + case DIRPBIT_UNIXPR : + if (vol_unix_priv(vol)) { + set_upriv = true; + memcpy( &owner, buf, sizeof(owner)); /* FIXME need to change owner too? */ + buf += sizeof( owner ); + memcpy( &group, buf, sizeof( group )); + buf += sizeof( group ); + + change_mdate = 1; + memcpy( &upriv, buf, sizeof( upriv )); + buf += sizeof( upriv ); + upriv = ntohl (upriv) | vol->v_dperm; + break; + } + /* fall through */ + default : + err = AFPERR_BITMAP; + bitmap = 0; + break; + } + + bitmap = bitmap>>1; + bit++; + } + + if (d_bitmap & ((1<u_name, d_bitmap); + return AFPERR_ACCESS; + } + if ((ad_get_MD_flags(&ad) & O_CREAT)) { + ad_setname(&ad, cfrombstr(curdir->d_m_name)); + } + isad = 1; + } + + bit = 0; + bitmap = d_bitmap; + while ( bitmap != 0 ) { + while (( bitmap & 1 ) == 0 ) { + bitmap = bitmap>>1; + bit++; + } + + switch( bit ) { + case DIRPBIT_ATTR : + if (isad) { + ad_getattr(&ad, &bshort); + oshort = bshort; + if ( ntohs( ashort ) & ATTRBIT_SETCLR ) { + ashort &= ~htons(vol->v_ignattr); + bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR ); + } else { + bshort &= ~ashort; + } + if ((bshort & htons(ATTRBIT_INVISIBLE)) != (oshort & htons(ATTRBIT_INVISIBLE))) + change_parent_mdate = 1; + ad_setattr(&ad, bshort); + } + break; + case DIRPBIT_CDATE : + if (isad) { + ad_setdate(&ad, AD_DATE_CREATE, cdate); + } + break; + case DIRPBIT_MDATE : + break; + case DIRPBIT_BDATE : + if (isad) { + ad_setdate(&ad, AD_DATE_BACKUP, bdate); + } + break; + case DIRPBIT_FINFO : + if (isad) { + /* Fixes #2802236 */ + uint16_t fflags; + memcpy(&fflags, finder_buf + FINDERINFO_FRFLAGOFF, sizeof(uint16_t)); + fflags &= htons(~FINDERINFO_ISHARED); + memcpy(finder_buf + FINDERINFO_FRFLAGOFF, &fflags, sizeof(uint16_t)); + /* #2802236 end */ + + if ( dir->d_did == DIRDID_ROOT ) { + /* + * Alright, we admit it, this is *really* sick! + * The 4 bytes that we don't copy, when we're dealing + * with the root of a volume, are the directory's + * location information. This eliminates that annoying + * behavior one sees when mounting above another mount + * point. + */ + memcpy( ad_entry( &ad, ADEID_FINDERI ), finder_buf, 10 ); + memcpy( ad_entry( &ad, ADEID_FINDERI ) + 14, finder_buf + 14, 18 ); + } else { + memcpy( ad_entry( &ad, ADEID_FINDERI ), finder_buf, 32 ); + } + } + break; + case DIRPBIT_UID : /* What kind of loser mounts as root? */ + if ( (dir->d_did == DIRDID_ROOT) && + (setdeskowner(vol, ntohl(owner), -1 ) < 0)) { + err = set_dir_errors(path, "setdeskowner", errno); + if (isad && err == AFPERR_PARAM) { + err = AFP_OK; /* ???*/ + } + else { + goto setdirparam_done; + } + } + if ( setdirowner(vol, upath, ntohl(owner), -1 ) < 0 ) { + err = set_dir_errors(path, "setdirowner", errno); + goto setdirparam_done; + } + break; + case DIRPBIT_GID : + if (dir->d_did == DIRDID_ROOT) + setdeskowner(vol, -1, ntohl(group) ); + if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) { + err = set_dir_errors(path, "setdirowner", errno); + goto setdirparam_done; + } + break; + case DIRPBIT_ACCESS : + break; + case DIRPBIT_PDINFO : + if (vol->v_obj->afp_version >= 30) { + err = AFPERR_BITMAP; + goto setdirparam_done; + } + break; + case DIRPBIT_UNIXPR : + if (!vol_unix_priv(vol)) { + err = AFPERR_BITMAP; + goto setdirparam_done; + } + break; + default : + err = AFPERR_BITMAP; + goto setdirparam_done; + break; + } + + bitmap = bitmap>>1; + bit++; + } + +setdirparam_done: + if (change_mdate && newdate == 0 && gettimeofday(&tv, NULL) == 0) { + newdate = AD_DATE_FROM_UNIX(tv.tv_sec); + } + if (newdate) { + if (isad) + ad_setdate(&ad, AD_DATE_MODIFY, newdate); + ut.actime = ut.modtime = AD_DATE_TO_UNIX(newdate); + utime(upath, &ut); + } + + if (isad) { + if (path->st_valid && !path->st_errno) { + struct stat *st = &path->st; + if (dir && dir->d_pdid) { + ad_setid(&ad, st->st_dev, st->st_ino, dir->d_did, dir->d_pdid, vol->v_stamp); + } + } + if (ad_flush(&ad) != 0) { + switch (errno) { + case EACCES: + err = AFPERR_ACCESS; + break; + default: + err = AFPERR_MISC; + break; + } + } + ad_close(&ad, ADFLAGS_HF); + } + + if (err == AFP_OK) { + if (set_maccess == true) { + if (dir->d_did == DIRDID_ROOT) { + setdeskmode(vol, mpriv); + if (!dir_rx_set(mpriv)) { + /* we can't remove read and search for owner on volume root */ + err = AFPERR_ACCESS; + goto setprivdone; + } + } + if (setdirunixmode(vol, upath, mpriv) < 0) { + LOG(log_info, logtype_afpd, "setdirparams(\"%s\"): setdirunixmode: %s", + fullpathname(upath), strerror(errno)); + err = set_dir_errors(path, "setdirmode", errno); + } + } + if ((set_upriv == true) && vol_unix_priv(vol)) { + if (dir->d_did == DIRDID_ROOT) { + if (!dir_rx_set(upriv)) { + /* we can't remove read and search for owner on volume root */ + err = AFPERR_ACCESS; + goto setprivdone; + } + setdeskowner(vol, -1, ntohl(group)); + setdeskmode(vol, upriv); + } + + if (setdirowner(vol, upath, -1, ntohl(group)) < 0) { + LOG(log_info, logtype_afpd, "setdirparams(\"%s\"): setdirowner: %s", + fullpathname(upath), strerror(errno)); + err = set_dir_errors(path, "setdirowner", errno); + goto setprivdone; + } + + if (setdirunixmode(vol, upath, upriv) < 0) { + LOG(log_info, logtype_afpd, "setdirparams(\"%s\"): setdirunixmode: %s", + fullpathname(upath), strerror(errno)); + err = set_dir_errors(path, "setdirunixmode", errno); + } + } + } + +setprivdone: + if (change_parent_mdate && dir->d_did != DIRDID_ROOT + && gettimeofday(&tv, NULL) == 0) { + if (movecwd(vol, dirlookup(vol, dir->d_pdid)) == 0) { + newdate = AD_DATE_FROM_UNIX(tv.tv_sec); + /* be careful with bitmap because now dir is null */ + bitmap = 1<d_u_name); + + dfd = dirfd( dp ); + if ( fsync ( dfd ) < 0 ) + LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s", + dir->d_u_name, strerror(errno) ); + closedir(dp); /* closes dfd too */ +#endif + + if ( -1 == (dfd = open(vol->ad_path(".", ADFLAGS_DIR), O_RDWR))) { + switch( errno ) { + case ENOENT: + return( AFPERR_NOOBJ ); + case EACCES: + return( AFPERR_ACCESS ); + default: + return( AFPERR_PARAM ); + } + } + + LOG(log_debug, logtype_afpd, "afp_syncdir: ad-file: '%s'", + vol->ad_path(".", ADFLAGS_DIR) ); + + if ( fsync(dfd) < 0 ) + LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s", + vol->ad_path(cfrombstr(dir->d_u_name), ADFLAGS_DIR), strerror(errno) ); + close(dfd); + } + + return ( AFP_OK ); +} + +int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct adouble ad; + struct vol *vol; + struct dir *dir; + char *upath; + struct path *s_path; + uint32_t did; + uint16_t vid; + int err; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; /* was AFPERR_NOOBJ */ + } + /* for concurrent access we need to be sure we are not in the + * folder we want to create... + */ + movecwd(vol, dir); + + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_PARAM); + } + /* cname was able to move curdir to it! */ + if (*s_path->m_name == '\0') + return AFPERR_EXIST; + + upath = s_path->u_name; + + if (AFP_OK != (err = netatalk_mkdir(vol, upath))) { + return err; + } + + if (of_stat(vol, s_path) < 0) { + return AFPERR_MISC; + } + + curdir->d_offcnt++; + + if ((dir = dir_add(vol, curdir, s_path, strlen(s_path->u_name))) == NULL) { + return AFPERR_MISC; + } + + if ( movecwd( vol, dir ) < 0 ) { + return( AFPERR_PARAM ); + } + + ad_init(&ad, vol); + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_CREATE | ADFLAGS_RDWR, 0777) < 0) { + return( AFPERR_ACCESS ); + } + ad_setname(&ad, s_path->m_name); + ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp); + + fce_register(obj, FCE_DIR_CREATE, bdata(curdir->d_fullpath), NULL); + + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + + memcpy( rbuf, &dir->d_did, sizeof( uint32_t )); + *rbuflen = sizeof( uint32_t ); + setvoltime(obj, vol ); + return( AFP_OK ); +} + +/* + * dst new unix filename (not a pathname) + * newname new mac name + * newparent curdir + * dirfd -1 means ignore dirfd (or use AT_FDCWD), otherwise src is relative to dirfd + */ +int renamedir(struct vol *vol, + int dirfd, + char *src, + char *dst, + struct dir *dir, + struct dir *newparent, + char *newname) +{ + struct adouble ad; + int err; + + /* existence check moved to afp_moveandrename */ + if ( unix_rename(dirfd, src, -1, dst ) < 0 ) { + switch ( errno ) { + case ENOENT : + return( AFPERR_NOOBJ ); + case EACCES : + return( AFPERR_ACCESS ); + case EROFS: + return AFPERR_VLOCK; + case EINVAL: + /* tried to move directory into a subdirectory of itself */ + return AFPERR_CANTMOVE; + case EXDEV: + /* this needs to copy and delete. bleah. that means we have + * to deal with entire directory hierarchies. */ + if ((err = copydir(vol, newparent, dirfd, src, dst)) < 0) { + deletedir(vol, -1, dst); + return err; + } + if ((err = deletedir(vol, dirfd, src)) < 0) + return err; + break; + default : + return( AFPERR_PARAM ); + } + } + + vol->vfs->vfs_renamedir(vol, dirfd, src, dst); + + ad_init(&ad, vol); + + if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR) == 0) { + ad_setname(&ad, newname); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + } + + return( AFP_OK ); +} + +/* delete an empty directory */ +int deletecurdir(struct vol *vol) +{ + struct dirent *de; + struct stat st; + struct dir *fdir, *pdir; + struct adouble ad; + uint16_t ashort; + int err; + + if ((pdir = dirlookup(vol, curdir->d_pdid)) == NULL) { + return( AFPERR_ACCESS ); + } + + fdir = curdir; + + ad_init(&ad, vol); + /* we never want to create a resource fork here, we are going to delete it */ + if ( ad_metadata( ".", ADFLAGS_DIR, &ad) == 0 ) { + + ad_getattr(&ad, &ashort); + ad_close(&ad, ADFLAGS_HF); + if (!(vol->v_ignattr & ATTRBIT_NODELETE) && (ashort & htons(ATTRBIT_NODELETE))) { + return AFPERR_OLOCK; + } + } + err = vol->vfs->vfs_deletecurdir(vol); + if (err) { + LOG(log_error, logtype_afpd, "deletecurdir: error deleting AppleDouble files in \"%s\"", + cfrombstr(curdir->d_fullpath)); + return err; + } + + if (movecwd(vol, pdir) < 0) { + err = afp_errno; + goto delete_done; + } + + LOG(log_debug, logtype_afpd, "deletecurdir: moved to \"%s\"", + cfrombstr(curdir->d_fullpath)); + + err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name)); + + switch (err) { + case AFP_OK: + case AFPERR_NOOBJ: + break; + case AFPERR_DIRNEMPT: + if (delete_vetoed_files(vol, bdata(fdir->d_u_name), false) != 0) + goto delete_done; + err = AFP_OK; + break; + default: + LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error", + cfrombstr(curdir->d_fullpath)); + goto delete_done; + } + + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, fdir->d_did); + AFP_CNID_DONE(); + + dir_remove( vol, fdir ); + +delete_done: + return err; +} + +int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct passwd *pw; + struct group *gr; + char *name; + uint32_t id; + int len, sfunc; + int utf8 = 0; + + ibuf++; + sfunc = (unsigned char) *ibuf++; + *rbuflen = 0; + + if (sfunc >= 3 && sfunc <= 6) { + if (obj->afp_version < 30) { + return( AFPERR_PARAM ); + } + utf8 = 1; + } + + switch ( sfunc ) { + case 1 : + case 3 :/* unicode */ + memcpy( &id, ibuf, sizeof( id )); + id = ntohl(id); + if ( id != 0 ) { + if (( pw = getpwuid( id )) == NULL ) { + return( AFPERR_NOITEM ); + } + len = convert_string_allocate( obj->options.unixcharset, ((!utf8)?obj->options.maccharset:CH_UTF8_MAC), + pw->pw_name, -1, &name); + } else { + len = 0; + name = NULL; + } + break; + case 2 : + case 4 : /* unicode */ + memcpy( &id, ibuf, sizeof( id )); + id = ntohl(id); + if ( id != 0 ) { + if (NULL == ( gr = (struct group *)getgrgid( id ))) { + return( AFPERR_NOITEM ); + } + len = convert_string_allocate( obj->options.unixcharset, (!utf8)?obj->options.maccharset:CH_UTF8_MAC, + gr->gr_name, -1, &name); + } else { + len = 0; + name = NULL; + } + break; + + case 5 : /* UUID -> username */ + case 6 : /* UUID -> groupname */ + if ((obj->afp_version < 32) || !(obj->options.flags & OPTION_UUID )) + return AFPERR_PARAM; + LOG(log_debug, logtype_afpd, "afp_mapid: valid UUID request"); + uuidtype_t type; + len = getnamefromuuid((unsigned char*) ibuf, &name, &type); + if (len != 0) /* its a error code, not len */ + return AFPERR_NOITEM; + switch (type) { + case UUID_USER: + if (( pw = getpwnam( name )) == NULL ) + return( AFPERR_NOITEM ); + LOG(log_debug, logtype_afpd, "afp_mapid: name:%s -> uid:%d", name, pw->pw_uid); + id = htonl(UUID_USER); + memcpy( rbuf, &id, sizeof( id )); + id = htonl( pw->pw_uid); + rbuf += sizeof( id ); + memcpy( rbuf, &id, sizeof( id )); + rbuf += sizeof( id ); + *rbuflen = 2 * sizeof( id ); + break; + case UUID_GROUP: + if (( gr = getgrnam( name )) == NULL ) + return( AFPERR_NOITEM ); + LOG(log_debug, logtype_afpd, "afp_mapid: group:%s -> gid:%d", name, gr->gr_gid); + id = htonl(UUID_GROUP); + memcpy( rbuf, &id, sizeof( id )); + rbuf += sizeof( id ); + id = htonl( gr->gr_gid); + memcpy( rbuf, &id, sizeof( id )); + rbuf += sizeof( id ); + *rbuflen = 2 * sizeof( id ); + break; + default: + return AFPERR_MISC; + } + break; + + default : + return( AFPERR_PARAM ); + } + + if (name) + len = strlen( name ); + + if (utf8) { + uint16_t tp = htons(len); + memcpy(rbuf, &tp, sizeof(tp)); + rbuf += sizeof(tp); + *rbuflen += 2; + } + else { + *rbuf++ = len; + *rbuflen += 1; + } + if ( len > 0 ) { + memcpy( rbuf, name, len ); + } + *rbuflen += len; + if (name) + free(name); + return( AFP_OK ); +} + +int afp_mapname(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct passwd *pw; + struct group *gr; + int len, sfunc; + uint32_t id; + uint16_t ulen; + + ibuf++; + sfunc = (unsigned char) *ibuf++; + *rbuflen = 0; + LOG(log_debug, logtype_afpd, "afp_mapname: sfunc: %d", sfunc); + switch ( sfunc ) { + case 1 : + case 2 : /* unicode */ + if (obj->afp_version < 30) { + return( AFPERR_PARAM ); + } + memcpy(&ulen, ibuf, sizeof(ulen)); + len = ntohs(ulen); + ibuf += 2; + LOG(log_debug, logtype_afpd, "afp_mapname: alive"); + break; + case 3 : + case 4 : + len = (unsigned char) *ibuf++; + break; + case 5 : /* username -> UUID */ + case 6 : /* groupname -> UUID */ + if ((obj->afp_version < 32) || !(obj->options.flags & OPTION_UUID )) + return AFPERR_PARAM; + memcpy(&ulen, ibuf, sizeof(ulen)); + len = ntohs(ulen); + ibuf += 2; + break; + default : + return( AFPERR_PARAM ); + } + + ibuf[ len ] = '\0'; + + if ( len == 0 ) + return AFPERR_PARAM; + else { + switch ( sfunc ) { + case 1 : /* unicode */ + case 3 : + if (NULL == ( pw = (struct passwd *)getpwnam( ibuf )) ) { + return( AFPERR_NOITEM ); + } + id = pw->pw_uid; + id = htonl(id); + memcpy( rbuf, &id, sizeof( id )); + *rbuflen = sizeof( id ); + break; + + case 2 : /* unicode */ + case 4 : + LOG(log_debug, logtype_afpd, "afp_mapname: getgrnam for name: %s",ibuf); + if (NULL == ( gr = (struct group *)getgrnam( ibuf ))) { + return( AFPERR_NOITEM ); + } + id = gr->gr_gid; + LOG(log_debug, logtype_afpd, "afp_mapname: getgrnam for name: %s -> id: %d",ibuf, id); + id = htonl(id); + memcpy( rbuf, &id, sizeof( id )); + *rbuflen = sizeof( id ); + break; + case 5 : /* username -> UUID */ + LOG(log_debug, logtype_afpd, "afp_mapname: name: %s",ibuf); + if (0 != getuuidfromname(ibuf, UUID_USER, (unsigned char *)rbuf)) + return AFPERR_NOITEM; + *rbuflen = UUID_BINSIZE; + break; + case 6 : /* groupname -> UUID */ + LOG(log_debug, logtype_afpd, "afp_mapname: name: %s",ibuf); + if (0 != getuuidfromname(ibuf, UUID_GROUP, (unsigned char *)rbuf)) + return AFPERR_NOITEM; + *rbuflen = UUID_BINSIZE; + break; + } + } + return( AFP_OK ); +} + +/* ------------------------------------ + variable DID support +*/ +int afp_closedir(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ +#if 0 + struct vol *vol; + struct dir *dir; + uint16_t vid; + uint32_t did; +#endif /* 0 */ + + *rbuflen = 0; + + /* do nothing as dids are static for the life of the process. */ +#if 0 + ibuf += 2; + + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (( vol = getvolbyvid( vid )) == NULL ) { + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (( dir = dirlookup( vol, did )) == NULL ) { + return( AFPERR_PARAM ); + } + + /* dir_remove -- deletedid */ +#endif /* 0 */ + + return AFP_OK; +} + +/* did creation gets done automatically + * there's a pb again with case but move it to cname + */ +int afp_opendir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + struct dir *parentdir; + struct path *path; + uint32_t did; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof(vid)); + ibuf += sizeof( vid ); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + memcpy(&did, ibuf, sizeof(did)); + ibuf += sizeof(did); + + if (NULL == ( parentdir = dirlookup( vol, did )) ) { + return afp_errno; + } + + if (NULL == ( path = cname( vol, parentdir, &ibuf )) ) { + return get_afp_errno(AFPERR_PARAM); + } + + if ( *path->m_name != '\0' ) { + return path_error(path, AFPERR_NOOBJ); + } + + if ( !path->st_valid && of_stat(vol, path) < 0 ) { + return( AFPERR_NOOBJ ); + } + if ( path->st_errno ) { + return( AFPERR_NOOBJ ); + } + + memcpy(rbuf, &curdir->d_did, sizeof(curdir->d_did)); + *rbuflen = sizeof(curdir->d_did); + return AFP_OK; +} diff --git a/etc/afpd/directory.h b/etc/afpd/directory.h new file mode 100644 index 0000000..eb89c60 --- /dev/null +++ b/etc/afpd/directory.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifndef AFPD_DIRECTORY_H +#define AFPD_DIRECTORY_H 1 + +#include +#include +#include + +/* sys/types.h usually snarfs in major/minor macros. if they don't + * try this file. */ +#ifndef major +#include +#endif + +#include +#include + +#include "volume.h" + +/* directory bits */ +#define DIRPBIT_ATTR 0 +#define DIRPBIT_PDID 1 +#define DIRPBIT_CDATE 2 +#define DIRPBIT_MDATE 3 +#define DIRPBIT_BDATE 4 +#define DIRPBIT_FINFO 5 +#define DIRPBIT_LNAME 6 +#define DIRPBIT_SNAME 7 +#define DIRPBIT_DID 8 +#define DIRPBIT_OFFCNT 9 +#define DIRPBIT_UID 10 +#define DIRPBIT_GID 11 +#define DIRPBIT_ACCESS 12 +#define DIRPBIT_PDINFO 13 /* ProDOS Info */ +#define DIRPBIT_UNIXPR 15 + +#define FILDIRBIT_ISDIR (1 << 7) /* is a directory */ +#define FILDIRBIT_ISFILE (0) /* is a file */ + +/* file/directory ids. what a mess. we scramble things in a vain attempt + * to get something meaningful */ +#ifndef AFS + +#if 0 +#define CNID_XOR(a) (((a) >> 16) ^ (a)) +#define CNID_DEV(a) ((((CNID_XOR(major((a)->st_dev)) & 0xf) << 3) | \ + (CNID_XOR(minor((a)->st_dev)) & 0x7)) << 24) +#define CNID_INODE(a) (((a)->st_ino ^ (((a)->st_ino & 0xff000000) >> 8)) \ + & 0x00ffffff) +#define CNID_FILE(a) (((a) & 0x1) << 31) +#define CNID(a,b) (CNID_DEV(a) | CNID_INODE(a) | CNID_FILE(b)) +#endif + +#define CNID(a,b) ((a)->st_ino & 0xffffffff) + +#else /* AFS */ +#define CNID(a,b) (((a)->st_ino & 0x7fffffff) | CNID_FILE(b)) +#endif /* AFS */ + +struct maccess { + u_char ma_user; + u_char ma_world; + u_char ma_group; + u_char ma_owner; +}; + +#define AR_USEARCH (1<<0) +#define AR_UREAD (1<<1) +#define AR_UWRITE (1<<2) +#define AR_UOWN (1<<7) + +q_t *invalid_dircache_entries; + +typedef int (*dir_loop)(struct dirent *, char *, void *); + +extern void dir_free_invalid_q(void); +extern struct dir *dir_new(const char *mname, const char *uname, const struct vol *, + cnid_t pdid, cnid_t did, bstring fullpath, struct stat *); +extern void dir_free (struct dir *); +extern struct dir *dir_add(struct vol *, const struct dir *, struct path *, int); +extern int dir_modify(const struct vol *vol, struct dir *dir, cnid_t pdid, cnid_t did, + const char *new_mname, const char *new_uname, bstring pdir_fullpath); +extern int dir_remove(const struct vol *vol, struct dir *dir); +extern struct dir *dirlookup (const struct vol *, cnid_t); +extern struct dir *dirlookup_bypath(const struct vol *vol, const char *path); + +extern int movecwd (const struct vol *, struct dir *); +extern struct path *cname (struct vol *, struct dir *, char **); + +extern int deletecurdir (struct vol *); +extern mode_t mtoumode (struct maccess *); +extern int getdirparams (const AFPObj *obj, const struct vol *, uint16_t, struct path *, + struct dir *, char *, size_t *); + +extern int setdirparams(struct vol *, struct path *, uint16_t, char *); +extern int renamedir(struct vol *, int, char *, char *, struct dir *, + struct dir *, char *); +extern int path_error(struct path *, int error); +extern void setdiroffcnt(struct dir *dir, struct stat *st, uint32_t count); +extern int dirreenumerate(struct dir *dir, struct stat *st); +extern int for_each_dirent(const struct vol *, char *, dir_loop , void *); +extern int check_access(const AFPObj *obj, struct vol *, char *name , int mode); +extern int file_access(const AFPObj *obj, struct vol *vol, struct path *path, int mode); +extern int netatalk_unlink (const char *name); + +/* from enumerate.c */ +extern char *check_dirent (const struct vol *, char *); + +/* FP functions */ +int afp_createdir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_opendir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setdirparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_closedir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_mapid (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_mapname (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_syncdir (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +/* from enumerate.c */ +int afp_enumerate (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_enumerate_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_enumerate_ext2 (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +/* from catsearch.c */ +int afp_catsearch (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_catsearch_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +#endif diff --git a/etc/afpd/enumerate.c b/etc/afpd/enumerate.c new file mode 100644 index 0000000..340f79a --- /dev/null +++ b/etc/afpd/enumerate.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "desktop.h" +#include "directory.h" +#include "dircache.h" +#include "volume.h" +#include "file.h" +#include "fork.h" +#include "filedir.h" + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* + * Struct to save directory reading context in. Used to prevent + * O(n^2) searches on a directory. + */ +struct savedir { + u_short sd_vid; + uint32_t sd_did; + int sd_buflen; + char *sd_buf; + char *sd_last; + unsigned int sd_sindex; +}; +#define SDBUFBRK 2048 + +static int enumerate_loop(struct dirent *de, char *mname _U_, void *data) +{ + struct savedir *sd = data; + char *start, *end; + int len,lenm; + + end = sd->sd_buf + sd->sd_buflen; + len = strlen(de->d_name); + *(sd->sd_last)++ = len; + lenm = 0; /* strlen(mname);*/ + if ( sd->sd_last + len +lenm + 4 > end ) { + char *buf; + + start = sd->sd_buf; + if (!(buf = realloc( sd->sd_buf, sd->sd_buflen +SDBUFBRK )) ) { + LOG(log_error, logtype_afpd, "afp_enumerate: realloc: %s", + strerror(errno) ); + errno = ENOMEM; + return -1; + } + sd->sd_buf = buf; + sd->sd_buflen += SDBUFBRK; + sd->sd_last = ( sd->sd_last - start ) + sd->sd_buf; + end = sd->sd_buf + sd->sd_buflen; + } + + memcpy( sd->sd_last, de->d_name, len + 1 ); + sd->sd_last += len + 1; +#if 0 + *(sd->sd_last)++ = lenm; + memcpy( sd->sd_last, mname, lenm + 1 ); + sd->sd_last += lenm + 1; +#endif + return 0; +} + +/* ----------------------------- + * FIXME: + * Doesn't work with dangling symlink + * ie: + * - Move a folder with a dangling symlink in the trash + * - empty the trash + * afp_enumerate return an empty listing but offspring count != 0 in afp_getdirparams + * and the Mac doesn't try to call afp_delete! + * + * Another option for symlink + * cf: + * http://sourceforge.net/tracker/index.php?func=detail&aid=461938&group_id=8642&atid=108642 + * +*/ +char *check_dirent(const struct vol *vol, char *name) +{ + if (!strcmp(name, "..") || !strcmp(name, ".")) + return NULL; + + if (!vol->vfs->vfs_validupath(vol, name)) + return NULL; + + /* check for vetoed filenames */ + if (veto_file(vol->v_veto, name)) + return NULL; + +#if 0 + char *m_name = NULL; + + if (NULL == (m_name = utompath(vol, name, 0, utf8_encoding()))) + return NULL; + + /* now check against too big a file */ + if (strlen(m_name) > vol->max_filename) + return NULL; +#endif + return name; +} + +/* ----------------------------- */ +int +for_each_dirent(const struct vol *vol, char *name, dir_loop fn, void *data) +{ + DIR *dp; + struct dirent *de; + char *m_name; + int ret; + + if (NULL == ( dp = opendir( name)) ) { + return -1; + } + ret = 0; + for ( de = readdir( dp ); de != NULL; de = readdir( dp )) { + if (!(m_name = check_dirent(vol, de->d_name))) + continue; + + ret++; + if (fn && fn(de,m_name, data) < 0) { + closedir(dp); + return -1; + } + } + closedir(dp); + return ret; +} + +/* This is the maximal length of a single entry for a file/dir in the reply + block if all bits in the file/dir bitmap are set: header(4) + params(104) + + macnamelength(1) + macname(31) + utf8(4) + utf8namelen(2) + utf8name(255) + + oddpadding(1) */ + +#define REPLY_PARAM_MAXLEN (4 + 104 + 1 + MACFILELEN + 4 + 2 + UTF8FILELEN_EARLY + 1) + +/* ----------------------------- */ +static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, + char *rbuf, + size_t *rbuflen, + int ext) +{ + static struct savedir sd = { 0, 0, 0, NULL, NULL, 0 }; + struct vol *vol; + struct dir *dir; + int did, ret, len, first = 1; + size_t esz; + char *data, *start; + uint16_t vid, fbitmap, dbitmap, reqcnt, actcnt = 0; + uint16_t temp16; + uint32_t sindex, maxsz, sz = 0; + struct path *o_path; + struct path s_path; + int header; + + if ( sd.sd_buflen == 0 ) { + if (( sd.sd_buf = (char *)malloc( SDBUFBRK )) == NULL ) { + LOG(log_error, logtype_afpd, "afp_enumerate: malloc: %s", strerror(errno) ); + *rbuflen = 0; + return AFPERR_MISC; + } + sd.sd_buflen = SDBUFBRK; + } + + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + + if (NULL == ( dir = dirlookup( vol, did )) ) { + *rbuflen = 0; + return (afp_errno == AFPERR_NOOBJ)?AFPERR_NODIR:afp_errno; + } + + memcpy( &fbitmap, ibuf, sizeof( fbitmap )); + fbitmap = ntohs( fbitmap ); + ibuf += sizeof( fbitmap ); + + memcpy( &dbitmap, ibuf, sizeof( dbitmap )); + dbitmap = ntohs( dbitmap ); + ibuf += sizeof( dbitmap ); + + /* check for proper bitmaps -- the stuff in comments is for + * variable directory ids. */ + if (!(fbitmap || dbitmap) + /*|| (fbitmap & (1 << FILPBIT_PDID)) || + (dbitmap & (1 << DIRPBIT_PDID))*/) { + *rbuflen = 0; + return AFPERR_BITMAP; + } + + memcpy( &reqcnt, ibuf, sizeof( reqcnt )); + reqcnt = ntohs( reqcnt ); + ibuf += sizeof( reqcnt ); + + if (ext == 2) { + memcpy( &sindex, ibuf, sizeof( sindex )); + sindex = ntohl( sindex ); + ibuf += sizeof( sindex ); + } + else { + memcpy( &temp16, ibuf, sizeof( temp16 )); + sindex = ntohs( temp16 ); + ibuf += sizeof( temp16 ); + } + + if (!sindex) { + *rbuflen = 0; + return AFPERR_PARAM ; + } + + if (ext == 2) { + memcpy( &maxsz, ibuf, sizeof( maxsz )); + maxsz = ntohl( maxsz ); + ibuf += sizeof( maxsz ); + } + else { + memcpy( &temp16, ibuf, sizeof( temp16 )); + maxsz = ntohs( temp16 ); + ibuf += sizeof( temp16 ); + } + + header = (ext)?4:2; + header *=sizeof( u_char ); + + maxsz = min(maxsz, *rbuflen - REPLY_PARAM_MAXLEN); + o_path = cname( vol, dir, &ibuf ); + + if (afp_errno == AFPERR_NOOBJ) + afp_errno = AFPERR_NODIR; + + *rbuflen = 0; + if (NULL == o_path ) { + return get_afp_errno(AFPERR_NOOBJ); + } + if ( *o_path->m_name != '\0') { + /* it's a file or it's a dir and extendir() was unable to chdir in it */ + return path_error(o_path, AFPERR_NODIR ); + } + + LOG(log_debug, logtype_afpd, "enumerate(\"%s/%s\", f/d:%04x/%04x, rc:%u, i:%u, max:%u)", + getcwdpath(), o_path->u_name, fbitmap, dbitmap, reqcnt, sindex, maxsz); + + data = rbuf + 3 * sizeof( uint16_t ); + sz = 3 * sizeof( uint16_t ); /* fbitmap, dbitmap, reqcount */ + + /* + * Read the directory into a pre-malloced buffer, stored + * len \0 + * The end is indicated by a len of 0. + */ + if ( sindex == 1 || curdir->d_did != sd.sd_did || vid != sd.sd_vid ) { + sd.sd_last = sd.sd_buf; + /* if dir was in the cache we don't have the inode */ + if (( !o_path->st_valid && ostat(".", &o_path->st, vol_syml_opt(vol)) < 0 ) || + (ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0) + { + LOG(log_error, logtype_afpd, "enumerate: loop error: %s (%d)", strerror(errno), errno); + switch (errno) { + case EACCES: + return AFPERR_ACCESS; + case ENOTDIR: + return AFPERR_BADTYPE; + case ENOMEM: + return AFPERR_MISC; + default: + return AFPERR_NODIR; + } + } + setdiroffcnt(curdir, &o_path->st, ret); + *sd.sd_last = 0; + + sd.sd_last = sd.sd_buf; + sd.sd_sindex = 1; + + sd.sd_vid = vid; + sd.sd_did = curdir->d_did; + } + + /* + * Position sd_last as dictated by sindex. + */ + if ( sindex < sd.sd_sindex ) { + sd.sd_sindex = 1; + sd.sd_last = sd.sd_buf; + } + while ( sd.sd_sindex < sindex ) { + len = (unsigned char)*(sd.sd_last)++; + if ( len == 0 ) { + sd.sd_did = 0; /* invalidate sd struct to force re-read */ + return( AFPERR_NOOBJ ); + } + sd.sd_last += len + 1; + sd.sd_sindex++; + } + + while (( len = (unsigned char)*(sd.sd_last)) != 0 ) { + /* + * If we've got all we need, send it. + */ + if ( actcnt == reqcnt ) { + break; + } + + /* + * Save the start position, in case we exceed the buffer + * limitation, and have to back up one. + */ + start = sd.sd_last; + sd.sd_last++; + + if (*sd.sd_last == 0) { + /* stat() already failed on this one */ + sd.sd_last += len + 1; + continue; + } + + memset(&s_path, 0, sizeof(s_path)); + s_path.u_name = sd.sd_last; + if (of_stat(vol, &s_path) < 0 ) { + /* so the next time it won't try to stat it again + * another solution would be to invalidate the cache with + * sd.sd_did = 0 but if it's not ENOENT error it will start again + */ + *sd.sd_last = 0; + sd.sd_last += len + 1; + curdir->d_offcnt--; /* a little lie */ + continue; + } + + /* conversions on the fly */ + const char *convname; + if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0) { + if (convname) { + s_path.u_name = (char *)convname; + AFP_CNID_START("cnid_lookup"); + s_path.id = cnid_lookup(vol->v_cdb, &s_path.st, curdir->d_did, sd.sd_last, strlen(sd.sd_last)); + AFP_CNID_DONE(); + if (s_path.id != CNID_INVALID) { + AFP_CNID_START("cnid_update"); + int cnid_up_ret = cnid_update(vol->v_cdb, s_path.id, &s_path.st, curdir->d_did, (char *)convname, strlen(convname)); + AFP_CNID_DONE(); + if (cnid_up_ret != 0) + LOG(log_error, logtype_afpd, "enumerate: error updating CNID of \"%s\"", fullpathname(convname)); + } + } + } + + sd.sd_last += len + 1; + s_path.m_name = NULL; + + /* + * If a fil/dir is not a dir, it's a file. This is slightly + * inaccurate, since that means /dev/null is a file, /dev/printer + * is a file, etc. + */ + if ( S_ISDIR(s_path.st.st_mode)) { + if ( dbitmap == 0 ) { + continue; + } + int len = strlen(s_path.u_name); + if ((dir = dircache_search_by_name(vol, curdir, s_path.u_name, len)) == NULL) { + if ((dir = dir_add(vol, curdir, &s_path, len)) == NULL) { + LOG(log_error, logtype_afpd, "enumerate(vid:%u, did:%u, name:'%s'): error adding dir: '%s'", + ntohs(vid), ntohl(did), o_path->u_name, s_path.u_name); + return AFPERR_MISC; + } + } + if ((ret = getdirparams(obj, vol, dbitmap, &s_path, dir, data + header , &esz)) != AFP_OK) + return( ret ); + + } else { + if ( fbitmap == 0 ) { + continue; + } + /* files are added to the dircache in getfilparams() -> getmetadata() */ + if (AFP_OK != ( ret = getfilparams(obj, vol, fbitmap, &s_path, curdir, + data + header, &esz, 1)) ) { + return( ret ); + } + } + + /* + * Make sure entry is an even length, possibly with a null + * byte on the end. + */ + if ( (esz + header) & 1 ) { + *(data + header + esz ) = '\0'; + esz++; + } + + /* + * Check if we've exceeded the size limit. + */ + if ( maxsz < sz + esz + header) { + if (first) { /* maxsz can't hold a single reply */ + return AFPERR_PARAM; + } + sd.sd_last = start; + break; + } + + if (first) + first = 0; + + sz += esz + header; + if (ext) { + temp16 = htons( esz + header ); + memcpy( data, &temp16, sizeof( temp16 )); + data += sizeof(temp16); + } + else { + *data++ = esz + header; + } + + *data++ = S_ISDIR(s_path.st.st_mode) ? FILDIRBIT_ISDIR : FILDIRBIT_ISFILE; + if (ext) { + *data++ = 0; + } + data += esz; + actcnt++; + /* FIXME if we rollover 16 bits and it's not FPEnumerateExt2 */ + } + + if ( actcnt == 0 ) { + sd.sd_did = 0; /* invalidate sd struct to force re-read */ + /* + * in case were converting adouble stuff: + * after enumerating the whole dir we should have converted everything + * thus the .AppleDouble dir shouls be empty thus we can no try to + * delete it + */ + if (vol->v_adouble == AD_VERSION_EA && ! (vol->v_flags & AFPVOL_NOV2TOEACONV)) + (void)rmdir(".AppleDouble"); + + return( AFPERR_NOOBJ ); + } + sd.sd_sindex = sindex + actcnt; + + /* + * All done, fill in misc junk in rbuf + */ + fbitmap = htons( fbitmap ); + memcpy( rbuf, &fbitmap, sizeof( fbitmap )); + rbuf += sizeof( fbitmap ); + dbitmap = htons( dbitmap ); + memcpy( rbuf, &dbitmap, sizeof( dbitmap )); + rbuf += sizeof( dbitmap ); + actcnt = htons( actcnt ); + memcpy( rbuf, &actcnt, sizeof( actcnt )); + rbuf += sizeof( actcnt ); + *rbuflen = sz; + return( AFP_OK ); +} + +/* ----------------------------- */ +int afp_enumerate(AFPObj *obj, char *ibuf, size_t ibuflen, + char *rbuf, + size_t *rbuflen) +{ + return enumerate(obj, ibuf,ibuflen ,rbuf,rbuflen , 0); +} + +/* ----------------------------- */ +int afp_enumerate_ext(AFPObj *obj, char *ibuf, size_t ibuflen, + char *rbuf, + size_t *rbuflen) +{ + return enumerate(obj, ibuf,ibuflen ,rbuf,rbuflen , 1); +} + +/* ----------------------------- */ +int afp_enumerate_ext2(AFPObj *obj, char *ibuf, size_t ibuflen, + char *rbuf, + size_t *rbuflen) +{ + return enumerate(obj, ibuf,ibuflen ,rbuf,rbuflen , 2); +} + diff --git a/etc/afpd/extattrs.c b/etc/afpd/extattrs.c new file mode 100644 index 0000000..18f5c78 --- /dev/null +++ b/etc/afpd/extattrs.c @@ -0,0 +1,522 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "volume.h" +#include "desktop.h" +#include "directory.h" +#include "fork.h" +#include "extattrs.h" + +static const char *ea_finderinfo = "com.apple.FinderInfo"; +static const char *ea_resourcefork = "com.apple.ResourceFork"; + +/* This should be big enough to consecutively store the names of all attributes */ +static char attrnamebuf[ATTRNAMEBUFSIZ]; + +#ifdef DEBUG +static void hexdump(void *m, size_t l) { + char *p = m; + int count = 0, len; + char buf[100]; + char *bufp = buf; + + while (l--) { + len = sprintf(bufp, "%02x ", *p++); + bufp += len; + count++; + + if ((count % 16) == 0) { + LOG(log_debug9, logtype_afpd, "%s", buf); + bufp = buf; + } + } +} +#endif + +/*************************************** + * AFP funcs + ****************************************/ + +/* + Note: we're being called twice. Firstly the client only want the size of all + EA names, secondly it wants these names. In order to avoid scanning EAs twice + we cache them in a static buffer. +*/ +int afp_listextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + int ret, oflag = 0, adflags = 0, fd = -1; + uint16_t vid, bitmap, uint16; + uint32_t did, maxreply, tmpattr; + struct vol *vol; + struct dir *dir; + struct path *s_path; + struct stat *st; + struct adouble ad, *adp = NULL; + struct ofork *opened = NULL; + char *uname, *FinderInfo; + char emptyFinderInfo[32] = { 0 }; + + static int buf_valid = 0; + static size_t attrbuflen = 0; + + *rbuflen = 0; + ibuf += 2; + + /* Get Bitmap and MaxReplySize first */ + memcpy( &bitmap, ibuf +6, sizeof(bitmap)); + bitmap = ntohs( bitmap ); + + memcpy( &maxreply, ibuf + 14, sizeof (maxreply)); + maxreply = ntohl( maxreply ); + + /* + If its the first request with maxreply=0 or if we didn't mark our buffers valid for + whatever reason (just a safety check, it should be valid), then scan for attributes + */ + if ((maxreply == 0) || (buf_valid == 0)) { + + attrbuflen = 0; + + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + if (NULL == ( vol = getvolbyvid( vid )) ) { + LOG(log_debug, logtype_afpd, "afp_listextattr: getvolbyvid error: %s", strerror(errno)); + return AFPERR_ACCESS; + } + + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); + if (NULL == ( dir = dirlookup( vol, did )) ) { + LOG(log_debug, logtype_afpd, "afp_listextattr: dirlookup error: %s", strerror(errno)); + return afp_errno; + } + + if (bitmap & kXAttrNoFollow) + oflag = O_NOFOLLOW; + /* Skip Bitmap, ReqCount, StartIndex and maxreply*/ + ibuf += 12; + + /* get name */ + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + LOG(log_debug, logtype_afpd, "afp_listextattr: cname error: %s", strerror(errno)); + return AFPERR_NOOBJ; + } + + st = &s_path->st; + if (!s_path->st_valid) { + /* it's a dir in our cache, we didn't stat it, do it now */ + of_statdir(vol, s_path); + } + if ( s_path->st_errno != 0 ) { + return( AFPERR_NOOBJ ); + } + + uname = s_path->u_name; + /* + We have to check the FinderInfo for the file, because if they aren't all 0 + we must return the synthetic attribute "com.apple.FinderInfo". + Note: the client will never (never seen in traces) request that attribute + via FPGetExtAttr ! + */ + + adp = &ad; + ad_init(adp, vol); + + if (path_isadir(s_path)) { + LOG(log_debug, logtype_afpd, "afp_listextattr(%s): is a dir", uname); + adflags = ADFLAGS_DIR; + } else { + LOG(log_debug, logtype_afpd, "afp_listextattr(%s): is a file", uname); + opened = of_findname(vol, s_path); + if (opened) { + adp = opened->of_ad; + fd = ad_meta_fileno(adp); + } + } + + if (ad_metadata(uname, adflags, adp) != 0 ) { + switch (errno) { + case ENOENT: + break; + case EACCES: + LOG(log_error, logtype_afpd, "afp_listextattr(%s): %s: check resource fork permission?", + uname, strerror(errno)); + return AFPERR_ACCESS; + default: + LOG(log_error, logtype_afpd, "afp_listextattr(%s): error getting metadata: %s", uname, strerror(errno)); + return AFPERR_MISC; + } + } else { + FinderInfo = ad_entry(adp, ADEID_FINDERI); + /* Check if FinderInfo equals default and empty FinderInfo*/ + if (memcmp(FinderInfo, emptyFinderInfo, 32) != 0) { + /* FinderInfo contains some non 0 bytes -> include "com.apple.FinderInfo" */ + strcpy(attrnamebuf, ea_finderinfo); + attrbuflen += strlen(ea_finderinfo) + 1; + LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): sending com.apple.FinderInfo", uname); + } + + /* Now check for Ressource fork and add virtual EA "com.apple.ResourceFork" if size > 0 */ + LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): Ressourcefork size: %llu", uname, adp->ad_rlen); + + if (adp->ad_rlen > 0) { + LOG(log_debug7, logtype_afpd, "afp_listextattr(%s): sending com.apple.RessourceFork.", uname); + strcpy(attrnamebuf + attrbuflen, ea_resourcefork); + attrbuflen += strlen(ea_resourcefork) + 1; + } + } + + ret = vol->vfs->vfs_ea_list(vol, attrnamebuf, &attrbuflen, uname, oflag, fd); + + switch (ret) { + case AFPERR_BADTYPE: + /* its a symlink and client requested O_NOFOLLOW */ + LOG(log_debug, logtype_afpd, "afp_listextattr(%s): encountered symlink with kXAttrNoFollow", uname); + attrbuflen = 0; + buf_valid = 0; + ret = AFP_OK; + goto exit; + case AFPERR_MISC: + attrbuflen = 0; + goto exit; + default: + buf_valid = 1; + } + } /* if ((maxreply == 0) || (buf_valid == 0)) */ + + /* Start building reply packet */ + bitmap = htons(bitmap); + memcpy( rbuf, &bitmap, sizeof(bitmap)); + rbuf += sizeof(bitmap); + *rbuflen += sizeof(bitmap); + + tmpattr = htonl(attrbuflen); + memcpy( rbuf, &tmpattr, sizeof(tmpattr)); + rbuf += sizeof(tmpattr); + *rbuflen += sizeof(tmpattr); + + /* Only copy buffer if the client asked for it (2nd request, maxreply>0) + and we didnt have an error (buf_valid) */ + if (maxreply && buf_valid) { + memcpy( rbuf, attrnamebuf, attrbuflen); + *rbuflen += attrbuflen; + buf_valid = 0; + } + + ret = AFP_OK; + +exit: + if (ret != AFP_OK) + buf_valid = 0; + + if (adp) + ad_close(adp, ADFLAGS_HF); + + return ret; +} + +static char *to_stringz(char *ibuf, uint16_t len) +{ +static char attrmname[256]; + + if (len > 255) + /* dont fool with us */ + len = 255; + + /* we must copy the name as its not 0-terminated and I DONT WANT TO WRITE to ibuf */ + strlcpy(attrmname, ibuf, len + 1); + return attrmname; +} + +int afp_getextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + int ret, oflag = 0, fd = -1; + uint16_t vid, bitmap, attrnamelen; + uint32_t did, maxreply; + char attruname[256]; + struct vol *vol; + struct dir *dir; + struct path *s_path; + struct adouble ad, *adp = NULL; + struct ofork *opened = NULL; + + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + if (NULL == ( vol = getvolbyvid( vid )) ) { + LOG(log_debug, logtype_afpd, "afp_getextattr: getvolbyvid error: %s", strerror(errno)); + return AFPERR_ACCESS; + } + + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); + if (NULL == ( dir = dirlookup( vol, did )) ) { + LOG(log_debug, logtype_afpd, "afp_getextattr: dirlookup error: %s", strerror(errno)); + return afp_errno; + } + + memcpy( &bitmap, ibuf, sizeof(bitmap)); + bitmap = ntohs( bitmap ); + ibuf += sizeof(bitmap); + + if (bitmap & kXAttrNoFollow) + oflag = O_NOFOLLOW; + + /* Skip Offset and ReqCount */ + ibuf += 16; + + /* Get MaxReply */ + memcpy(&maxreply, ibuf, sizeof(maxreply)); + maxreply = ntohl(maxreply); + ibuf += sizeof(maxreply); + + /* get name */ + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + LOG(log_debug, logtype_afpd, "afp_getextattr: cname error: %s", strerror(errno)); + return AFPERR_NOOBJ; + } + + if ((unsigned long)ibuf & 1) + ibuf++; + + /* get length of EA name */ + memcpy(&attrnamelen, ibuf, sizeof(attrnamelen)); + attrnamelen = ntohs(attrnamelen); + ibuf += sizeof(attrnamelen); + + LOG(log_debug, logtype_afpd, "afp_getextattr(%s): EA: %s", s_path->u_name, to_stringz(ibuf, attrnamelen)); + + /* Convert EA name in utf8 to unix charset */ + if ( 0 >= convert_string(CH_UTF8_MAC, obj->options.unixcharset, ibuf, attrnamelen, attruname, 256) ) + return AFPERR_MISC; + + /* write bitmap now */ + bitmap = htons(bitmap); + memcpy(rbuf, &bitmap, sizeof(bitmap)); + rbuf += sizeof(bitmap); + *rbuflen += sizeof(bitmap); + + if (path_isadir(s_path)) { + LOG(log_debug, logtype_afpd, "afp_getextattr(%s): is a dir", s_path->u_name); + } else { + LOG(log_debug, logtype_afpd, "afp_getextattr(%s): is a file", s_path->u_name); + opened = of_findname(vol, s_path); + if (opened) { + adp = opened->of_ad; + fd = ad_meta_fileno(adp); + } + } + + /* + Switch on maxreply: + if its 0 we must return the size of the requested attribute, + if its non 0 we must return the attribute. + */ + if (maxreply == 0) + ret = vol->vfs->vfs_ea_getsize(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname, fd); + else + ret = vol->vfs->vfs_ea_getcontent(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname, maxreply, fd); + + return ret; +} + +int afp_setextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + int oflag = 0, ret, fd = -1; + uint16_t vid, bitmap, attrnamelen; + uint32_t did, attrsize; + char attruname[256]; + char *attrmname; + struct vol *vol; + struct dir *dir; + struct path *s_path; + struct adouble ad, *adp = NULL; + struct ofork *opened = NULL; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + if (NULL == ( vol = getvolbyvid( vid )) ) { + LOG(log_debug, logtype_afpd, "afp_setextattr: getvolbyvid error: %s", strerror(errno)); + return AFPERR_ACCESS; + } + + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); + if (NULL == ( dir = dirlookup( vol, did )) ) { + LOG(log_debug, logtype_afpd, "afp_setextattr: dirlookup error: %s", strerror(errno)); + return afp_errno; + } + + memcpy( &bitmap, ibuf, sizeof(bitmap)); + bitmap = ntohs( bitmap ); + ibuf += sizeof(bitmap); + + if (bitmap & kXAttrNoFollow) + oflag |= O_NOFOLLOW; + + if (bitmap & kXAttrCreate) + oflag |= O_CREAT; + else if (bitmap & kXAttrReplace) + oflag |= O_TRUNC; + + /* Skip Offset */ + ibuf += 8; + + /* get name */ + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + LOG(log_debug, logtype_afpd, "afp_setextattr: cname error: %s", strerror(errno)); + return AFPERR_NOOBJ; + } + + if (path_isadir(s_path)) { + LOG(log_debug, logtype_afpd, "afp_setextattr(%s): is a dir", s_path->u_name); + } else { + LOG(log_debug, logtype_afpd, "afp_setextattr(%s): is a file", s_path->u_name); + opened = of_findname(vol, s_path); + if (opened) { + adp = opened->of_ad; + fd = ad_meta_fileno(adp); + } + } + + + if ((unsigned long)ibuf & 1) + ibuf++; + + /* get length of EA name */ + memcpy(&attrnamelen, ibuf, sizeof(attrnamelen)); + attrnamelen = ntohs(attrnamelen); + ibuf += sizeof(attrnamelen); + if (attrnamelen > 255) + return AFPERR_PARAM; + + attrmname = ibuf; + /* Convert EA name in utf8 to unix charset */ + if ( 0 >= convert_string(CH_UTF8_MAC, obj->options.unixcharset, attrmname, attrnamelen, attruname, 256)) + return AFPERR_MISC; + + ibuf += attrnamelen; + /* get EA size */ + memcpy(&attrsize, ibuf, sizeof(attrsize)); + attrsize = ntohl(attrsize); + ibuf += sizeof(attrsize); + if (attrsize > MAX_EA_SIZE) + /* we arbitrarily make this fatal */ + return AFPERR_PARAM; + + LOG(log_debug, logtype_afpd, "afp_setextattr(%s): EA: %s, size: %u", s_path->u_name, to_stringz(attrmname, attrnamelen), attrsize); + + ret = vol->vfs->vfs_ea_set(vol, s_path->u_name, attruname, ibuf, attrsize, oflag, fd); + + return ret; +} + +int afp_remextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + int oflag = 0, ret, fd = -1; + uint16_t vid, bitmap, attrnamelen; + uint32_t did; + char attruname[256]; + struct vol *vol; + struct dir *dir; + struct path *s_path; + struct adouble ad, *adp = NULL; + struct ofork *opened = NULL; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + if (NULL == ( vol = getvolbyvid( vid )) ) { + LOG(log_debug, logtype_afpd, "afp_remextattr: getvolbyvid error: %s", strerror(errno)); + return AFPERR_ACCESS; + } + + memcpy( &did, ibuf, sizeof(did)); + ibuf += sizeof(did); + if (NULL == ( dir = dirlookup( vol, did )) ) { + LOG(log_debug, logtype_afpd, "afp_remextattr: dirlookup error: %s", strerror(errno)); + return afp_errno; + } + + memcpy( &bitmap, ibuf, sizeof(bitmap)); + bitmap = ntohs( bitmap ); + ibuf += sizeof(bitmap); + + if (bitmap & kXAttrNoFollow) + oflag |= O_NOFOLLOW; + + /* get name */ + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + LOG(log_debug, logtype_afpd, "afp_remextattr: cname error: %s", strerror(errno)); + return AFPERR_NOOBJ; + } + + if (path_isadir(s_path)) { + LOG(log_debug, logtype_afpd, "afp_remextattr(%s): is a dir", s_path->u_name); + } else { + LOG(log_debug, logtype_afpd, "afp_remextattr(%s): is a file", s_path->u_name); + opened = of_findname(vol, s_path); + if (opened) { + adp = opened->of_ad; + fd = ad_meta_fileno(adp); + } + } + + if ((unsigned long)ibuf & 1) + ibuf++; + + /* get length of EA name */ + memcpy(&attrnamelen, ibuf, sizeof(attrnamelen)); + attrnamelen = ntohs(attrnamelen); + ibuf += sizeof(attrnamelen); + if (attrnamelen > 255) + return AFPERR_PARAM; + + /* Convert EA name in utf8 to unix charset */ + if ( 0 >= (convert_string(CH_UTF8_MAC, obj->options.unixcharset,ibuf, attrnamelen, attruname, 256)) ) + return AFPERR_MISC; + + LOG(log_debug, logtype_afpd, "afp_remextattr(%s): EA: %s", s_path->u_name, to_stringz(ibuf, attrnamelen)); + + ret = vol->vfs->vfs_ea_remove(vol, s_path->u_name, attruname, oflag, fd); + + return ret; +} + diff --git a/etc/afpd/extattrs.h b/etc/afpd/extattrs.h new file mode 100644 index 0000000..68e6590 --- /dev/null +++ b/etc/afpd/extattrs.h @@ -0,0 +1,24 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. + */ + +#ifndef AFPD_EXT_ATTRS_H +#define AFPD_EXT_ATTRS_H + +/* AFP funcs */ +int afp_listextattr (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getextattr (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setextattr(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_remextattr(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +#endif /* AFPD_EXT_ATTRS_H */ diff --git a/etc/afpd/fce_api.c b/etc/afpd/fce_api.c new file mode 100644 index 0000000..158ad60 --- /dev/null +++ b/etc/afpd/fce_api.c @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2010 Mark Williams + * Copyright (c) 2012 Frank Lahm + * + * File change event API for netatalk + * + * for every detected filesystem change a UDP packet is sent to an arbitrary list + * of listeners. Each packet contains unix path of modified filesystem element, + * event reason, and a consecutive event id (32 bit). Technically we are UDP client and are sending + * out packets synchronuosly as they are created by the afp functions. This should not affect + * performance measurably. The only delaying calls occur during initialization, if we have to + * resolve non-IP hostnames to IP. All numeric data inside the packet is network byte order, so use + * ntohs / ntohl to resolve length and event id. Ideally a listener receives every packet with + * no gaps in event ids, starting with event id 1 and mode FCE_CONN_START followed by + * data events from id 2 up to 0xFFFFFFFF, followed by 0 to 0xFFFFFFFF and so on. + * + * A gap or not starting with 1 mode FCE_CONN_START or receiving mode FCE_CONN_BROKEN means that + * the listener has lost at least one filesystem event + * + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fork.h" +#include "file.h" +#include "directory.h" +#include "desktop.h" +#include "volume.h" + +// ONLY USED IN THIS FILE +#include "fce_api_internal.h" + +extern int afprun_bg(int root, char *cmd); + +/* We store our connection data here */ +static struct udp_entry udp_socket_list[FCE_MAX_UDP_SOCKS]; +static int udp_sockets = 0; +static bool udp_initialized = false; +static unsigned long fce_ev_enabled = + (1 << FCE_FILE_MODIFY) | + (1 << FCE_FILE_DELETE) | + (1 << FCE_DIR_DELETE) | + (1 << FCE_FILE_CREATE) | + (1 << FCE_DIR_CREATE) | + (1 << FCE_FILE_MOVE) | + (1 << FCE_DIR_MOVE) | + (1 << FCE_LOGIN) | + (1 << FCE_LOGOUT); + +static uint8_t fce_ev_info; /* flags of additional info to send in events */ + +#define MAXIOBUF 4096 +static unsigned char iobuf[MAXIOBUF]; +static const char **skip_files; +static struct fce_close_event last_close_event; + +/* + * This only initializes consecutive events beginning at 1, high + * numbered events must be initialized in the code + */ +static char *fce_event_names[FCE_LAST_EVENT + 1] = { + "", + "FCE_FILE_MODIFY", + "FCE_FILE_DELETE", + "FCE_DIR_DELETE", + "FCE_FILE_CREATE", + "FCE_DIR_CREATE", + "FCE_FILE_MOVE", + "FCE_DIR_MOVE", + "FCE_LOGIN", + "FCE_LOGOUT" +}; + +/* + * + * Initialize network structs for any listeners + * We dont give return code because all errors are handled internally (I hope..) + * + * */ +void fce_init_udp() +{ + int rv; + struct addrinfo hints, *servinfo, *p; + + if (udp_initialized == true) + return; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + + for (int i = 0; i < udp_sockets; i++) { + struct udp_entry *udp_entry = udp_socket_list + i; + + /* Close any pending sockets */ + if (udp_entry->sock != -1) + close(udp_entry->sock); + + if ((rv = getaddrinfo(udp_entry->addr, udp_entry->port, &hints, &servinfo)) != 0) { + LOG(log_error, logtype_fce, "fce_init_udp: getaddrinfo(%s:%s): %s", + udp_entry->addr, udp_entry->port, gai_strerror(rv)); + continue; + } + + /* loop through all the results and make a socket */ + for (p = servinfo; p != NULL; p = p->ai_next) { + if ((udp_entry->sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + LOG(log_error, logtype_fce, "fce_init_udp: socket(%s:%s): %s", + udp_entry->addr, udp_entry->port, strerror(errno)); + continue; + } + break; + } + + if (p == NULL) { + LOG(log_error, logtype_fce, "fce_init_udp: no socket for %s:%s", + udp_entry->addr, udp_entry->port); + } + udp_entry->addrinfo = *p; + memcpy(&udp_entry->addrinfo, p, sizeof(struct addrinfo)); + memcpy(&udp_entry->sockaddr, p->ai_addr, sizeof(struct sockaddr_storage)); + freeaddrinfo(servinfo); + } + + udp_initialized = true; +} + +void fce_cleanup() +{ + if (udp_initialized == false ) + return; + + for (int i = 0; i < udp_sockets; i++) + { + struct udp_entry *udp_entry = udp_socket_list + i; + + /* Close any pending sockets */ + if (udp_entry->sock != -1) + { + close( udp_entry->sock ); + udp_entry->sock = -1; + } + } + udp_initialized = false; +} + +/* + * Construct a UDP packet for our listeners and return packet size + * */ +static ssize_t build_fce_packet(const AFPObj *obj, + char *iobuf, + fce_ev_t event, + const char *path, + const char *oldpath, + pid_t pid, + const char *user, + uint32_t event_id) +{ + char *p = iobuf; + size_t pathlen; + ssize_t datalen = 0; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + uint8_t packet_info = fce_ev_info; + + /* FCE magic */ + memcpy(p, FCE_PACKET_MAGIC, 8); + p += 8; + datalen += 8; + + /* version */ + *p = FCE_PACKET_VERSION; + p += 1; + datalen += 1; + + /* optional: options */ + if (FCE_PACKET_VERSION > 1) { + if (oldpath) + packet_info |= FCE_EV_INFO_SRCPATH; + *p = packet_info; + p += 1; + datalen += 1; + } + + /* event */ + *p = event; + p += 1; + datalen += 1; + + /* optional: padding */ + if (FCE_PACKET_VERSION > 1) { + p += 1; + datalen += 1; + } + + /* optional: reserved */ + if (FCE_PACKET_VERSION > 1) { + p += 8; + datalen += 8; + } + + /* event ID */ + uint32 = htonl(event_id); + memcpy(p, &uint32, sizeof(uint32)); + p += sizeof(uint32); + datalen += sizeof(uint32); + + /* optional: pid */ + if (packet_info & FCE_EV_INFO_PID) { + uint64 = pid; + uint64 = hton64(uint64); + memcpy(p, &uint64, sizeof(uint64)); + p += sizeof(uint64); + datalen += sizeof(uint64); + } + + /* optional: username */ + if (packet_info & FCE_EV_INFO_USER) { + uint16 = strlen(user); + uint16 = htons(uint16); + memcpy(p, &uint16, sizeof(uint16)); + p += sizeof(uint16); + datalen += sizeof(uint16); + memcpy(p, user, strlen(user)); + p += strlen(user); + datalen += strlen(user); + } + + /* path */ + if ((pathlen = strlen(path)) >= MAXPATHLEN) + pathlen = MAXPATHLEN - 1; + uint16 = pathlen; + uint16 = htons(uint16); + memcpy(p, &uint16, sizeof(uint16)); + p += sizeof(uint16); + datalen += sizeof(uint16); + memcpy(p, path, pathlen); + p += pathlen; + datalen += pathlen; + + /* optional: source path */ + if (packet_info & FCE_EV_INFO_SRCPATH) { + if ((pathlen = strlen(oldpath)) >= MAXPATHLEN) + pathlen = MAXPATHLEN - 1; + uint16 = pathlen; + uint16 = htons(uint16); + memcpy(p, &uint16, sizeof(uint16)); + p += sizeof(uint16); + datalen += sizeof(uint16); + memcpy(p, oldpath, pathlen); + p += pathlen; + datalen += pathlen; + } + + /* return the packet len */ + return datalen; +} + +/* + * Send the fce information to all (connected) listeners + * We dont give return code because all errors are handled internally (I hope..) + * */ +static void send_fce_event(const AFPObj *obj, int event, const char *path, const char *oldpath) +{ + static bool first_event = true; + static uint32_t event_id = 0; /* the unique packet couter to detect packet/data loss. Going from 0xFFFFFFFF to 0x0 is a valid increment */ + static char *user; + time_t now = time(NULL); + ssize_t data_len; + + /* initialized ? */ + if (first_event == true) { + first_event = false; + + fce_event_names[FCE_CONN_START] = "FCE_CONN_START"; + fce_event_names[FCE_CONN_BROKEN] = "FCE_CONN_BROKEN"; + + struct passwd *pwd = getpwuid(obj->uid); + user = strdup(pwd->pw_name); + + switch (obj->fce_version) { + case 1: + /* fce_ev_info unused */ + break; + case 2: + fce_ev_info = FCE_EV_INFO_PID | FCE_EV_INFO_USER; + break; + default: + fce_ev_info = 0; + LOG(log_error, logtype_fce, "Unsupported FCE protocol version %d", obj->fce_version); + break; + } + + fce_init_udp(); + /* Notify listeners the we start from the beginning */ + send_fce_event(obj, FCE_CONN_START, "", NULL); + } + + /* run script */ + if (obj->fce_notify_script) { + static bstring quote = NULL; + static bstring quoterep = NULL; + static bstring slash = NULL; + static bstring slashrep = NULL; + + if (!quote) { + quote = bfromcstr("'"); + quoterep = bfromcstr("'\\''"); + slash = bfromcstr("\\"); + slashrep = bfromcstr("\\\\"); + } + + bstring cmd = bformat("%s -v %d -e %s -i %" PRIu32 "", + obj->fce_notify_script, + FCE_PACKET_VERSION, + fce_event_names[event], + event_id); + + if (path[0]) { + bstring bpath = bfromcstr(path); + bfindreplace(bpath, slash, slashrep, 0); + bfindreplace(bpath, quote, quoterep, 0); + bformata(cmd, " -P '%s'", bdata(bpath)); + bdestroy(bpath); + } + if (fce_ev_info | FCE_EV_INFO_PID) + bformata(cmd, " -p %" PRIu64 "", (uint64_t)getpid()); + if (fce_ev_info | FCE_EV_INFO_USER) + bformata(cmd, " -u %s", user); + if (oldpath) { + bstring boldpath = bfromcstr(oldpath); + bfindreplace(boldpath, slash, slashrep, 0); + bfindreplace(boldpath, quote, quoterep, 0); + bformata(cmd, " -S '%s'", bdata(boldpath)); + bdestroy(boldpath); + } + (void)afprun_bg(1, bdata(cmd)); + bdestroy(cmd); + } + + for (int i = 0; i < udp_sockets; i++) { + int sent_data = 0; + struct udp_entry *udp_entry = udp_socket_list + i; + + /* we had a problem earlier ? */ + if (udp_entry->sock == -1) { + /* We still have to wait ?*/ + if (now < udp_entry->next_try_on_error) + continue; + + /* Reopen socket */ + udp_entry->sock = socket(udp_entry->addrinfo.ai_family, + udp_entry->addrinfo.ai_socktype, + udp_entry->addrinfo.ai_protocol); + + if (udp_entry->sock == -1) { + /* failed again, so go to rest again */ + LOG(log_error, logtype_fce, "Cannot recreate socket for fce UDP connection: errno %d", errno ); + + udp_entry->next_try_on_error = now + FCE_SOCKET_RETRY_DELAY_S; + continue; + } + + udp_entry->next_try_on_error = 0; + + /* Okay, we have a running socket again, send server that we had a problem on our side*/ + data_len = build_fce_packet(obj, iobuf, FCE_CONN_BROKEN, "", NULL, getpid(), user, 0); + + sendto(udp_entry->sock, + iobuf, + data_len, + 0, + (struct sockaddr *)&udp_entry->sockaddr, + udp_entry->addrinfo.ai_addrlen); + } + + /* build our data packet */ + data_len = build_fce_packet(obj, iobuf, event, path, oldpath, getpid(), user, event_id); + + sent_data = sendto(udp_entry->sock, + iobuf, + data_len, + 0, + (struct sockaddr *)&udp_entry->sockaddr, + udp_entry->addrinfo.ai_addrlen); + + /* Problems ? */ + if (sent_data != data_len) { + /* Argh, socket broke, we close and retry later */ + LOG(log_error, logtype_fce, "send_fce_event: error sending packet to %s:%s, transfered %d of %d: %s", + udp_entry->addr, udp_entry->port, sent_data, data_len, strerror(errno)); + + close( udp_entry->sock ); + udp_entry->sock = -1; + udp_entry->next_try_on_error = now + FCE_SOCKET_RETRY_DELAY_S; + } + } + + event_id++; +} + +static int add_udp_socket(const char *target_ip, const char *target_port ) +{ + if (target_port == NULL) + target_port = FCE_DEFAULT_PORT_STRING; + + if (udp_sockets >= FCE_MAX_UDP_SOCKS) { + LOG(log_error, logtype_fce, "Too many file change api UDP connections (max %d allowed)", FCE_MAX_UDP_SOCKS ); + return AFPERR_PARAM; + } + + udp_socket_list[udp_sockets].addr = strdup(target_ip); + udp_socket_list[udp_sockets].port = strdup(target_port); + udp_socket_list[udp_sockets].sock = -1; + memset(&udp_socket_list[udp_sockets].addrinfo, 0, sizeof(struct addrinfo)); + memset(&udp_socket_list[udp_sockets].sockaddr, 0, sizeof(struct sockaddr_storage)); + udp_socket_list[udp_sockets].next_try_on_error = 0; + + udp_sockets++; + + return AFP_OK; +} + +static void save_close_event(const AFPObj *obj, const char *path) +{ + time_t now = time(NULL); + + /* Check if it's a close for the same event as the last one */ + if (last_close_event.time /* is there any saved event ? */ + && (strcmp(path, last_close_event.path) != 0)) { + /* no, so send the saved event out now */ + send_fce_event(obj, FCE_FILE_MODIFY,last_close_event.path, NULL); + } + + LOG(log_debug, logtype_fce, "save_close_event: %s", path); + + last_close_event.time = now; + strncpy(last_close_event.path, path, MAXPATHLEN); +} + +static void fce_init_ign_names(const char *ignores) +{ + int count = 0; + char *names = strdup(ignores); + char *p; + int i = 0; + + while (names[i]) { + count++; + for (; names[i] && names[i] != '/'; i++) + ; + if (!names[i]) + break; + i++; + } + + skip_files = calloc(count + 1, sizeof(char *)); + + for (i = 0, p = strtok(names, "/"); p ; p = strtok(NULL, "/")) + skip_files[i++] = strdup(p); + + free(names); +} + +/* + * + * Dispatcher for all incoming file change events + * + * */ +int fce_register(const AFPObj *obj, fce_ev_t event, const char *path, const char *oldpath) +{ + static bool first_event = true; + const char *bname; + + if (!(fce_ev_enabled & (1 << event))) + return AFP_OK; + + AFP_ASSERT(event >= FCE_FIRST_EVENT && event <= FCE_LAST_EVENT); + AFP_ASSERT(path); + + LOG(log_debug, logtype_fce, "register_fce(path: %s, event: %s)", + path, fce_event_names[event]); + + bname = basename_safe(path); + + if ((udp_sockets == 0) && (obj->fce_notify_script == NULL)) { + /* No listeners configured */ + return AFP_OK; + } + + /* do some initialization on the fly the first time */ + if (first_event) { + fce_initialize_history(); + fce_init_ign_names(obj->fce_ign_names); + first_event = false; + } + + /* handle files which should not cause events (.DS_Store atc. ) */ + for (int i = 0; skip_files[i] != NULL; i++) { + if (strcmp(bname, skip_files[i]) == 0) + return AFP_OK; + } + + /* Can we ignore this event based on type or history? */ + if (fce_handle_coalescation(event, path)) { + LOG(log_debug9, logtype_fce, "Coalesced fc event <%d> for <%s>", event, path); + return AFP_OK; + } + + switch (event) { + case FCE_FILE_MODIFY: + save_close_event(obj, path); + break; + default: + send_fce_event(obj, event, path, oldpath); + break; + } + + return AFP_OK; +} + +static void check_saved_close_events(const AFPObj *obj) +{ + time_t now = time(NULL); + + /* check if configured holdclose time has passed */ + if (last_close_event.time && ((last_close_event.time + obj->options.fce_fmodwait) < now)) { + LOG(log_debug, logtype_fce, "check_saved_close_events: sending event: %s", last_close_event.path); + /* yes, send event */ + send_fce_event(obj, FCE_FILE_MODIFY, &last_close_event.path[0], NULL); + last_close_event.path[0] = 0; + last_close_event.time = 0; + } +} + +/******************** External calls start here **************************/ + +/* + * API-Calls for file change api, called form outside (file.c directory.c ofork.c filedir.c) + * */ +void fce_pending_events(const AFPObj *obj) +{ + if (!udp_sockets) + return; + check_saved_close_events(obj); +} + +/* + * + * Extern connect to afpd parameter, can be called multiple times for multiple listeners (up to MAX_UDP_SOCKS times) + * + * */ +int fce_add_udp_socket(const char *target) +{ + const char *port = FCE_DEFAULT_PORT_STRING; + char target_ip[256] = {""}; + + strncpy(target_ip, target, sizeof(target_ip) -1); + + char *port_delim = strchr( target_ip, ':' ); + if (port_delim) { + *port_delim = 0; + port = port_delim + 1; + } + return add_udp_socket(target_ip, port); +} + +int fce_set_events(const char *events) +{ + char *e; + char *p; + + if (events == NULL) + return AFPERR_PARAM; + + e = strdup(events); + + fce_ev_enabled = 0; + + for (p = strtok(e, ", "); p; p = strtok(NULL, ", ")) { + if (strcmp(p, "fmod") == 0) { + fce_ev_enabled |= (1 << FCE_FILE_MODIFY); + } else if (strcmp(p, "fdel") == 0) { + fce_ev_enabled |= (1 << FCE_FILE_DELETE); + } else if (strcmp(p, "ddel") == 0) { + fce_ev_enabled |= (1 << FCE_DIR_DELETE); + } else if (strcmp(p, "fcre") == 0) { + fce_ev_enabled |= (1 << FCE_FILE_CREATE); + } else if (strcmp(p, "dcre") == 0) { + fce_ev_enabled |= (1 << FCE_DIR_CREATE); + } else if (strcmp(p, "fmov") == 0) { + fce_ev_enabled |= (1 << FCE_FILE_MOVE); + } else if (strcmp(p, "dmov") == 0) { + fce_ev_enabled |= (1 << FCE_DIR_MOVE); + } else if (strcmp(p, "login") == 0) { + fce_ev_enabled |= (1 << FCE_LOGIN); + } else if (strcmp(p, "logout") == 0) { + fce_ev_enabled |= (1 << FCE_LOGOUT); + } + } + + free(e); + + return AFP_OK; +} diff --git a/etc/afpd/fce_api_internal.h b/etc/afpd/fce_api_internal.h new file mode 100644 index 0000000..1c22643 --- /dev/null +++ b/etc/afpd/fce_api_internal.h @@ -0,0 +1,51 @@ +/* + * File: fce_api_internal.h + * Author: mw + * + * Created on 1. Oktober 2010, 23:48 + */ + +#ifndef _FCE_API_INTERNAL_H +#define _FCE_API_INTERNAL_H + +#include + +#include + +#define FCE_MAX_UDP_SOCKS 5 /* Allow a maximum of udp listeners for file change events */ +#define FCE_SOCKET_RETRY_DELAY_S 600 /* Pause this time in s after socket was broken */ +#define FCE_HISTORY_LEN 10 /* This is used to coalesce events */ +#define MAX_COALESCE_TIME_MS 1000 /* Events oldeer than this are not coalesced */ + +#define FCE_COALESCE_CREATE (1 << 0) +#define FCE_COALESCE_DELETE (1 << 1) +#define FCE_COALESCE_ALL (FCE_COALESCE_CREATE | FCE_COALESCE_DELETE) + +struct udp_entry { + int sock; + char *addr; + char *port; + struct addrinfo addrinfo; + struct sockaddr_storage sockaddr; + time_t next_try_on_error; /* In case of error set next timestamp to retry */ +}; + +struct fce_history { + fce_ev_t fce_h_event; + char fce_h_path[MAXPATHLEN + 1]; + struct timeval fce_h_tv; +}; + +struct fce_close_event { + time_t time; + char path[MAXPATHLEN + 1]; +}; + +#define PACKET_HDR_LEN (sizeof(struct fce_packet) - FCE_MAX_PATH_LEN) + +bool fce_handle_coalescation(int event, const char *path); +void fce_initialize_history(); + + +#endif /* _FCE_API_INTERNAL_H */ + diff --git a/etc/afpd/fce_util.c b/etc/afpd/fce_util.c new file mode 100644 index 0000000..8586a40 --- /dev/null +++ b/etc/afpd/fce_util.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2010 Mark Williams + * + * File change event API for netatalk + * + * for every detected filesystem change a UDP packet is sent to an arbitrary list + * of listeners. Each packet contains unix path of modified filesystem element, + * event reason, and a consecutive event id (32 bit). Technically we are UDP client and are sending + * out packets synchronuosly as they are created by the afp functions. This should not affect + * performance measurably. The only delaying calls occur during initialization, if we have to + * resolve non-IP hostnames to IP. All numeric data inside the packet is network byte order, so use + * ntohs / ntohl to resolve length and event id. Ideally a listener receives every packet with + * no gaps in event ids, starting with event id 1 and mode FCE_CONN_START followed by + * data events from id 2 up to 0xFFFFFFFF, followed by 0 to 0xFFFFFFFF and so on. + * + * A gap or not starting with 1 mode FCE_CONN_START or receiving mode FCE_CONN_BROKEN means that + * the listener has lost at least one filesystem event + * + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fork.h" +#include "file.h" +#include "directory.h" +#include "desktop.h" +#include "volume.h" + +// ONLY USED IN THIS FILE +#include "fce_api_internal.h" + +/* We store our connection data here */ +static uint32_t coalesce = 0; +static struct fce_history fce_history_list[FCE_HISTORY_LEN]; + +/**** +* With coalesce we try to reduce the events over UDP, the eventlistener would throw these +* events away anyway. +* This works only, if the connected listener uses the events on a "per directory" base +* It is a very simple aproach, but saves a lot of events sent to listeners. +* Every "child element" event is ignored as long as its parent event is not older +* than MAX_COALESCE_TIME_MS ms. If large directory trees or large files are created or deleted, +* this probably will not work recursive, because the time to copy data will exceed this +* event timeout. +* +****/ + +static long get_ms_difftime ( struct timeval *tv1, struct timeval *tv2 ) +{ + unsigned long s = tv2->tv_sec - tv1->tv_sec; + long us = tv2->tv_usec - tv1->tv_usec; + + return s * 1000 + us/1000; +} + +/****************************************************************************** + * Public functions follow + ******************************************************************************/ + +void fce_initialize_history() +{ + for (int i = 0; i < FCE_HISTORY_LEN; i++) { + memset( &fce_history_list[i], 0, sizeof(fce_history_list[i]) ); + } +} + +bool fce_handle_coalescation(int event, const char *path) +{ + /* These two are used to eval our next index in history */ + /* the history is unsorted, speed should not be a problem, length is 10 */ + unsigned long oldest_entry = (unsigned long )((long)-1); + int oldest_entry_idx = -1; + struct timeval tv; + + if (coalesce == 0) + return false; + + /* After a file creation *ALWAYS* a file modification is produced */ + if ((event == FCE_FILE_CREATE) && (coalesce & FCE_COALESCE_CREATE)) + return true; + + /* get timestamp */ + gettimeofday(&tv, 0); + + /* Now detect events in the very near history */ + for (int i = 0; i < FCE_HISTORY_LEN; i++) { + struct fce_history *fh = &fce_history_list[i]; + + /* Not inited ? */ + if (fh->fce_h_tv.tv_sec == 0) { + /* we can use it for new elements */ + oldest_entry = 0; + oldest_entry_idx = i; + continue; + } + + /* Too old ? */ + if (get_ms_difftime(&fh->fce_h_tv, &tv ) > MAX_COALESCE_TIME_MS) { + /* Invalidate entry */ + fh->fce_h_tv.tv_sec = 0; + oldest_entry = 0; + oldest_entry_idx = i; + continue; + } + + + /* If we find a parent dir wich was created we are done */ + if ((coalesce & FCE_COALESCE_CREATE) && (fh->fce_h_event == FCE_DIR_CREATE)) { + /* Parent dir ? */ + if (!strncmp(fh->fce_h_path, path, strlen(fh->fce_h_path))) + return true; + } + + /* If we find a parent dir we should be DELETED we are done */ + if ((coalesce & FCE_COALESCE_DELETE) + && (event == FCE_FILE_DELETE || event == FCE_DIR_DELETE)) { + /* Parent dir ? */ + if (!strncmp(fh->fce_h_path, path, strlen(fh->fce_h_path))) + return true; + } + + /* Detect oldest entry for next new entry */ + if (oldest_entry_idx == -1 || fh->fce_h_tv.tv_sec < oldest_entry) { + oldest_entry = fh->fce_h_tv.tv_sec; + oldest_entry_idx = i; + } + } + + /* We have a new entry for the history, register it */ + fce_history_list[oldest_entry_idx].fce_h_tv = tv; + fce_history_list[oldest_entry_idx].fce_h_event = event; + strncpy(fce_history_list[oldest_entry_idx].fce_h_path, path, MAXPATHLEN); + + /* we have to handle this event */ + return false; +} + +/* + * Set event coalescation to reduce number of events sent over UDP + * all|delete|create + */ + +int fce_set_coalesce(const char *opt) +{ + char *e; + char *p; + + if (opt == NULL) + return AFPERR_PARAM; + + e = strdup(opt); + + for (p = strtok(e, ","); p; p = strtok(NULL, ",")) { + if (strcmp(p, "all") == 0) { + coalesce = FCE_COALESCE_ALL; + } else if (strcmp(p, "delete") == 0) { + coalesce = FCE_COALESCE_DELETE; + } else if (strcmp(p, "create") == 0) { + coalesce = FCE_COALESCE_CREATE; + } + } + + free(e); + + return AFP_OK; +} + + + + diff --git a/etc/afpd/file.c b/etc/afpd/file.c new file mode 100644 index 0000000..6d5cb4f --- /dev/null +++ b/etc/afpd/file.c @@ -0,0 +1,2322 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "directory.h" +#include "dircache.h" +#include "desktop.h" +#include "volume.h" +#include "fork.h" +#include "file.h" +#include "filedir.h" +#include "unix.h" + +/* the format for the finderinfo fields (from IM: Toolbox Essentials): + * field bytes subfield bytes + * + * files: + * ioFlFndrInfo 16 -> type 4 type field + * creator 4 creator field + * flags 2 finder flags: + * alias, bundle, etc. + * location 4 location in window + * folder 2 window that contains file + * + * ioFlXFndrInfo 16 -> iconID 2 icon id + * unused 6 reserved + * script 1 script system + * xflags 1 reserved + * commentID 2 comment id + * putawayID 4 home directory id + */ + +const u_char ufinderi[ADEDLEN_FINDERI] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + +static const u_char old_ufinderi[] = { + 'T', 'E', 'X', 'T', 'U', 'N', 'I', 'X' + }; + +/* ---------------------- +*/ +static int default_type(void *finder) +{ + if (!memcmp(finder, ufinderi, 8) || !memcmp(finder, old_ufinderi, 8)) + return 1; + return 0; +} + +/* FIXME path : unix or mac name ? (for now it's unix name ) */ +void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data, int islink) +{ + struct extmap *em; + void *ad_finder = NULL; + int chk_ext = 0; + + if (adp) + ad_finder = ad_entry(adp, ADEID_FINDERI); + + if (ad_finder) { + memcpy(data, ad_finder, ADEDLEN_FINDERI); + /* default type ? */ + if (default_type(ad_finder)) + chk_ext = 1; + } + else { + memcpy(data, ufinderi, ADEDLEN_FINDERI); + chk_ext = 1; + if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */ + uint16_t ashort; + + ashort = htons(FINDERINFO_INVISIBLE); + memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort)); + } + } + + if (islink && !vol_syml_opt(vol)) { + uint16_t linkflag; + memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2); + linkflag |= htons(FINDERINFO_ISALIAS); + memcpy((char *)data + FINDERINFO_FRFLAGOFF, &linkflag, 2); + memcpy((char *)data + FINDERINFO_FRTYPEOFF,"slnk",4); + memcpy((char *)data + FINDERINFO_FRCREATOFF,"rhap",4); + } + + /** Only enter if no appledouble information and no finder information found. */ + if (chk_ext && (em = getextmap( upath ))) { + memcpy(data, em->em_type, sizeof( em->em_type )); + memcpy((char *)data + 4, em->em_creator, sizeof(em->em_creator)); + } + + return data; +} + +/* --------------------- +*/ +char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, uint32_t utf8) +{ + uint32_t aint; + char *tp = NULL; + char *src = name; + aint = strlen( name ); + + if (!utf8) { + /* want mac name */ + if (utf8_encoding(vol->v_obj)) { + /* but name is an utf8 mac name */ + char *u, *m; + + /* global static variable... */ + tp = strdup(name); + if (!(u = mtoupath(vol, name, pid, 1)) || !(m = utompath(vol, u, id, 0))) { + aint = 0; + } + else { + aint = strlen(m); + src = m; + } + + } + if (aint > MACFILELEN) + aint = MACFILELEN; + *data++ = aint; + } + else { + uint16_t temp; + + if (aint > UTF8FILELEN_EARLY) /* FIXME safeguard, anyway if no ascii char it's game over*/ + aint = UTF8FILELEN_EARLY; + + utf8 = vol->v_kTextEncoding; + memcpy(data, &utf8, sizeof(utf8)); + data += sizeof(utf8); + + temp = htons(aint); + memcpy(data, &temp, sizeof(temp)); + data += sizeof(temp); + } + + memcpy( data, src, aint ); + data += aint; + if (tp) { + strcpy(name, tp); + free(tp); + } + return data; +} + +/* + * FIXME: PDINFO is UTF8 and doesn't need adp +*/ +#define PARAM_NEED_ADP(b) ((b) & ((1 << FILPBIT_ATTR) |\ + (1 << FILPBIT_CDATE) |\ + (1 << FILPBIT_MDATE) |\ + (1 << FILPBIT_BDATE) |\ + (1 << FILPBIT_FINFO) |\ + (1 << FILPBIT_RFLEN) |\ + (1 << FILPBIT_EXTRFLEN) |\ + (1 << FILPBIT_PDINFO) |\ + (1 << FILPBIT_FNUM) |\ + (1 << FILPBIT_UNIXPR))) + +/*! + * @brief Get CNID for did/upath args both from database and adouble file + * + * 1. Get the objects CNID as stored in its adouble file + * 2. Get the objects CNID from the database + * 3. If there's a problem with a "dbd" database, fallback to "tdb" in memory + * 4. In case 2 and 3 differ, store 3 in the adouble file + * + * @param vol (rw) volume + * @param adp (rw) adouble struct of object upath, might be NULL + * @param st (r) stat of upath, must NOT be NULL + * @param did (r) parent CNID of upath + * @param upath (r) name of object + * @param len (r) strlen of upath + */ +uint32_t get_id(struct vol *vol, + struct adouble *adp, + const struct stat *st, + const cnid_t did, + const char *upath, + const int len) +{ + static int first = 1; /* mark if this func is called the first time */ + uint32_t adcnid; + uint32_t dbcnid = CNID_INVALID; + +restart: + if (vol->v_cdb != NULL) { + /* prime aint with what we think is the cnid, set did to zero for + catching moved files */ + adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp); /* (1) */ + + AFP_CNID_START("cnid_add"); + dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid); /* (2) */ + AFP_CNID_DONE(); + + /* Throw errors if cnid_add fails. */ + if (dbcnid == CNID_INVALID) { + switch (errno) { + case CNID_ERR_CLOSE: /* the db is closed */ + break; + case CNID_ERR_PARAM: + LOG(log_error, logtype_afpd, "get_id: Incorrect parameters passed to cnid_add"); + afp_errno = AFPERR_PARAM; + goto exit; + case CNID_ERR_PATH: + afp_errno = AFPERR_PARAM; + goto exit; + default: + /* Close CNID backend if "dbd" and switch to temp in-memory "tdb" */ + /* we have to do it here for "dbd" because it uses "lazy opening" */ + /* In order to not end in a loop somehow with goto restart below */ + /* */ + if (first && (strcmp(vol->v_cnidscheme, "dbd") == 0)) { /* (3) */ + cnid_close(vol->v_cdb); + free(vol->v_cnidscheme); + vol->v_cnidscheme = strdup("tdb"); + + int flags = CNID_FLAG_MEMORY; + if ((vol->v_flags & AFPVOL_NODEV)) { + flags |= CNID_FLAG_NODEV; + } + LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", + vol->v_path); + vol->v_cdb = cnid_open(vol, "tdb", flags); + if (vol->v_cdb) { + if (!(vol->v_flags & AFPVOL_TM)) { + vol->v_flags |= AFPVOL_RO; + setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead." + "Check server messages for details. Switching to read-only mode."); + kill(getpid(), SIGUSR2); + } + goto restart; /* now try again with the temp CNID db */ + } else { + setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB failed too!" + "Check server messages for details, can't recover from this state!"); + } + } + afp_errno = AFPERR_MISC; + goto exit; + } + } + else if (adp && adcnid && (adcnid != dbcnid)) { /* 4 */ + /* Update the ressource fork. For a folder adp is always null */ + LOG(log_debug, logtype_afpd, "get_id(%s/%s): calling ad_setid(old: %u, new: %u)", + getcwdpath(), upath, htonl(adcnid), htonl(dbcnid)); + if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) { + if (ad_flush(adp) != 0) + LOG(log_error, logtype_afpd, "get_id(\"%s\"): can't flush", fullpathname(upath)); + } + } + } + +exit: + first = 0; + return dbcnid; +} + +/* -------------------------- */ +int getmetadata(const AFPObj *obj, + struct vol *vol, + uint16_t bitmap, + struct path *path, struct dir *dir, + char *buf, size_t *buflen, struct adouble *adp) +{ + char *data, *l_nameoff = NULL, *upath; + char *utf_nameoff = NULL; + int bit = 0; + uint32_t aint; + cnid_t id = 0; + uint16_t ashort; + u_char achar, fdType[4]; + uint32_t utf8 = 0; + struct stat *st; + struct maccess ma; + + LOG(log_debug, logtype_afpd, "getmetadata(\"%s\")", path->u_name); + + upath = path->u_name; + st = &path->st; + data = buf; + + if ( ((bitmap & ( (1 << FILPBIT_FINFO)|(1 << FILPBIT_LNAME)|(1 <m_name) + || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding(obj)) /* FIXME should be m_name utf8 filename */ + || (bitmap & (1 << FILPBIT_FNUM))) { + if (!path->id) { + bstring fullpath; + struct dir *cachedfile; + int len = strlen(upath); + if ((cachedfile = dircache_search_by_name(vol, dir, upath, len)) != NULL) + id = cachedfile->d_did; + else { + id = get_id(vol, adp, st, dir->d_did, upath, len); + + /* Add it to the cache */ + LOG(log_debug, logtype_afpd, "getmetadata: caching: did:%u, \"%s\", cnid:%u", + ntohl(dir->d_did), upath, ntohl(id)); + + /* Get macname from unixname first */ + if (path->m_name == NULL) { + if ((path->m_name = utompath(vol, upath, id, utf8_encoding(obj))) == NULL) { + LOG(log_error, logtype_afpd, "getmetadata: utompath error"); + return AFPERR_MISC; + } + } + + /* Build fullpath */ + if (((fullpath = bstrcpy(dir->d_fullpath)) == NULL) + || (bconchar(fullpath, '/') != BSTR_OK) + || (bcatcstr(fullpath, upath)) != BSTR_OK) { + LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno)); + bdestroy(fullpath); + return AFPERR_MISC; + } + + if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, fullpath, st)) == NULL) { + LOG(log_error, logtype_afpd, "getmetadata: error from dir_new"); + return AFPERR_MISC; + } + + if ((dircache_add(vol, cachedfile)) != 0) { + LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error"); + return AFPERR_MISC; + } + } + } else { + id = path->id; + } + + if (id == CNID_INVALID) + return afp_errno; + + if (!path->m_name) { + path->m_name = utompath(vol, upath, id, utf8_encoding(vol->v_obj)); + } + } + while ( bitmap != 0 ) { + while (( bitmap & 1 ) == 0 ) { + bitmap = bitmap>>1; + bit++; + } + + switch ( bit ) { + case FILPBIT_ATTR : + if ( adp ) { + ad_getattr(adp, &ashort); + } else if (vol_inv_dots(vol) && *upath == '.') { + ashort = htons(ATTRBIT_INVISIBLE); + } else + ashort = 0; + ashort &= ~htons(vol->v_ignattr); +#if 0 + /* FIXME do we want a visual clue if the file is read only + */ + struct maccess ma; + accessmode(vol, ".", &ma, dir , NULL); + if ((ma.ma_user & AR_UWRITE)) { + accessmode(vol, upath, &ma, dir , st); + if (!(ma.ma_user & AR_UWRITE)) { + ashort |= htons(ATTRBIT_NOWRITE); + } + } +#endif + memcpy(data, &ashort, sizeof( ashort )); + data += sizeof( ashort ); + LOG(log_debug, logtype_afpd, "metadata('%s'): AFP Attributes: %04x", + path->u_name, ntohs(ashort)); + break; + + case FILPBIT_PDID : + memcpy(data, &dir->d_did, sizeof( uint32_t )); + data += sizeof( uint32_t ); + LOG(log_debug, logtype_afpd, "metadata('%s'): Parent DID: %u", + path->u_name, ntohl(dir->d_did)); + break; + + case FILPBIT_CDATE : + if (!adp || (ad_getdate(adp, AD_DATE_CREATE, &aint) < 0)) + aint = AD_DATE_FROM_UNIX(st->st_mtime); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case FILPBIT_MDATE : + if ( adp && (ad_getdate(adp, AD_DATE_MODIFY, &aint) == 0)) { + if ((st->st_mtime > AD_DATE_TO_UNIX(aint))) { + aint = AD_DATE_FROM_UNIX(st->st_mtime); + } + } else { + aint = AD_DATE_FROM_UNIX(st->st_mtime); + } + memcpy(data, &aint, sizeof( int )); + data += sizeof( int ); + break; + + case FILPBIT_BDATE : + if (!adp || (ad_getdate(adp, AD_DATE_BACKUP, &aint) < 0)) + aint = AD_DATE_START; + memcpy(data, &aint, sizeof( int )); + data += sizeof( int ); + break; + + case FILPBIT_FINFO : + get_finderinfo(vol, upath, adp, (char *)data,S_ISLNK(st->st_mode)); + data += ADEDLEN_FINDERI; + break; + + case FILPBIT_LNAME : + l_nameoff = data; + data += sizeof( uint16_t ); + break; + + case FILPBIT_SNAME : + memset(data, 0, sizeof(uint16_t)); + data += sizeof( uint16_t ); + break; + + case FILPBIT_FNUM : + memcpy(data, &id, sizeof( id )); + data += sizeof( id ); + LOG(log_debug, logtype_afpd, "metadata('%s'): CNID: %u", + path->u_name, ntohl(id)); + break; + + case FILPBIT_DFLEN : + if (st->st_size > 0xffffffff) + aint = 0xffffffff; + else + aint = htonl( st->st_size ); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case FILPBIT_RFLEN: { + off_t rlen; + if (adp) { + if (adp->ad_rlen > 0xffffffff) + aint = 0xffffffff; + else + aint = htonl( adp->ad_rlen); + } else { + rlen = ad_reso_size(path->u_name, 0, NULL); + if (rlen > 0xffffffff) + rlen = 0xffffffff; + aint = htonl(rlen); + } + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + } + + /* Current client needs ProDOS info block for this file. + Use simple heuristic and let the Mac "type" string tell + us what the PD file code should be. Everything gets a + subtype of 0x0000 unless the original value was hashed + to "pXYZ" when we created it. See IA, Ver 2. + */ + case FILPBIT_PDINFO : + if (obj->afp_version >= 30) { /* UTF8 name */ + utf8 = kTextEncodingUTF8; + utf_nameoff = data; + data += sizeof( uint16_t ); + aint = 0; + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + } + else { + if ( adp ) { + memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 ); + + if ( memcmp( fdType, "TEXT", 4 ) == 0 ) { + achar = '\x04'; + ashort = 0x0000; + } + else if ( memcmp( fdType, "PSYS", 4 ) == 0 ) { + achar = '\xff'; + ashort = 0x0000; + } + else if ( memcmp( fdType, "PS16", 4 ) == 0 ) { + achar = '\xb3'; + ashort = 0x0000; + } + else if ( memcmp( fdType, "BINA", 4 ) == 0 ) { + achar = '\x00'; + ashort = 0x0000; + } + else if ( fdType[0] == 'p' ) { + achar = fdType[1]; + ashort = (fdType[2] * 256) + fdType[3]; + } + else { + achar = '\x00'; + ashort = 0x0000; + } + } + else { + achar = '\x00'; + ashort = 0x0000; + } + + *data++ = achar; + *data++ = 0; + memcpy(data, &ashort, sizeof( ashort )); + data += sizeof( ashort ); + memset(data, 0, sizeof( ashort )); + data += sizeof( ashort ); + } + break; + case FILPBIT_EXTDFLEN: + aint = htonl(st->st_size >> 32); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + aint = htonl(st->st_size); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + case FILPBIT_EXTRFLEN: + if (adp) { + aint = htonl(adp->ad_rlen >> 32); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + aint = htonl(adp->ad_rlen); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + } else { + int64_t rlen = hton64(ad_reso_size(path->u_name, 0, NULL)); + memcpy(data, &rlen, sizeof(rlen)); + data += sizeof(rlen); + } + break; + case FILPBIT_UNIXPR : + /* accessmode may change st_mode with ACLs */ + accessmode(obj, vol, upath, &ma, dir , st); + + aint = htonl(st->st_uid); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + aint = htonl(st->st_gid); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + + /* FIXME: ugly hack + type == slnk indicates an OSX style symlink, + we have to add S_IFLNK to the mode, otherwise + 10.3 clients freak out. */ + + aint = st->st_mode; + if (adp) { + memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 ); + if ( memcmp( fdType, "slnk", 4 ) == 0 ) { + aint |= S_IFLNK; + } + } + aint = htonl(aint); + + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); + + *data++ = ma.ma_user; + *data++ = ma.ma_world; + *data++ = ma.ma_group; + *data++ = ma.ma_owner; + break; + + default : + return( AFPERR_BITMAP ); + } + bitmap = bitmap>>1; + bit++; + } + if ( l_nameoff ) { + ashort = htons( data - buf ); + memcpy(l_nameoff, &ashort, sizeof( ashort )); + data = set_name(vol, data, dir->d_did, path->m_name, id, 0); + } + if ( utf_nameoff ) { + ashort = htons( data - buf ); + memcpy(utf_nameoff, &ashort, sizeof( ashort )); + data = set_name(vol, data, dir->d_did, path->m_name, id, utf8); + } + *buflen = data - buf; + return (AFP_OK); +} + +/* ----------------------- */ +int getfilparams(const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct path *path, + struct dir *dir, char *buf, size_t *buflen, int in_enumerate) +{ + struct adouble ad, *adp; + int opened = 0; + int rc; + int flags; /* uninitialized ok */ + + LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name); + + opened = PARAM_NEED_ADP(bitmap); + adp = NULL; + + if (opened) { + char *upath; + /* + * Dont check for and resturn open fork attributes when enumerating + * This saves a lot of syscalls, the client will hopefully only use the result + * in FPGetFileParms where we return the correct value + */ + flags = (!in_enumerate &&(bitmap & (1 << FILPBIT_ATTR))) ? ADFLAGS_CHECK_OF : 0; + + adp = of_ad(vol, path, &ad); + upath = path->u_name; + + if ( ad_metadata( upath, flags, adp) < 0 ) { + switch (errno) { + case EACCES: + LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?", + upath, strerror(errno)); + return AFPERR_ACCESS; + case EIO: + LOG(log_error, logtype_afpd, "getfilparams(%s): bad resource fork", upath); + /* fall through */ + case ENOENT: + default: + adp = NULL; + break; + } + } + } + rc = getmetadata(obj, vol, bitmap, path, dir, buf, buflen, adp); + + if (opened) + ad_close(adp, ADFLAGS_HF | flags); + + return( rc ); +} + +/* ----------------------------- */ +int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct adouble ad; + struct vol *vol; + struct dir *dir; + struct ofork *of = NULL; + char *path, *upath; + int creatf, did, openf, retvalue = AFP_OK; + uint16_t vid; + struct path *s_path; + + *rbuflen = 0; + ibuf++; + creatf = (unsigned char) *ibuf++; + + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + + if (NULL == ( vol = getvolbyvid( vid )) ) + return( AFPERR_PARAM ); + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy(&did, ibuf, sizeof( did)); + ibuf += sizeof( did ); + + if (NULL == ( dir = dirlookup( vol, did )) ) + return afp_errno; + + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) + return get_afp_errno(AFPERR_PARAM); + if ( *s_path->m_name == '\0' ) + return( AFPERR_BADTYPE ); + + upath = s_path->u_name; + ad_init(&ad, vol); + + /* if upath is deleted we already in trouble anyway */ + if ((of = of_findname(vol, s_path))) { + if (creatf) + return AFPERR_BUSY; + else + return AFPERR_EXIST; + } + + if (creatf) + openf = ADFLAGS_RDWR | ADFLAGS_CREATE | ADFLAGS_TRUNC; + else + /* on a soft create, if the file is open then ad_open won't fail + because open syscall is not called */ + openf = ADFLAGS_RDWR | ADFLAGS_CREATE | ADFLAGS_EXCL; + + if (ad_open(&ad, upath, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | openf, 0666) < 0) { + switch ( errno ) { + case EROFS: + return AFPERR_VLOCK; + case ENOENT : /* we were already in 'did folder' so chdir() didn't fail */ + return ( AFPERR_NOOBJ ); + case EEXIST : + return( AFPERR_EXIST ); + case EACCES : + return( AFPERR_ACCESS ); + case EDQUOT: + case ENOSPC : + LOG(log_info, logtype_afpd, "afp_createfile: DISK FULL"); + return( AFPERR_DFULL ); + default : + return( AFPERR_PARAM ); + } + } + if ( ad_meta_fileno( &ad ) == -1 ) { /* Hard META / HF */ + /* FIXME with hard create on an existing file, we already + * corrupted the data file. + */ + netatalk_unlink( upath ); + ad_close( &ad, ADFLAGS_DF ); + return AFPERR_ACCESS; + } + + path = s_path->m_name; + ad_setname(&ad, path); + + struct stat st; + if (lstat(upath, &st) != 0) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): stat: %s", + upath, strerror(errno)); + ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF); + return AFPERR_MISC; + } + + cnid_t id; + if ((id = get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath))) == CNID_INVALID) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath); + goto createfile_iderr; + } + (void)ad_setid(&ad, st.st_dev, st.st_ino, id, dir->d_did, vol->v_stamp); + +createfile_iderr: + ad_flush(&ad); + ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF ); + fce_register(obj, FCE_FILE_CREATE, fullpathname(upath), NULL); + + curdir->d_offcnt++; + setvoltime(obj, vol ); + + return (retvalue); +} + +int afp_setfilparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + struct path *s_path; + int did, rc; + uint16_t vid, bitmap; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy(&did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; /* was AFPERR_NOOBJ */ + } + + memcpy(&bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_PARAM); + } + + if (path_isadir(s_path)) { + return( AFPERR_BADTYPE ); /* it's a directory */ + } + + if ( s_path->st_errno != 0 ) { + return( AFPERR_NOOBJ ); + } + + if ((u_long)ibuf & 1 ) { + ibuf++; + } + + if (AFP_OK == ( rc = setfilparams(obj, vol, s_path, bitmap, ibuf )) ) { + setvoltime(obj, vol ); + } + + return( rc ); +} + +/* + * cf AFP3.0.pdf page 252 for change_mdate and change_parent_mdate logic + * +*/ +extern struct path Cur_Path; + +int setfilparams(const AFPObj *obj, struct vol *vol, + struct path *path, uint16_t f_bitmap, char *buf ) +{ + struct adouble ad, *adp; + struct extmap *em; + int bit, isad = 1, err = AFP_OK; + char *upath; + u_char achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */ + uint16_t ashort, bshort, oshort; + uint32_t aint; + uint32_t upriv; + uint16_t upriv_bit = 0; + struct utimbuf ut; + int change_mdate = 0; + int change_parent_mdate = 0; + int newdate = 0; + struct timeval tv; + uid_t f_uid; + gid_t f_gid; + uint16_t bitmap = f_bitmap; + uint32_t cdate,bdate; + u_char finder_buf[32]; + int symlinked = S_ISLNK(path->st.st_mode); + int fp; + ssize_t len; + char symbuf[MAXPATHLEN+1]; + +#ifdef DEBUG + LOG(log_debug9, logtype_afpd, "begin setfilparams:"); +#endif /* DEBUG */ + + adp = of_ad(vol, path, &ad); + upath = path->u_name; + + if (!vol_unix_priv(vol) && check_access(obj, vol, upath, OPENACC_WR ) < 0) { + return AFPERR_ACCESS; + } + + /* with unix priv maybe we have to change adouble file priv first */ + bit = 0; + while ( bitmap != 0 ) { + while (( bitmap & 1 ) == 0 ) { + bitmap = bitmap>>1; + bit++; + } + switch( bit ) { + case FILPBIT_ATTR : + change_mdate = 1; + memcpy(&ashort, buf, sizeof( ashort )); + buf += sizeof( ashort ); + break; + case FILPBIT_CDATE : + change_mdate = 1; + memcpy(&cdate, buf, sizeof(cdate)); + buf += sizeof( cdate ); + break; + case FILPBIT_MDATE : + memcpy(&newdate, buf, sizeof( newdate )); + buf += sizeof( newdate ); + break; + case FILPBIT_BDATE : + change_mdate = 1; + memcpy(&bdate, buf, sizeof( bdate)); + buf += sizeof( bdate ); + break; + case FILPBIT_FINFO : + change_mdate = 1; + if (memcmp(buf,"slnkrhap",8) == 0 + && !(S_ISLNK(path->st.st_mode)) + && !(vol->v_flags & AFPVOL_FOLLOWSYM)) { + /* request to turn this into a symlink */ + if ((fp = open(path->u_name, O_RDONLY)) == -1) { + err = AFPERR_MISC; + goto setfilparam_done; + } + len = read(fp, symbuf, MAXPATHLEN); + close(fp); + if (!(len > 0)) { + err = AFPERR_MISC; + goto setfilparam_done; + } + if (unlink(path->u_name) != 0) { + err = AFPERR_MISC; + goto setfilparam_done; + } + symbuf[len] = 0; + if (symlink(symbuf, path->u_name) != 0) { + err = AFPERR_MISC; + goto setfilparam_done; + } + of_stat(vol, path); + symlinked = 1; + } + memcpy(finder_buf, buf, 32 ); + buf += 32; + break; + case FILPBIT_UNIXPR : + if (!vol_unix_priv(vol)) { + /* this volume doesn't use unix priv */ + err = AFPERR_BITMAP; + bitmap = 0; + break; + } + change_mdate = 1; + change_parent_mdate = 1; + + memcpy( &aint, buf, sizeof( aint )); + f_uid = ntohl (aint); + buf += sizeof( aint ); + memcpy( &aint, buf, sizeof( aint )); + f_gid = ntohl (aint); + buf += sizeof( aint ); + setfilowner(vol, f_uid, f_gid, path); + + memcpy( &upriv, buf, sizeof( upriv )); + buf += sizeof( upriv ); + upriv = ntohl (upriv); + if ((upriv & S_IWUSR)) { + setfilunixmode(vol, path, upriv); + } + else { + /* do it later */ + upriv_bit = 1; + } + break; + case FILPBIT_PDINFO : + if (obj->afp_version < 30) { /* else it's UTF8 name */ + achar = *buf; + buf += 2; + /* Keep special case to support crlf translations */ + if ((unsigned int) achar == 0x04) { + fdType = (u_char *)"TEXT"; + buf += 2; + } else { + xyy[0] = ( u_char ) 'p'; + xyy[1] = achar; + xyy[3] = *buf++; + xyy[2] = *buf++; + fdType = xyy; + } + break; + } + /* fallthrough */ + default : + err = AFPERR_BITMAP; + /* break while loop */ + bitmap = 0; + break; + } + + bitmap = bitmap>>1; + bit++; + } + + /* second try with adouble open + */ + if (ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) < 0) { + LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error"); + /* + * For some things, we don't need an adouble header: + * - change of modification date + * - UNIX privs (Bug-ID #2863424) + */ + if (!symlinked && f_bitmap & ~(1<m_name); + cnid_t id; + if ((id = get_id(vol, adp, &path->st, curdir->d_did, upath, strlen(upath))) == CNID_INVALID) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath); + return AFPERR_MISC; + } + (void)ad_setid(adp, path->st.st_dev, path->st.st_ino, id, curdir->d_did, vol->v_stamp); + } + + bit = 0; + bitmap = f_bitmap; + while ( bitmap != 0 ) { + while (( bitmap & 1 ) == 0 ) { + bitmap = bitmap>>1; + bit++; + } + + switch( bit ) { + case FILPBIT_ATTR : + ad_getattr(adp, &bshort); + oshort = bshort; + if ( ntohs( ashort ) & ATTRBIT_SETCLR ) { + ashort &= ~htons(vol->v_ignattr); + bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR ); + } else { + bshort &= ~ashort; + } + if ((bshort & htons(ATTRBIT_INVISIBLE)) != (oshort & htons(ATTRBIT_INVISIBLE))) + change_parent_mdate = 1; + ad_setattr(adp, bshort); + break; + case FILPBIT_CDATE : + ad_setdate(adp, AD_DATE_CREATE, cdate); + break; + case FILPBIT_MDATE : + break; + case FILPBIT_BDATE : + ad_setdate(adp, AD_DATE_BACKUP, bdate); + break; + case FILPBIT_FINFO : + if (default_type( ad_entry( adp, ADEID_FINDERI )) + && ( + ((em = getextmap( path->m_name )) && + !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) && + !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator))) + || ((em = getdefextmap()) && + !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) && + !memcmp(finder_buf + 4, em->em_creator,sizeof( em->em_creator))) + )) { + memcpy(finder_buf, ufinderi, 8 ); + } + memcpy(ad_entry( adp, ADEID_FINDERI ), finder_buf, 32 ); + break; + case FILPBIT_UNIXPR : + if (upriv_bit) { + setfilunixmode(vol, path, upriv); + } + break; + case FILPBIT_PDINFO : + if (obj->afp_version < 30) { /* else it's UTF8 name */ + memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 ); + memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 ); + break; + } + /* fallthrough */ + default : + err = AFPERR_BITMAP; + goto setfilparam_done; + } + bitmap = bitmap>>1; + bit++; + } + +setfilparam_done: + if (change_mdate && newdate == 0 && gettimeofday(&tv, NULL) == 0) { + newdate = AD_DATE_FROM_UNIX(tv.tv_sec); + } + if (newdate) { + if (isad) + ad_setdate(adp, AD_DATE_MODIFY, newdate); + ut.actime = ut.modtime = AD_DATE_TO_UNIX(newdate); + utime(upath, &ut); + } + + if (isad) { + ad_flush(adp); + ad_close(adp, ADFLAGS_HF); + } + + if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) { + newdate = AD_DATE_FROM_UNIX(tv.tv_sec); + bitmap = 1< dst[\"%s\"]", sdir_fd, src, dst); + + if ( unix_rename( sdir_fd, src, -1, dst ) < 0 ) { + switch ( errno ) { + case ENOENT : + return( AFPERR_NOOBJ ); + case EPERM: + case EACCES : + return( AFPERR_ACCESS ); + case EROFS: + return AFPERR_VLOCK; + case EXDEV : /* Cross device move -- try copy */ + /* NOTE: with open file it's an error because after the copy we will + * get two files, it's fixable for our process (eg reopen the new file, get the + * locks, and so on. But it doesn't solve the case with a second process + */ + if (adp->ad_open_forks) { + /* FIXME warning in syslog so admin'd know there's a conflict ?*/ + return AFPERR_OLOCK; /* little lie */ + } + if (AFP_OK != ( rc = copyfile(vol, vol, ddir, sdir_fd, src, dst, newname, NULL )) ) { + /* on error copyfile delete dest */ + return( rc ); + } + return deletefile(vol, sdir_fd, src, 0); + default : + return( AFPERR_PARAM ); + } + } + + if (vol->vfs->vfs_renamefile(vol, sdir_fd, src, dst) < 0 ) { + int err; + + err = errno; + /* try to undo the data fork rename, + * we know we are on the same device + */ + if (err) { + unix_rename(-1, dst, sdir_fd, src ); + /* return the first error */ + switch ( err) { + case ENOENT : + return AFPERR_NOOBJ; + case EPERM: + case EACCES : + return AFPERR_ACCESS ; + case EROFS: + return AFPERR_VLOCK; + default : + return AFPERR_PARAM ; + } + } + } + + /* don't care if we can't open the newly renamed ressource fork */ + if (ad_open(adp, dst, ADFLAGS_HF | ADFLAGS_RDWR) == 0) { + ad_setname(adp, newname); + ad_flush( adp ); + ad_close( adp, ADFLAGS_HF ); + } + + return( AFP_OK ); +} + +/* ---------------- + convert a Mac long name to an utf8 name, +*/ +size_t mtoUTF8(const struct vol *vol, const char *src, size_t srclen, char *dest, size_t destlen) +{ +size_t outlen; + + if ((size_t)-1 == (outlen = convert_string ( vol->v_maccharset, CH_UTF8_MAC, src, srclen, dest, destlen)) ) { + return -1; + } + return outlen; +} + +/* ---------------- */ +int copy_path_name(const struct vol *vol, char *newname, char *ibuf) +{ +char type = *ibuf; +size_t plen = 0; +uint16_t len16; +uint32_t hint; + + if ( type != 2 && !(vol->v_obj->afp_version >= 30 && type == 3) ) { + return -1; + } + ibuf++; + switch (type) { + case 2: + if (( plen = (unsigned char)*ibuf++ ) != 0 ) { + if (vol->v_obj->afp_version >= 30) { + /* convert it to UTF8 + */ + if ((plen = mtoUTF8(vol, ibuf, plen, newname, AFPOBJ_TMPSIZ)) == (size_t)-1) + return -1; + } + else { + strncpy( newname, ibuf, plen ); + newname[ plen ] = '\0'; + } + if (strlen(newname) != plen) { + /* there's \0 in newname, e.g. it's a pathname not + * only a filename. + */ + return -1; + } + } + break; + case 3: + memcpy(&hint, ibuf, sizeof(hint)); + ibuf += sizeof(hint); + + memcpy(&len16, ibuf, sizeof(len16)); + ibuf += sizeof(len16); + plen = ntohs(len16); + + if (plen) { + if (plen > AFPOBJ_TMPSIZ) { + return -1; + } + strncpy( newname, ibuf, plen ); + newname[ plen ] = '\0'; + if (strlen(newname) != plen) { + return -1; + } + } + break; + } + return plen; +} + +/* ----------------------------------- +*/ +int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *s_vol, *d_vol; + struct dir *dir; + char *newname, *p, *upath; + struct path *s_path; + uint32_t sdid, ddid; + int err, retvalue = AFP_OK; + uint16_t svid, dvid; + + struct adouble ad, *adp; + int denyreadset; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&svid, ibuf, sizeof( svid )); + ibuf += sizeof( svid ); + if (NULL == ( s_vol = getvolbyvid( svid )) ) { + return( AFPERR_PARAM ); + } + + memcpy(&sdid, ibuf, sizeof( sdid )); + ibuf += sizeof( sdid ); + if (NULL == ( dir = dirlookup( s_vol, sdid )) ) { + return afp_errno; + } + + memcpy(&dvid, ibuf, sizeof( dvid )); + ibuf += sizeof( dvid ); + memcpy(&ddid, ibuf, sizeof( ddid )); + ibuf += sizeof( ddid ); + + if (NULL == ( s_path = cname( s_vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_PARAM); + } + if ( path_isadir(s_path) ) { + return( AFPERR_BADTYPE ); + } + + /* don't allow copies when the file is open. + * XXX: the spec only calls for read/deny write access. + * however, copyfile doesn't have any of that info, + * and locks need to stay coherent. as a result, + * we just balk if the file is opened already. */ + + adp = of_ad(s_vol, s_path, &ad); + + if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) { + return AFPERR_DENYCONF; + } +#ifdef HAVE_FSHARE_T + fshare_t shmd; + shmd.f_access = F_RDACC; + shmd.f_deny = F_NODNY; + if (fcntl(ad_data_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } + if (AD_RSRC_OPEN(adp) && fcntl(ad_reso_fileno(adp), F_SHARE, &shmd) != 0) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } +#endif + denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || + ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); + + if (denyreadset) { + retvalue = AFPERR_DENYCONF; + goto copy_exit; + } + + newname = obj->newtmp; + strcpy( newname, s_path->m_name ); + + p = ctoupath( s_vol, curdir, newname ); + if (!p) { + retvalue = AFPERR_PARAM; + goto copy_exit; + } + + if (NULL == ( d_vol = getvolbyvid( dvid )) ) { + retvalue = AFPERR_PARAM; + goto copy_exit; + } + + if (d_vol->v_flags & AFPVOL_RO) { + retvalue = AFPERR_VLOCK; + goto copy_exit; + } + + if (NULL == ( dir = dirlookup( d_vol, ddid )) ) { + retvalue = afp_errno; + goto copy_exit; + } + + if (( s_path = cname( d_vol, dir, &ibuf )) == NULL ) { + retvalue = get_afp_errno(AFPERR_NOOBJ); + goto copy_exit; + } + + if ( *s_path->m_name != '\0' ) { + retvalue =path_error(s_path, AFPERR_NOOBJ); + goto copy_exit; + } + + /* one of the handful of places that knows about the path type */ + if (copy_path_name(d_vol, newname, ibuf) < 0) { + retvalue = AFPERR_PARAM; + goto copy_exit; + } + /* newname is always only a filename so curdir *is* its + * parent folder + */ + if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding(d_vol->v_obj)))) { + retvalue =AFPERR_PARAM; + goto copy_exit; + } + + if ( (err = copyfile(s_vol, d_vol, curdir, -1, p, upath , newname, adp)) < 0 ) { + retvalue = err; + goto copy_exit; + } + curdir->d_offcnt++; + + setvoltime(obj, d_vol ); + +copy_exit: + ad_close( adp, ADFLAGS_DF |ADFLAGS_HF | ADFLAGS_SETSHRMD); + return( retvalue ); +} + +/* ---------------------------------- + * if newname is NULL (from directory.c) we don't want to copy the resource fork. + * because we are doing it elsewhere. + * currently if newname is NULL then adp is NULL. + */ +int copyfile(struct vol *s_vol, + struct vol *d_vol, + struct dir *d_dir, + int sfd, + char *src, + char *dst, + char *newname, + struct adouble *adp) +{ + struct adouble ads, add; + int err = 0; + int ret_err = 0; + int adflags; + int stat_result; + struct stat st; + + LOG(log_debug, logtype_afpd, "copyfile(sfd:%d,s:'%s',d:'%s',n:'%s')", + sfd, src, dst, newname); + + if (adp == NULL) { + ad_init(&ads, s_vol); + adp = &ads; + } + + adflags = ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF | ADFLAGS_RF | ADFLAGS_NORF; + + if (ad_openat(adp, sfd, src, adflags | ADFLAGS_RDONLY) < 0) { + ret_err = errno; + goto done; + } + + if (!AD_META_OPEN(adp)) + /* no resource fork, don't create one for dst file */ + adflags &= ~ADFLAGS_HF; + + if (!AD_RSRC_OPEN(adp)) + /* no resource fork, don't create one for dst file */ + adflags &= ~ADFLAGS_RF; + + stat_result = fstat(ad_data_fileno(adp), &st); /* saving stat exit code, thus saving us on one more stat later on */ + + if (stat_result < 0) { + /* unlikely but if fstat fails, the default file mode will be 0666. */ + st.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + } + + ad_init(&add, d_vol); + if (ad_open(&add, dst, adflags | ADFLAGS_RDWR | ADFLAGS_CREATE | ADFLAGS_EXCL, st.st_mode | S_IRUSR | S_IWUSR) < 0) { + ret_err = errno; + ad_close( adp, adflags ); + if (EEXIST != ret_err) { + deletefile(d_vol, -1, dst, 0); + goto done; + } + return AFPERR_EXIST; + } + + if ((err = copy_fork(ADEID_DFORK, &add, adp)) != 0) + LOG(log_error, logtype_afpd, "copyfile('%s'): %s", src, strerror(errno)); + + if (err == 0) + if ((err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst)) != 0) + LOG(log_error, logtype_afpd, "copyfile('%s'): %s", src, strerror(errno)); + + if (err < 0) + ret_err = errno; + + if (AD_META_OPEN(&add)) { + if (AD_META_OPEN(adp)) + ad_copy_header(&add, adp); + ad_setname(&add, dst); + cnid_t id; + struct stat stdest; + if (fstat(ad_meta_fileno(&add), &stdest) != 0) { + ret_err = errno; + goto error; + } + if ((id = get_id(d_vol, &add, &stdest, d_dir->d_did, dst, strlen(dst))) == CNID_INVALID) { + ret_err = EINVAL; + goto error; + } + (void)ad_setid(&add, stdest.st_dev, stdest.st_ino, id, d_dir->d_did, d_vol->v_stamp); + ad_flush(&add); + } + +error: + ad_close( adp, adflags ); + + if (ad_close( &add, adflags ) <0) { + ret_err = errno; + } + + if (ret_err) { + deletefile(d_vol, -1, dst, 0); + } + else if (stat_result == 0) { + /* set dest modification date to src date */ + struct utimbuf ut; + + ut.actime = ut.modtime = st.st_mtime; + utime(dst, &ut); + /* FIXME netatalk doesn't use resource fork file date + * but maybe we should set its modtime too. + */ + } + +done: + switch ( ret_err ) { + case 0: + return AFP_OK; + case EDQUOT: + case EFBIG: + case ENOSPC: + LOG(log_info, logtype_afpd, "copyfile: DISK FULL"); + return AFPERR_DFULL; + case ENOENT: + return AFPERR_NOOBJ; + case EACCES: + return AFPERR_ACCESS; + case EROFS: + return AFPERR_VLOCK; + } + return AFPERR_PARAM; +} + + +/* ----------------------------------- + vol: not NULL delete cnid entry. then we are in curdir and file is a only filename + checkAttrib: 1 check kFPDeleteInhibitBit (deletfile called by afp_delete) + + when deletefile is called we don't have lock on it, file is closed (for us) + untrue if called by renamefile + + ad_open always try to open file RDWR first and ad_lock takes care of + WRITE lock on read only file. +*/ + +static int check_attrib(const struct vol *vol, struct adouble *adp) +{ +uint16_t bshort = 0; + + ad_getattr(adp, &bshort); + /* + * Does kFPDeleteInhibitBit (bit 8) set? + */ + if (!(vol->v_ignattr & ATTRBIT_NODELETE) && (bshort & htons(ATTRBIT_NODELETE))) { + return AFPERR_OLOCK; + } + if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) { + return AFPERR_BUSY; + } + return 0; +} +/* + * dirfd can be used for unlinkat semantics + */ +int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib) +{ + struct adouble ad; + struct adouble *adp = NULL; + int adflags, err = AFP_OK; + int meta = 0; + + LOG(log_debug, logtype_afpd, "deletefile('%s')", file); + + ad_init(&ad, vol); + if (checkAttrib) { + /* was EACCESS error try to get only metadata */ + /* we never want to create a resource fork here, we are going to delete it + * moreover sometimes deletefile is called with a no existent file and + * ad_open would create a 0 byte resource fork + */ + if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) { + if ((err = check_attrib(vol, &ad))) { + ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF); + return err; + } + meta = 1; + } + } + + /* try to open both forks at once */ + adflags = ADFLAGS_DF; + if (ad_openat(&ad, dirfd, file, adflags | ADFLAGS_RF | ADFLAGS_NORF | ADFLAGS_RDONLY) < 0 ) { + switch (errno) { + case ENOENT: + err = AFPERR_NOOBJ; + goto end; + case EACCES: /* maybe it's a file with no write mode for us */ + break; /* was return AFPERR_ACCESS;*/ + case EROFS: + err = AFPERR_VLOCK; + goto end; + default: + err = AFPERR_PARAM; + goto end; + } + } + else { + adp = &ad; + } + + if ( adp && AD_RSRC_OPEN(adp) ) { /* there's a resource fork */ + adflags |= ADFLAGS_RF; + /* FIXME we have a pb here because we want to know if a file is open + * there's a 'priority inversion' if you can't open the ressource fork RW + * you can delete it if it's open because you can't get a write lock. + * + * ADLOCK_FILELOCK means the whole ressource fork, not only after the + * metadatas + * + * FIXME it doesn't work for RFORK open read only and fork open without deny mode + */ + if (ad_tmplock(&ad, ADEID_RFORK, ADLOCK_WR |ADLOCK_FILELOCK, 0, 0, 0) < 0 ) { + err = AFPERR_BUSY; + goto end; + } + } + + if (adp && ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) { + LOG(log_error, logtype_afpd, "deletefile('%s'): ad_tmplock error: %s", file, strerror(errno)); + err = AFPERR_BUSY; + } else if (!(err = vol->vfs->vfs_deletefile(vol, dirfd, file)) && !(err = netatalk_unlinkat(dirfd, file )) ) { + cnid_t id; + if (checkAttrib) { + AFP_CNID_START("cnid_get"); + id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)); + AFP_CNID_DONE(); + if (id) { + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, id); + AFP_CNID_DONE(); + } + } + } + +end: + if (meta) + ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF); + + if (adp) + ad_close( &ad, adflags ); /* ad_close removes locks if any */ + + return err; +} + +/* ------------------------------------ */ +/* return a file id */ +int afp_createid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct stat *st; + struct vol *vol; + struct dir *dir; + char *upath; + int len; + cnid_t did, id; + u_short vid; + struct path *s_path; + + *rbuflen = 0; + + ibuf += 2; + + memcpy(&vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM); + } + + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { + return AFPERR_NOOP; + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy(&did, ibuf, sizeof( did )); + ibuf += sizeof(did); + + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; /* was AFPERR_PARAM */ + } + + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); /* was AFPERR_PARAM */ + } + + if ( path_isadir(s_path) ) { + return( AFPERR_BADTYPE ); + } + + upath = s_path->u_name; + switch (s_path->st_errno) { + case 0: + break; /* success */ + case EPERM: + case EACCES: + return AFPERR_ACCESS; + case ENOENT: + return AFPERR_NOOBJ; + default: + return AFPERR_PARAM; + } + st = &s_path->st; + AFP_CNID_START("cnid_lookup"); + id = cnid_lookup(vol->v_cdb, st, did, upath, len = strlen(upath)); + AFP_CNID_DONE(); + if (id) { + memcpy(rbuf, &id, sizeof(id)); + *rbuflen = sizeof(id); + return AFPERR_EXISTID; + } + + if ((id = get_id(vol, NULL, st, did, upath, len)) != CNID_INVALID) { + memcpy(rbuf, &id, sizeof(id)); + *rbuflen = sizeof(id); + return AFP_OK; + } + + return afp_errno; +} + +/* ------------------------------- */ +struct reenum { + struct vol *vol; + cnid_t did; +}; + +static int reenumerate_loop(struct dirent *de, char *mname _U_, void *data) +{ + struct path path; + struct reenum *param = data; + struct vol *vol = param->vol; + cnid_t did = param->did; + cnid_t aint; + + if (ostat(de->d_name, &path.st, vol_syml_opt(vol)) < 0) + return 0; + + /* update or add to cnid */ + AFP_CNID_START("cnid_add"); + aint = cnid_add(vol->v_cdb, &path.st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */ + AFP_CNID_DONE(); + + return 0; +} + +/* -------------------- + * Ok the db is out of synch with the dir. + * but if it's a deleted file we don't want to do it again and again. +*/ +static int +reenumerate_id(struct vol *vol, char *name, struct dir *dir) +{ + int ret; + struct reenum data; + struct stat st; + + if (vol->v_cdb == NULL) { + return -1; + } + + /* FIXME use of_statdir ? */ + if (ostat(name, &st, vol_syml_opt(vol))) { + return -1; + } + + if (dirreenumerate(dir, &st)) { + /* we already did it once and the dir haven't been modified */ + return dir->d_offcnt; + } + + data.vol = vol; + data.did = dir->d_did; + if ((ret = for_each_dirent(vol, name, reenumerate_loop, (void *)&data)) >= 0) { + setdiroffcnt(curdir, &st, ret); + dir->d_flags |= DIRF_CNID; + } + + return ret; +} + +/* ------------------------------ + resolve a file id */ +int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + char *upath; + struct path path; + int err, retry=0; + size_t buflen; + cnid_t id, cnid; + uint16_t vid, bitmap; + + static char buffer[12 + MAXPATHLEN + 1]; + int len = 12 + MAXPATHLEN + 1; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM); + } + + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { + return AFPERR_NOOP; + } + + memcpy(&id, ibuf, sizeof( id )); + ibuf += sizeof(id); + cnid = id; + + if (!id) { + /* some MacOS versions after a catsearch do a *lot* of afp_resolveid with 0 */ + return AFPERR_NOID; + } +retry: + AFP_CNID_START("cnid_resolve"); + upath = cnid_resolve(vol->v_cdb, &id, buffer, len); + AFP_CNID_DONE(); + if (upath == NULL) { + return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */ + } + + if (NULL == ( dir = dirlookup( vol, id )) ) { + return AFPERR_NOID; /* idem AFPERR_PARAM */ + } + if (movecwd(vol, dir) < 0) { + switch (errno) { + case EACCES: + case EPERM: + return AFPERR_ACCESS; + case ENOENT: + return AFPERR_NOID; + default: + return AFPERR_PARAM; + } + } + + memset(&path, 0, sizeof(path)); + path.u_name = upath; + if (of_stat(vol, &path) < 0 ) { +#ifdef ESTALE + /* with nfs and our working directory is deleted */ + if (errno == ESTALE) { + errno = ENOENT; + } +#endif + if ( errno == ENOENT && !retry) { + /* cnid db is out of sync, reenumerate the directory and update ids */ + reenumerate_id(vol, ".", dir); + id = cnid; + retry = 1; + goto retry; + } + switch (errno) { + case EACCES: + case EPERM: + return AFPERR_ACCESS; + case ENOENT: + return AFPERR_NOID; + default: + return AFPERR_PARAM; + } + } + + /* directories are bad */ + if (S_ISDIR(path.st.st_mode)) { + /* OS9 and OSX don't return the same error code */ + return (obj->afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE; + } + + memcpy(&bitmap, ibuf, sizeof(bitmap)); + bitmap = ntohs( bitmap ); + if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding(obj)))) { + return AFPERR_NOID; + } + path.id = cnid; + if (AFP_OK != (err = getfilparams(obj, vol, bitmap, &path , curdir, + rbuf + sizeof(bitmap), &buflen, 0))) { + return err; + } + *rbuflen = buflen + sizeof(bitmap); + memcpy(rbuf, ibuf, sizeof(bitmap)); + + return AFP_OK; +} + +/* ------------------------------ */ +int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct stat st; + struct vol *vol; + struct dir *dir; + char *upath; + int err; + cnid_t id; + cnid_t fileid; + u_short vid; + static char buffer[12 + MAXPATHLEN + 1]; + int len = 12 + MAXPATHLEN + 1; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM); + } + + if (vol->v_cdb == NULL || !(vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { + return AFPERR_NOOP; + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy(&id, ibuf, sizeof( id )); + ibuf += sizeof(id); + fileid = id; + + AFP_CNID_START("cnid_resolve"); + upath = cnid_resolve(vol->v_cdb, &id, buffer, len); + AFP_CNID_DONE(); + if (upath == NULL) { + return AFPERR_NOID; + } + + if (NULL == ( dir = dirlookup( vol, id )) ) { + if (afp_errno == AFPERR_NOOBJ) { + err = AFPERR_NOOBJ; + goto delete; + } + return( AFPERR_PARAM ); + } + + err = AFP_OK; + if ((movecwd(vol, dir) < 0) || (ostat(upath, &st, vol_syml_opt(vol)) < 0)) { + switch (errno) { + case EACCES: + case EPERM: + return AFPERR_ACCESS; +#ifdef ESTALE + case ESTALE: +#endif + case ENOENT: + /* still try to delete the id */ + err = AFPERR_NOOBJ; + break; + default: + return AFPERR_PARAM; + } + } + else if (S_ISDIR(st.st_mode)) /* directories are bad */ + return AFPERR_BADTYPE; + +delete: + AFP_CNID_START("cnid_delete"); + if (cnid_delete(vol->v_cdb, fileid)) { + AFP_CNID_DONE(); + switch (errno) { + case EROFS: + return AFPERR_VLOCK; + case EPERM: + case EACCES: + return AFPERR_ACCESS; + default: + return AFPERR_PARAM; + } + } + AFP_CNID_DONE(); + return err; +} + +/* ------------------------------ */ +static struct adouble *find_adouble(const AFPObj *obj, struct vol *vol, struct path *path, struct ofork **of, struct adouble *adp) +{ + int ret; + + if (path->st_errno) { + switch (path->st_errno) { + case ENOENT: + afp_errno = AFPERR_NOID; + break; + case EPERM: + case EACCES: + afp_errno = AFPERR_ACCESS; + break; + default: + afp_errno = AFPERR_PARAM; + break; + } + return NULL; + } + /* we use file_access both for legacy Mac perm and + * for unix privilege, rename will take care of folder perms + */ + if (file_access(obj, vol, path, OPENACC_WR ) < 0) { + afp_errno = AFPERR_ACCESS; + return NULL; + } + + if ((*of = of_findname(vol, path))) { + /* reuse struct adouble so it won't break locks */ + adp = (*of)->of_ad; + } + else { + ret = ad_open(adp, path->u_name, ADFLAGS_HF | ADFLAGS_RDWR); + /* META and HF */ + if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) { + /* from AFP spec. + * The user must have the Read & Write privilege for both files in order to use this command. + */ + ad_close(adp, ADFLAGS_HF); + afp_errno = AFPERR_ACCESS; + return NULL; + } + } + return adp; +} + +#define APPLETEMP ".AppleTempXXXXXX" + +int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct stat srcst, destst; + struct vol *vol; + struct dir *dir, *sdir; + char *spath, temp[17], *p; + char *supath, *upath; + struct path *path; + int err; + struct adouble ads; + struct adouble add; + struct adouble *adsp = NULL; + struct adouble *addp = NULL; + struct ofork *s_of = NULL; + struct ofork *d_of = NULL; + int crossdev; + + int slen, dlen; + uint32_t sid, did; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof(vid)); + ibuf += sizeof(vid); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM); + } + + if ((vol->v_flags & AFPVOL_RO)) + return AFPERR_VLOCK; + + /* source and destination dids */ + memcpy(&sid, ibuf, sizeof(sid)); + ibuf += sizeof(sid); + memcpy(&did, ibuf, sizeof(did)); + ibuf += sizeof(did); + + /* source file */ + if (NULL == (dir = dirlookup( vol, sid )) ) { + return afp_errno; /* was AFPERR_PARAM */ + } + + if (NULL == ( path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + if ( path_isadir(path) ) { + return AFPERR_BADTYPE; /* it's a dir */ + } + + /* save some stuff */ + srcst = path->st; + sdir = curdir; + spath = obj->oldtmp; + supath = obj->newtmp; + strcpy(spath, path->m_name); + strcpy(supath, path->u_name); /* this is for the cnid changing */ + p = absupath( vol, sdir, supath); + if (!p) { + /* pathname too long */ + return AFPERR_PARAM ; + } + + ad_init(&ads, vol); + if (!(adsp = find_adouble(obj, vol, path, &s_of, &ads))) { + return afp_errno; + } + + /* ***** from here we may have resource fork open **** */ + + /* look for the source cnid. if it doesn't exist, don't worry about + * it. */ + AFP_CNID_START("cnid_lookup"); + sid = cnid_lookup(vol->v_cdb, &srcst, sdir->d_did, supath,slen = strlen(supath)); + AFP_CNID_DONE(); + + if (NULL == ( dir = dirlookup( vol, did )) ) { + err = afp_errno; /* was AFPERR_PARAM */ + goto err_exchangefile; + } + + if (NULL == ( path = cname( vol, dir, &ibuf )) ) { + err = get_afp_errno(AFPERR_NOOBJ); + goto err_exchangefile; + } + + if ( path_isadir(path) ) { + err = AFPERR_BADTYPE; + goto err_exchangefile; + } + + /* FPExchangeFiles is the only call that can return the SameObj + * error */ + if ((curdir == sdir) && strcmp(spath, path->m_name) == 0) { + err = AFPERR_SAMEOBJ; + goto err_exchangefile; + } + + ad_init(&add, vol); + if (!(addp = find_adouble(obj, vol, path, &d_of, &add))) { + err = afp_errno; + goto err_exchangefile; + } + destst = path->st; + + /* they are not on the same device and at least one is open + * FIXME broken for for crossdev and adouble v2 + * return an error + */ + crossdev = (srcst.st_dev != destst.st_dev); + if (/* (d_of || s_of) && */ crossdev) { + err = AFPERR_MISC; + goto err_exchangefile; + } + + /* look for destination id. */ + upath = path->u_name; + AFP_CNID_START("cnid_lookup"); + did = cnid_lookup(vol->v_cdb, &destst, curdir->d_did, upath, dlen = strlen(upath)); + AFP_CNID_DONE(); + + /* construct a temp name. + * NOTE: the temp file will be in the dest file's directory. it + * will also be inaccessible from AFP. */ + memcpy(temp, APPLETEMP, sizeof(APPLETEMP)); + int fd; + if ((fd = mkstemp(temp)) == -1) { + err = AFPERR_MISC; + goto err_exchangefile; + } + close(fd); + + if (crossdev) { + /* FIXME we need to close fork for copy, both s_of and d_of are null */ + ad_close(adsp, ADFLAGS_HF); + ad_close(addp, ADFLAGS_HF); + } + + /* now, quickly rename the file. we error if we can't. */ + if ((err = renamefile(vol, curdir, -1, p, temp, temp, adsp)) != AFP_OK) + goto err_exchangefile; + of_rename(vol, s_of, sdir, spath, curdir, temp); + + /* rename destination to source */ + if ((err = renamefile(vol, curdir, -1, upath, p, spath, addp)) != AFP_OK) + goto err_src_to_tmp; + of_rename(vol, d_of, curdir, path->m_name, sdir, spath); + + /* rename temp to destination */ + if ((err = renamefile(vol, curdir, -1, temp, upath, path->m_name, adsp)) != AFP_OK) + goto err_dest_to_src; + of_rename(vol, s_of, curdir, temp, curdir, path->m_name); + + /* + * id's need switching. src -> dest and dest -> src. + * we need to re-stat() if it was a cross device copy. + */ + if (sid) { + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, sid); + AFP_CNID_DONE(); + } + if (did) { + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, did); + AFP_CNID_DONE(); + } + + if ((did && ( (crossdev && ostat(upath, &srcst, vol_syml_opt(vol)) < 0) || + cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0)) + || + (sid && ( (crossdev && ostat(p, &destst, vol_syml_opt(vol)) < 0) || + cnid_update(vol->v_cdb, sid, &destst, sdir->d_did,supath, slen) < 0)) + ) { + switch (errno) { + case EPERM: + case EACCES: + err = AFPERR_ACCESS; + break; + default: + err = AFPERR_PARAM; + } + goto err_temp_to_dest; + } + + if (AD_META_OPEN(adsp) || AD_META_OPEN(addp)) { + struct adouble adtmp; + bool opened_ads, opened_add; + + ad_init(&adtmp, vol); + ad_init_offsets(&adtmp); + + if (!AD_META_OPEN(adsp)) { + if (ad_open(adsp, p, ADFLAGS_HF) != 0) + return -1; + opened_ads = true; + } + + if (!AD_META_OPEN(addp)) { + if (ad_open(addp, upath, ADFLAGS_HF) != 0) + return -1; + opened_add = true; + } + + if (ad_copy_header(&adtmp, adsp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(adsp, addp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(addp, &adtmp) != 0) + goto err_temp_to_dest; + ad_flush(adsp); + ad_flush(addp); + + if (opened_ads) + ad_close(adsp, ADFLAGS_HF); + if (opened_add) + ad_close(addp, ADFLAGS_HF); + } + + /* FIXME: we should switch ressource fork too */ + + /* here we need to reopen if crossdev */ + if (sid && ad_setid(addp, destst.st_dev, destst.st_ino, sid, sdir->d_did, vol->v_stamp)) + { + ad_flush( addp ); + } + + if (did && ad_setid(adsp, srcst.st_dev, srcst.st_ino, did, curdir->d_did, vol->v_stamp)) + { + ad_flush( adsp ); + } + + /* change perms, src gets dest perm and vice versa */ + + become_root(); + + /* + * we need to exchange ACL entries as well + */ + /* exchange_acls(vol, p, upath); */ + + path->st = srcst; + path->st_valid = 1; + path->st_errno = 0; + path->m_name = NULL; + path->u_name = upath; + + setfilunixmode(vol, path, destst.st_mode); + setfilowner(vol, destst.st_uid, destst.st_gid, path); + + path->st = destst; + path->st_valid = 1; + path->st_errno = 0; + path->u_name = p; + + setfilunixmode(vol, path, srcst.st_mode); + setfilowner(vol, srcst.st_uid, srcst.st_gid, path); + + unbecome_root(); + + err = AFP_OK; + goto err_exchangefile; + + /* all this stuff is so that we can unwind a failed operation + * properly. */ +err_temp_to_dest: + /* rename dest to temp */ + renamefile(vol, curdir, -1, upath, temp, temp, adsp); + of_rename(vol, s_of, curdir, upath, curdir, temp); + +err_dest_to_src: + /* rename source back to dest */ + renamefile(vol, curdir, -1, p, upath, path->m_name, addp); + of_rename(vol, d_of, sdir, spath, curdir, path->m_name); + +err_src_to_tmp: + /* rename temp back to source */ + renamefile(vol, curdir, -1, temp, p, spath, adsp); + of_rename(vol, s_of, curdir, temp, sdir, spath); + +err_exchangefile: + if ( !s_of && adsp && ad_meta_fileno(adsp) != -1 ) { /* META */ + ad_close(adsp, ADFLAGS_HF); + } + if ( !d_of && addp && ad_meta_fileno(addp) != -1 ) {/* META */ + ad_close(addp, ADFLAGS_HF); + } + + struct dir *cached; + if ((cached = dircache_search_by_did(vol, sid)) != NULL) + (void)dir_remove(vol, cached); + if ((cached = dircache_search_by_did(vol, did)) != NULL) + (void)dir_remove(vol, cached); + + return err; +} diff --git a/etc/afpd/file.h b/etc/afpd/file.h new file mode 100644 index 0000000..1d0ff45 --- /dev/null +++ b/etc/afpd/file.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifndef AFPD_FILE_H +#define AFPD_FILE_H 1 + +/*#include */ /* including it here causes some confusion */ +#include +#include +#include +#include + +#include "volume.h" +#include "directory.h" + +extern const u_char ufinderi[]; + +#define FILPBIT_ATTR 0 +#define FILPBIT_PDID 1 +#define FILPBIT_CDATE 2 +#define FILPBIT_MDATE 3 +#define FILPBIT_BDATE 4 +#define FILPBIT_FINFO 5 +#define FILPBIT_LNAME 6 +#define FILPBIT_SNAME 7 +#define FILPBIT_FNUM 8 +#define FILPBIT_DFLEN 9 +#define FILPBIT_RFLEN 10 +#define FILPBIT_EXTDFLEN 11 +#define FILPBIT_PDINFO 13 /* ProDOS Info/ UTF8 name */ +#define FILPBIT_EXTRFLEN 14 +#define FILPBIT_UNIXPR 15 + +#define kTextEncodingUTF8 0x08000103 + +typedef enum { + /* Mac OS encodings*/ + kTextEncodingMacRoman = 0L, + kTextEncodingMacJapanese = 1, + kTextEncodingMacChineseTrad = 2, + kTextEncodingMacKorean = 3, + kTextEncodingMacArabic = 4, + kTextEncodingMacHebrew = 5, + kTextEncodingMacGreek = 6, + kTextEncodingMacCyrillic = 7, + kTextEncodingMacDevanagari = 9, + kTextEncodingMacGurmukhi = 10, + kTextEncodingMacGujarati = 11, + kTextEncodingMacOriya = 12, + kTextEncodingMacBengali = 13, + kTextEncodingMacTamil = 14, + kTextEncodingMacTelugu = 15, + kTextEncodingMacKannada = 16, + kTextEncodingMacMalayalam = 17, + kTextEncodingMacSinhalese = 18, + kTextEncodingMacBurmese = 19, + kTextEncodingMacKhmer = 20, + kTextEncodingMacThai = 21, + kTextEncodingMacLaotian = 22, + kTextEncodingMacGeorgian = 23, + kTextEncodingMacArmenian = 24, + kTextEncodingMacChineseSimp = 25, + kTextEncodingMacTibetan = 26, + kTextEncodingMacMongolian = 27, + kTextEncodingMacEthiopic = 28, + kTextEncodingMacCentralEurRoman = 29, + kTextEncodingMacVietnamese = 30, + kTextEncodingMacExtArabic = 31, /* The following use script code 0, smRoman*/ + kTextEncodingMacSymbol = 33, + kTextEncodingMacDingbats = 34, + kTextEncodingMacTurkish = 35, + kTextEncodingMacCroatian = 36, + kTextEncodingMacIcelandic = 37, + kTextEncodingMacRomanian = 38, + kTextEncodingMacCeltic = 39, + kTextEncodingMacGaelic = 40, + kTextEncodingMacKeyboardGlyphs = 41, +} kTextEncoding_t; + +extern char *set_name (const struct vol *, char *, cnid_t, char *, cnid_t, uint32_t ); + +extern struct extmap *getextmap (const char *); +extern struct extmap *getdefextmap (void); + +extern int getfilparams (const AFPObj *obj, struct vol *, uint16_t, struct path *, + struct dir *, char *buf, size_t *, int); +extern int setfilparams (const AFPObj *obj, struct vol *, struct path *, uint16_t, char *); +extern int renamefile (struct vol *, struct dir *, int, char *, char *, char *, struct adouble *); +extern int copyfile (struct vol *, struct vol *, struct dir *, int, char *, char *, char *, struct adouble *); +extern int deletefile (const struct vol *, int, char *, int); + +extern int getmetadata (const AFPObj *obj, struct vol *vol, uint16_t bitmap, struct path *path, + struct dir *dir, char *buf, size_t *buflen, struct adouble *adp); + +extern void *get_finderinfo (const struct vol *, const char *, struct adouble *, void *, int); + +extern size_t mtoUTF8 (const struct vol *, const char *, size_t , char *, size_t ); +extern int copy_path_name (const struct vol *, char *, char *i); + +extern uint32_t get_id (struct vol *, + struct adouble *, + const struct stat *, + cnid_t , + const char *, + int ); + +/* FP functions */ +int afp_exchangefiles (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setfilparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_copyfile (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_createfile (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_createid (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_resolveid (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_deleteid (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +#endif diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c new file mode 100644 index 0000000..7adbeed --- /dev/null +++ b/etc/afpd/filedir.c @@ -0,0 +1,861 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "directory.h" +#include "dircache.h" +#include "desktop.h" +#include "volume.h" +#include "fork.h" +#include "file.h" +#include "filedir.h" +#include "unix.h" + +int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct stat *st; + struct vol *vol; + struct dir *dir; + uint32_t did; + int ret; + size_t buflen; + uint16_t fbitmap, dbitmap, vid; + struct path *s_path; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + /* was AFPERR_PARAM but it helps OS 10.3 when a volume has been removed + * from the list. + */ + return( AFPERR_ACCESS ); + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + memcpy( &fbitmap, ibuf, sizeof( fbitmap )); + fbitmap = ntohs( fbitmap ); + ibuf += sizeof( fbitmap ); + memcpy( &dbitmap, ibuf, sizeof( dbitmap )); + dbitmap = ntohs( dbitmap ); + ibuf += sizeof( dbitmap ); + + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + LOG(log_debug, logtype_afpd, "getfildirparams(vid:%u, did:%u, f/d:%04x/%04x) {cwdid:%u, cwd: %s, name:'%s'}", + ntohs(vid), ntohl(dir->d_did), fbitmap, dbitmap, + ntohl(curdir->d_did), cfrombstr(curdir->d_fullpath), s_path->u_name); + + st = &s_path->st; + if (!s_path->st_valid) { + /* it's a dir and it should be there + * because we chdir in it in cname or + * it's curdir (maybe deleted, but then we can't know). + * So we need to try harder. + */ + of_statdir(vol, s_path); + } + if ( s_path->st_errno != 0 ) { + if (afp_errno != AFPERR_ACCESS) { + return( AFPERR_NOOBJ ); + } + } + + + buflen = 0; + if (S_ISDIR(st->st_mode)) { + if (dbitmap) { + dir = s_path->d_dir; + if (!dir) + return AFPERR_NOOBJ; + + ret = getdirparams(obj, vol, dbitmap, s_path, dir, + rbuf + 3 * sizeof( uint16_t ), &buflen ); + if (ret != AFP_OK ) + return( ret ); + } + /* this is a directory */ + *(rbuf + 2 * sizeof( uint16_t )) = (char) FILDIRBIT_ISDIR; + } else { + if (fbitmap && AFP_OK != (ret = getfilparams(obj, vol, fbitmap, s_path, curdir, + rbuf + 3 * sizeof( uint16_t ), &buflen, 0)) ) { + return( ret ); + } + /* this is a file */ + *(rbuf + 2 * sizeof( uint16_t )) = FILDIRBIT_ISFILE; + } + *rbuflen = buflen + 3 * sizeof( uint16_t ); + fbitmap = htons( fbitmap ); + memcpy( rbuf, &fbitmap, sizeof( fbitmap )); + rbuf += sizeof( fbitmap ); + dbitmap = htons( dbitmap ); + memcpy( rbuf, &dbitmap, sizeof( dbitmap )); + rbuf += sizeof( dbitmap ) + sizeof( u_char ); + *rbuf = 0; + + return( AFP_OK ); +} + +int afp_setfildirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct stat *st; + struct vol *vol; + struct dir *dir; + struct path *path; + uint16_t vid, bitmap; + int did, rc; + + *rbuflen = 0; + ibuf += 2; + memcpy( &vid, ibuf, sizeof(vid)); + ibuf += sizeof( vid ); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy( &did, ibuf, sizeof( did)); + ibuf += sizeof( did); + + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + memcpy( &bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + + if (NULL == ( path = cname( vol, dir, &ibuf ))) { + return get_afp_errno(AFPERR_NOOBJ); + } + + st = &path->st; + if (!path->st_valid) { + /* it's a dir and it should be there + * because we chdir in it in cname + */ + of_statdir(vol, path); + } + + if ( path->st_errno != 0 ) { + if (afp_errno != AFPERR_ACCESS) + return( AFPERR_NOOBJ ); + } + /* + * If ibuf is odd, make it even. + */ + if ((u_long)ibuf & 1 ) { + ibuf++; + } + + if (S_ISDIR(st->st_mode)) { + rc = setdirparams(vol, path, bitmap, ibuf ); + } else { + rc = setfilparams(obj, vol, path, bitmap, ibuf ); + } + if ( rc == AFP_OK ) { + setvoltime(obj, vol ); + } + + return( rc ); +} + +/* -------------------------------------------- + Factorise some checks on a pathname +*/ +int check_name(const struct vol *vol, char *name) +{ + if (!vol->vfs->vfs_validupath(vol, name)) { + LOG(log_error, logtype_afpd, "check_name: illegal name: '%s'", name); + return AFPERR_EXIST; + } + + /* check for vetoed filenames */ + if (veto_file(vol->v_veto, name)) + return AFPERR_EXIST; + return 0; +} + +/* ------------------------- + move and rename sdir:oldname to curdir:newname in volume vol + special care is needed for lock +*/ +static int moveandrename(const AFPObj *obj, + struct vol *vol, + struct dir *sdir, + int sdir_fd, + char *oldname, + char *newname, + int isdir) +{ + char *oldunixname = NULL; + char *upath; + int rc; + struct stat *st, nst; + int adflags; + struct adouble ad; + struct adouble *adp; + struct ofork *opened = NULL; + struct path path; + cnid_t id; + int cwd_fd = -1; + + ad_init(&ad, vol); + adp = &ad; + adflags = 0; + + if (!isdir) { + if ((oldunixname = strdup(mtoupath(vol, oldname, sdir->d_did, utf8_encoding(vol->v_obj)))) == NULL) + return AFPERR_PARAM; /* can't convert */ + AFP_CNID_START("cnid_get"); + id = cnid_get(vol->v_cdb, sdir->d_did, oldunixname, strlen(oldunixname)); + AFP_CNID_DONE(); + +#ifndef HAVE_ATFUNCS + /* Need full path */ + free(oldunixname); + if ((oldunixname = strdup(ctoupath(vol, sdir, oldname))) == NULL) + return AFPERR_PARAM; /* pathname too long */ +#endif /* HAVE_ATFUNCS */ + + path.st_valid = 0; + path.u_name = oldunixname; + +#ifdef HAVE_ATFUNCS + opened = of_findnameat(sdir_fd, &path); +#else + opened = of_findname(vol, &path); +#endif /* HAVE_ATFUNCS */ + + if (opened) { + /* reuse struct adouble so it won't break locks */ + adp = opened->of_ad; + } + } else { + id = sdir->d_did; /* we already have the CNID */ + if ((oldunixname = strdup(ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname))) == NULL) + return AFPERR_PARAM; + adflags = ADFLAGS_DIR; + } + + /* + * oldunixname now points to either + * a) full pathname of the source fs object (if renameat is not available) + * b) the oldname (renameat is available) + * we are in the dest folder so we need to use + * a) oldunixname for ad_open + * b) fchdir sdir_fd before eg ad_open or use *at functions where appropiate + */ + + if (sdir_fd != -1) { + if ((cwd_fd = open(".", O_RDONLY)) == -1) + return AFPERR_MISC; + if (fchdir(sdir_fd) != 0) { + rc = AFPERR_MISC; + goto exit; + } + } + if (!ad_metadata(oldunixname, adflags, adp)) { + uint16_t bshort; + + ad_getattr(adp, &bshort); + + ad_close(adp, ADFLAGS_HF); + if (!(vol->v_ignattr & ATTRBIT_NORENAME) && (bshort & htons(ATTRBIT_NORENAME))) { + rc = AFPERR_OLOCK; + goto exit; + } + } + if (sdir_fd != -1) { + if (fchdir(cwd_fd) != 0) { + LOG(log_error, logtype_afpd, "moveandrename: %s", strerror(errno) ); + rc = AFPERR_MISC; + goto exit; + } + } + + if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding(vol->v_obj)))){ + rc = AFPERR_PARAM; + goto exit; + } + path.u_name = upath; + st = &path.st; + if (0 != (rc = check_name(vol, upath))) { + goto exit; + } + + if (isdir) + LOG(log_debug, logtype_afpd, + "moveandrename(\"%s\" -> \"%s/%s\")", + oldunixname, bdata(curdir->d_fullpath), upath); + else + LOG(log_debug, logtype_afpd, + "moveandrename(\"%s/%s\" -> \"%s/%s\")", + bdata(sdir->d_fullpath), oldunixname, bdata(curdir->d_fullpath), upath); + + /* source == destination. we just silently accept this. */ + if ((!isdir && curdir == sdir) || (isdir && curdir->d_did == sdir->d_pdid)) { + if (strcmp(oldname, newname) == 0) { + rc = AFP_OK; + goto exit; + } + + if (stat(upath, st) == 0) { + if (!stat(oldunixname, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) { + /* not the same file */ + rc = AFPERR_EXIST; + goto exit; + } + errno = 0; + } + } else if (stat(upath, st ) == 0) { + rc = AFPERR_EXIST; + goto exit; + } + + if ( !isdir ) { + path.st_valid = 1; + path.st_errno = errno; + if (of_findname(vol, &path)) { + rc = AFPERR_EXIST; /* was AFPERR_BUSY; */ + } else { + rc = renamefile(vol, curdir, sdir_fd, oldunixname, upath, newname, adp ); + if (rc == AFP_OK) + of_rename(vol, opened, sdir, oldname, curdir, newname); + } + } else { + rc = renamedir(vol, sdir_fd, oldunixname, upath, sdir, curdir, newname); + } + if ( rc == AFP_OK && id ) { + /* renaming may have moved the file/dir across a filesystem */ + if (stat(upath, st) < 0) { + rc = AFPERR_MISC; + goto exit; + } + + /* Remove it from the cache */ + struct dir *cacheddir = dircache_search_by_did(vol, id); + if (cacheddir) { + LOG(log_warning, logtype_afpd,"Still cached: \"%s/%s\"", getcwdpath(), upath); + (void)dir_remove(vol, cacheddir); + } + + /* Fixup adouble info */ + if (!ad_metadata(upath, adflags, adp)) { + ad_setid(adp, st->st_dev, st->st_ino, id, curdir->d_did, vol->v_stamp); + ad_flush(adp); + ad_close(adp, ADFLAGS_HF); + } + + /* fix up the catalog entry */ + AFP_CNID_START("cnid_update"); + cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath)); + AFP_CNID_DONE(); + + /* Send FCE event */ + if (isdir) { + fce_register(obj, FCE_DIR_MOVE, fullpathname(upath), oldunixname); + } else { + bstring srcpath = bformat("%s/%s", bdata(sdir->d_fullpath), oldunixname); + fce_register(obj, FCE_FILE_MOVE, fullpathname(upath), bdata(srcpath)); + bdestroy(srcpath); + } + } + +exit: + if (cwd_fd != -1) + close(cwd_fd); + if (oldunixname) + free(oldunixname); + return rc; +} + +/* -------------------------------------------- */ +int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *sdir; + char *oldname, *newname; + struct path *path; + uint32_t did; + int plen; + uint16_t vid; + int isdir = 0; + int rc; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( did ); + if (NULL == ( sdir = dirlookup( vol, did )) ) { + return afp_errno; + } + + /* source pathname */ + if (NULL == ( path = cname( vol, sdir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + sdir = curdir; + newname = obj->newtmp; + oldname = obj->oldtmp; + isdir = path_isadir(path); + if ( *path->m_name != '\0' ) { + strcpy(oldname, path->m_name); /* an extra copy for of_rename */ + if (isdir) { + /* curdir parent dir, need to move sdir back */ + sdir = path->d_dir; + } + } + else { + if ( sdir->d_did == DIRDID_ROOT ) { /* root directory */ + return( AFPERR_NORENAME ); + } + /* move to destination dir */ + if ( movecwd( vol, dirlookup(vol, sdir->d_pdid) ) < 0 ) { + return afp_errno; + } + memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) +1); + } + + /* another place where we know about the path type */ + if ((plen = copy_path_name(vol, newname, ibuf)) < 0) { + return( AFPERR_PARAM ); + } + + if (!plen) { + return AFP_OK; /* newname == oldname same dir */ + } + + rc = moveandrename(obj, vol, sdir, -1, oldname, newname, isdir); + if ( rc == AFP_OK ) { + setvoltime(obj, vol ); + } + + return( rc ); +} + +/* + * Recursivley delete vetoed files and directories if the volume option is set + * + * @param vol (r) volume handle + * @param upath (r) path of directory + * + * If the volume option delete veto files is set, this function recursively scans the + * directory "upath" for vetoed files and tries deletes these, the it will try to delete + * the directory. That may fail if the directory contains normal files that aren't vetoed. + * + * @returns 0 if the directory upath and all of its contents were deleted, otherwise -1. + * If the volume option is not set it returns -1. + */ +int delete_vetoed_files(struct vol *vol, const char *upath, bool in_vetodir) +{ + EC_INIT; + DIR *dp = NULL; + struct dirent *de; + struct stat sb; + int pwd = -1; + bool vetoed; + + if (!(vol->v_flags & AFPVOL_DELVETO)) + return -1; + + EC_NEG1( pwd = open(".", O_RDONLY)); + EC_ZERO( chdir(upath) ); + EC_NULL( dp = opendir(".") ); + + while ((de = readdir(dp))) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + + if (stat(de->d_name, &sb) != 0) { + LOG(log_error, logtype_afpd, "delete_vetoed_files(\"%s/%s\"): %s", + upath, de->d_name, strerror(errno)); + EC_EXIT_STATUS(AFPERR_DIRNEMPT); + } + + if (in_vetodir || veto_file(vol->v_veto, de->d_name)) + vetoed = true; + else + vetoed = false; + + if (vetoed) { + LOG(log_debug, logtype_afpd, "delete_vetoed_files(\"%s/%s\"): deleting vetoed file", + upath, de->d_name); + switch (sb.st_mode & S_IFMT) { + case S_IFDIR: + /* recursion */ + EC_ZERO( delete_vetoed_files(vol, de->d_name, vetoed)); + break; + case S_IFREG: + case S_IFLNK: + EC_ZERO( netatalk_unlink(de->d_name) ); + break; + default: + break; + } + } + } + + EC_ZERO_LOG( fchdir(pwd) ); + pwd = -1; + EC_ZERO_LOG( rmdir(upath) ); + +EC_CLEANUP: + if (dp) + closedir(dp); + if (pwd != -1) { + if (fchdir(pwd) != 0) + ret = -1; + } + + EC_EXIT; +} + +/* ------------------------------- */ +int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + struct path *s_path; + char *upath; + int did; + int rc = AFP_OK; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( int ); + + if (NULL == ( dir = dirlookup( vol, did )) ) { + return afp_errno; + } + + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + upath = s_path->u_name; + if (path_isadir(s_path)) { + if (*s_path->m_name != '\0' || curdir->d_did == DIRDID_ROOT) { + if (vol->v_adouble == AD_VERSION2) + return AFPERR_ACCESS; + if (*s_path->m_name == '\0' && curdir->d_did == DIRDID_ROOT) + return AFPERR_ACCESS; + if (rmdir(upath) != 0) { + switch (errno) { + case ENOTEMPTY: + if (delete_vetoed_files(vol, upath, false) != 0) + return AFPERR_DIRNEMPT; + break; + case EACCES: + return AFPERR_ACCESS; + default: + return AFPERR_MISC; + } + } + struct dir *deldir; + cnid_t delcnid = CNID_INVALID; + if ((deldir = dircache_search_by_name(vol, curdir, upath, strlen(upath)))) { + delcnid = deldir->d_did; + dir_remove(vol, deldir); + } + if (delcnid == CNID_INVALID) { + AFP_CNID_START("cnid_get"); + delcnid = cnid_get(vol->v_cdb, curdir->d_did, upath, strlen(upath)); + AFP_CNID_DONE(); + } + if (delcnid != CNID_INVALID) { + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, delcnid); + AFP_CNID_DONE(); + } + fce_register(obj, FCE_DIR_DELETE, fullpathname(upath), NULL); + } else { + /* we have to cache this, the structs are lost in deletcurdir*/ + /* but we need the positive returncode to send our event */ + bstring dname; + if ((dname = bstrcpy(curdir->d_u_name)) == NULL) + return AFPERR_MISC; + if ((rc = deletecurdir(vol)) == AFP_OK) + fce_register(obj, FCE_DIR_DELETE, fullpathname(cfrombstr(dname)), NULL); + bdestroy(dname); + } + } else if (of_findname(vol, s_path)) { + rc = AFPERR_BUSY; + } else { + /* it's a file st_valid should always be true + * only test for ENOENT because EACCES needs + * to read meta data in deletefile + */ + if (s_path->st_valid && s_path->st_errno == ENOENT) { + rc = AFPERR_NOOBJ; + } else { + if ((rc = deletefile(vol, -1, upath, 1)) == AFP_OK) { + fce_register(obj, FCE_FILE_DELETE, fullpathname(upath), NULL); + if (vol->v_tm_used < s_path->st.st_size) + vol->v_tm_used = 0; + else + vol->v_tm_used -= s_path->st.st_size; + } + struct dir *cachedfile; + if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath)))) { + dircache_remove(vol, cachedfile, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); + dir_free(cachedfile); + } + } + } + if ( rc == AFP_OK ) { + curdir->d_offcnt--; + setvoltime(obj, vol ); + } + + return( rc ); +} +/* ------------------------ */ +char *absupath(const struct vol *vol, struct dir *dir, char *u) +{ + static char pathbuf[MAXPATHLEN + 1]; + bstring path; + + if (u == NULL || dir == NULL || vol == NULL) + return NULL; + + if ((path = bstrcpy(dir->d_fullpath)) == NULL) + return NULL; + if (bcatcstr(path, "/") != BSTR_OK) + return NULL; + if (bcatcstr(path, u) != BSTR_OK) + return NULL; + if (path->slen > MAXPATHLEN) { + bdestroy(path); + return NULL; + } + + LOG(log_debug, logtype_afpd, "absupath: %s", cfrombstr(path)); + + strncpy(pathbuf, cfrombstr(path), blength(path) + 1); + bdestroy(path); + + return(pathbuf); +} + +char *ctoupath(const struct vol *vol, struct dir *dir, char *name) +{ + if (vol == NULL || dir == NULL || name == NULL) + return NULL; + return absupath(vol, dir, mtoupath(vol, name, dir->d_did, utf8_encoding(vol->v_obj))); +} + +/* ------------------------- */ +int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + struct dir *sdir, *ddir; + int isdir; + char *oldname, *newname; + struct path *path; + int did; + int pdid; + int plen; + uint16_t vid; + int rc; + int sdir_fd = -1; + + + *rbuflen = 0; + ibuf += 2; + + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + if (vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + /* source did followed by dest did */ + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( int ); + if (NULL == ( sdir = dirlookup( vol, did )) ) { + return afp_errno; /* was AFPERR_PARAM */ + } + + memcpy( &did, ibuf, sizeof( did )); + ibuf += sizeof( int ); + + /* source pathname */ + if (NULL == ( path = cname( vol, sdir, &ibuf )) ) { + return get_afp_errno(AFPERR_NOOBJ); + } + + sdir = curdir; + newname = obj->newtmp; + oldname = obj->oldtmp; + + isdir = path_isadir(path); + if ( *path->m_name != '\0' ) { + if (isdir) { + sdir = path->d_dir; + } + strcpy(oldname, path->m_name); /* an extra copy for of_rename */ + } else { + memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) + 1); + } + +#ifdef HAVE_ATFUNCS + if ((sdir_fd = open(".", O_RDONLY)) == -1) + return AFPERR_MISC; +#endif + + /* get the destination directory */ + if (NULL == ( ddir = dirlookup( vol, did )) ) { + rc = afp_errno; /* was AFPERR_PARAM */ + goto exit; + } + if (NULL == ( path = cname( vol, ddir, &ibuf ))) { + rc = AFPERR_NOOBJ; + goto exit; + } + pdid = curdir->d_did; + if ( *path->m_name != '\0' ) { + rc = path_error(path, AFPERR_NOOBJ); + goto exit; + } + + /* one more place where we know about path type */ + if ((plen = copy_path_name(vol, newname, ibuf)) < 0) { + rc = AFPERR_PARAM; + goto exit; + } + + if (!plen) { + strcpy(newname, oldname); + } + + /* This does the work */ + LOG(log_debug, logtype_afpd, "afp_move(oldname:'%s', newname:'%s', isdir:%u)", + oldname, newname, isdir); + rc = moveandrename(obj, vol, sdir, sdir_fd, oldname, newname, isdir); + + if ( rc == AFP_OK ) { + char *upath = mtoupath(vol, newname, pdid, utf8_encoding(obj)); + + if (NULL == upath) { + rc = AFPERR_PARAM; + goto exit; + } + /* if unix priv don't try to match perm with dest folder */ + if (!isdir && !vol_unix_priv(vol)) { + int admode = ad_mode("", 0777) | vol->v_fperm; + + setfilmode(vol, upath, admode, path->st_valid ? &path->st : NULL); + vol->vfs->vfs_setfilmode(vol, upath, admode, path->st_valid ? &path->st : NULL); + } + setvoltime(obj, vol ); + } + +exit: +#ifdef HAVE_ATFUNCS + if (sdir_fd != -1) + close(sdir_fd); +#endif + + return( rc ); +} + +int veto_file(const char*veto_str, const char*path) +/* given a veto_str like "abc/zxc/" and path "abc", return 1 + * veto_str should be '/' delimited + * if path matches any one of the veto_str elements exactly, then 1 is returned + * otherwise, 0 is returned. + */ +{ + int i; /* index to veto_str */ + int j; /* index to path */ + + if ((veto_str == NULL) || (path == NULL)) + return 0; + + for(i=0, j=0; veto_str[i] != '\0'; i++) { + if (veto_str[i] == '/') { + if ((j>0) && (path[j] == '\0')) { + LOG(log_debug, logtype_afpd, "vetoed file:'%s'", path); + return 1; + } + j = 0; + } else { + if (veto_str[i] != path[j]) { + while ((veto_str[i] != '/') + && (veto_str[i] != '\0')) + i++; + j = 0; + continue; + } + j++; + } + } + return 0; +} + diff --git a/etc/afpd/filedir.h b/etc/afpd/filedir.h new file mode 100644 index 0000000..f72e544 --- /dev/null +++ b/etc/afpd/filedir.h @@ -0,0 +1,27 @@ +#ifndef AFPD_FILEDIR_H +#define AFPD_FILEDIR_H 1 + +#include +#include +#include "volume.h" + +extern struct afp_options default_options; + +extern char *ctoupath (const struct vol *, struct dir *, + char *); +extern char *absupath (const struct vol *, struct dir *, + char *); +extern int veto_file (const char *veto_str, const char *path); +extern int check_name (const struct vol *vol, char *name); + +extern int matchfile2dirperms (char *, struct vol *, int); +extern int delete_vetoed_files(struct vol *vol, const char *upath, bool in_vetodir); + +/* FP functions */ +int afp_moveandrename (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_rename (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_delete (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getfildirparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setfildirparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +#endif diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c new file mode 100644 index 0000000..4311655 --- /dev/null +++ b/etc/afpd/fork.c @@ -0,0 +1,1347 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 2010 Frank Lahm + * + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fork.h" +#include "file.h" +#include "directory.h" +#include "desktop.h" +#include "volume.h" + +#ifdef AFS +struct ofork *writtenfork; +#endif + +static int getforkparams(const AFPObj *obj, struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen) +{ + struct path path; + struct stat *st; + + struct adouble *adp; + struct dir *dir; + struct vol *vol; + + + /* can only get the length of the opened fork */ + if ( ( (bitmap & ((1<of_flags & AFPFORK_RSRC)) + || + ( (bitmap & ((1<of_flags & AFPFORK_DATA))) { + return( AFPERR_BITMAP ); + } + + if (! AD_META_OPEN(ofork->of_ad)) { + adp = NULL; + } else { + adp = ofork->of_ad; + } + + vol = ofork->of_vol; + dir = dirlookup(vol, ofork->of_did); + + if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding(obj)))) { + return( AFPERR_MISC ); + } + path.m_name = of_name(ofork); + path.id = 0; + st = &path.st; + if ( bitmap & ( (1<of_ad ) <= 0 ) { + /* 0 is for symlink */ + if (movecwd(vol, dir) < 0) + return( AFPERR_NOOBJ ); + if ( lstat( path.u_name, st ) < 0 ) + return( AFPERR_NOOBJ ); + } else { + if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) { + return( AFPERR_BITMAP ); + } + } + } + return getmetadata(obj, vol, bitmap, &path, dir, buf, buflen, adp ); +} + +static off_t get_off_t(char **ibuf, int is64) +{ + uint32_t temp; + off_t ret; + + ret = 0; + memcpy(&temp, *ibuf, sizeof( temp )); + ret = ntohl(temp); /* ntohl is unsigned */ + *ibuf += sizeof(temp); + + if (is64) { + memcpy(&temp, *ibuf, sizeof( temp )); + *ibuf += sizeof(temp); + ret = ntohl(temp)| (ret << 32); + } + else { + ret = (int)ret; /* sign extend */ + } + return ret; +} + +static int set_off_t(off_t offset, char *rbuf, int is64) +{ + uint32_t temp; + int ret; + + ret = 0; + if (is64) { + temp = htonl(offset >> 32); + memcpy(rbuf, &temp, sizeof( temp )); + rbuf += sizeof(temp); + ret = sizeof( temp ); + offset &= 0xffffffff; + } + temp = htonl(offset); + memcpy(rbuf, &temp, sizeof( temp )); + ret += sizeof( temp ); + + return ret; +} + +static int is_neg(int is64, off_t val) +{ + if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U))) + return 1; + return 0; +} + +static int sum_neg(int is64, off_t offset, off_t reqcount) +{ + if (is_neg(is64, offset +reqcount) ) + return 1; + return 0; +} + +static int fork_setmode(const AFPObj *obj, struct adouble *adp, int eid, int access, int ofrefnum) +{ + int ret; + int readset; + int writeset; + int denyreadset; + int denywriteset; + + if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) { + return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum); + } + + if ((access & (OPENACC_RD | OPENACC_DRD))) { + if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0) + return readset; + if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0) + return denyreadset; + + if ((access & OPENACC_RD) && denyreadset) { + errno = EACCES; + return -1; + } + if ((access & OPENACC_DRD) && readset) { + errno = EACCES; + return -1; + } + /* boolean logic is not enough, because getforkmode is not always telling the + * true + */ + if ((access & OPENACC_RD)) { + ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum); + if (ret) + return ret; + } + if ((access & OPENACC_DRD)) { + ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum); + if (ret) + return ret; + } + } + /* ------------same for writing -------------- */ + if ((access & (OPENACC_WR | OPENACC_DWR))) { + if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0) + return writeset; + if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0) + return denywriteset; + + if ((access & OPENACC_WR) && denywriteset) { + errno = EACCES; + return -1; + } + if ((access & OPENACC_DWR) && writeset) { + errno = EACCES; + return -1; + } + if ((access & OPENACC_WR)) { + ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum); + if (ret) + return ret; + } + if ((access & OPENACC_DWR)) { + ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum); + if (ret) + return ret; + } + } + + /* + * Fix for Bug 560: put the Solaris share reservation after our locking stuff. + * Note that this still leaves room for a race condition where between placing our own + * locks above and putting the Solaris share move below another client puts a lock. + * We then end up with set locks from above and return with an error code, the proper + * fix requires a sane cleanup function for the error path in this function. + */ + +#ifdef HAVE_FSHARE_T + fshare_t shmd; + + if (obj->options.flags & OPTION_SHARE_RESERV) { + shmd.f_access = (access & OPENACC_RD ? F_RDACC : 0) | (access & OPENACC_WR ? F_WRACC : 0); + if (shmd.f_access == 0) + /* we must give an access mode, otherwise fcntl will complain */ + shmd.f_access = F_RDACC; + shmd.f_deny = (access & OPENACC_DRD ? F_RDDNY : F_NODNY) | (access & OPENACC_DWR) ? F_WRDNY : 0; + shmd.f_id = ofrefnum; + + int fd = (eid == ADEID_DFORK) ? ad_data_fileno(adp) : ad_reso_fileno(adp); + + if (fd != -1 && fd != AD_SYMLINK && fcntl(fd, F_SHARE, &shmd) != 0) { + LOG(log_debug, logtype_afpd, "fork_setmode: fcntl: %s", strerror(errno)); + errno = EACCES; + return -1; + } + } +#endif + + return 0; +} + +/* ----------------------- */ +int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + struct dir *dir; + struct ofork *ofork, *opened; + struct adouble *adsame = NULL; + size_t buflen; + int ret, adflags, eid; + uint32_t did; + uint16_t vid, bitmap, access, ofrefnum; + char fork, *path, *upath; + struct stat *st; + uint16_t bshort; + struct path *s_path; + + ibuf++; + fork = *ibuf++; + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof(vid); + + *rbuflen = 0; + if (NULL == ( vol = getvolbyvid( vid ))) { + return( AFPERR_PARAM ); + } + + memcpy(&did, ibuf, sizeof( did )); + ibuf += sizeof( int ); + + if (NULL == ( dir = dirlookup( vol, did ))) { + return afp_errno; + } + + memcpy(&bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + memcpy(&access, ibuf, sizeof( access )); + access = ntohs( access ); + ibuf += sizeof( access ); + + if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) { + return AFPERR_VLOCK; + } + + if (NULL == ( s_path = cname( vol, dir, &ibuf ))) { + return get_afp_errno(AFPERR_PARAM); + } + + if (*s_path->m_name == '\0') { + /* it's a dir ! */ + return AFPERR_BADTYPE; + } + + /* stat() data fork st is set because it's not a dir */ + switch ( s_path->st_errno ) { + case 0: + break; + case ENOENT: + return AFPERR_NOOBJ; + case EACCES: + return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS; + default: + LOG(log_error, logtype_afpd, "afp_openfork(%s): %s", s_path->m_name, strerror(errno)); + return AFPERR_PARAM; + } + + upath = s_path->u_name; + path = s_path->m_name; + st = &s_path->st; + + if (!vol_unix_priv(vol)) { + if (check_access(obj, vol, upath, access ) < 0) { + return AFPERR_ACCESS; + } + } else { + if (file_access(obj, vol, s_path, access ) < 0) { + return AFPERR_ACCESS; + } + } + + if ((opened = of_findname(vol, s_path))) { + adsame = opened->of_ad; + } + + adflags = ADFLAGS_SETSHRMD; + + if (fork == OPENFORK_DATA) { + eid = ADEID_DFORK; + adflags |= ADFLAGS_DF; + } else { + eid = ADEID_RFORK; + adflags |= ADFLAGS_RF; + } + + if (access & OPENACC_WR) { + adflags |= ADFLAGS_RDWR; + if (fork != OPENFORK_DATA) + /* + * We only try to create the resource + * fork if the user wants to open it for write acess. + */ + adflags |= ADFLAGS_CREATE; + } else { + adflags |= ADFLAGS_RDONLY; + } + + if ((ofork = of_alloc(vol, curdir, path, &ofrefnum, eid, adsame, st)) == NULL) + return AFPERR_NFILE; + + LOG(log_debug, logtype_afpd, "afp_openfork(\"%s\", %s, %s)", + fullpathname(s_path->u_name), + (fork == OPENFORK_DATA) ? "data" : "reso", + !(access & OPENACC_WR) ? "O_RDONLY" : "O_RDWR"); + + ret = AFPERR_NOOBJ; + + /* First ad_open(), opens data or ressource fork */ + if (ad_open(ofork->of_ad, upath, adflags, 0666) < 0) { + switch (errno) { + case EROFS: + ret = AFPERR_VLOCK; + case EACCES: + goto openfork_err; + case ENOENT: + goto openfork_err; + case EMFILE : + case ENFILE : + ret = AFPERR_NFILE; + goto openfork_err; + case EISDIR : + ret = AFPERR_BADTYPE; + goto openfork_err; + default: + LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) ); + ret = AFPERR_PARAM; + goto openfork_err; + } + } + + /* + * Create metadata if we open rw, otherwise only open existing metadata + */ + if (access & OPENACC_WR) { + adflags = ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE; + } else { + adflags = ADFLAGS_HF | ADFLAGS_RDONLY; + } + + if (ad_open(ofork->of_ad, upath, adflags, 0666) == 0) { + ofork->of_flags |= AFPFORK_META; + if (ad_get_MD_flags(ofork->of_ad) & O_CREAT) { + LOG(log_debug, logtype_afpd, "afp_openfork(\"%s\"): setting CNID", upath); + cnid_t id; + if ((id = get_id(vol, ofork->of_ad, st, dir->d_did, upath, strlen(upath))) == CNID_INVALID) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): CNID error", upath); + goto openfork_err; + } + (void)ad_setid(ofork->of_ad, st->st_dev, st->st_ino, id, dir->d_did, vol->v_stamp); + ad_flush(ofork->of_ad); + } + } else { + switch (errno) { + case EACCES: + case ENOENT: + /* no metadata? We don't care! */ + break; + case EROFS: + ret = AFPERR_VLOCK; + case EMFILE : + case ENFILE : + ret = AFPERR_NFILE; + goto openfork_err; + case EISDIR : + ret = AFPERR_BADTYPE; + goto openfork_err; + default: + LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) ); + ret = AFPERR_PARAM; + goto openfork_err; + } + } + + if ((adflags & ADFLAGS_RF) && (ad_get_RF_flags( ofork->of_ad) & O_CREAT)) { + if (ad_setname(ofork->of_ad, path)) { + ad_flush( ofork->of_ad ); + } + } + + if ((ret = getforkparams(obj, ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) { + ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD); + goto openfork_err; + } + + *rbuflen = buflen + 2 * sizeof( uint16_t ); + bitmap = htons( bitmap ); + memcpy(rbuf, &bitmap, sizeof( uint16_t )); + rbuf += sizeof( uint16_t ); + + /* check WriteInhibit bit if we have a ressource fork + * the test is done here, after some Mac trafic capture + */ + if (ad_meta_fileno(ofork->of_ad) != -1) { /* META */ + ad_getattr(ofork->of_ad, &bshort); + if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) { + ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD); + of_dealloc(ofork); + ofrefnum = 0; + memcpy(rbuf, &ofrefnum, sizeof(ofrefnum)); + return(AFPERR_OLOCK); + } + } + + /* + * synchronization locks: + */ + + /* don't try to lock non-existent rforks. */ + if ((eid == ADEID_DFORK) + || (ad_reso_fileno(ofork->of_ad) != -1) + || (ofork->of_ad->ad_vers == AD_VERSION_EA)) { + ret = fork_setmode(obj, ofork->of_ad, eid, access, ofrefnum); + /* can we access the fork? */ + if (ret < 0) { + ofork->of_flags |= AFPFORK_ERROR; + ret = errno; + ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD); + of_dealloc(ofork); + switch (ret) { + case EAGAIN: /* return data anyway */ + case EACCES: + case EINVAL: + ofrefnum = 0; + memcpy(rbuf, &ofrefnum, sizeof(ofrefnum)); + return( AFPERR_DENYCONF ); + break; + default: + *rbuflen = 0; + LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_lock: %s", s_path->m_name, strerror(ret) ); + return( AFPERR_PARAM ); + } + } + if ((access & OPENACC_WR)) + ofork->of_flags |= AFPFORK_ACCWR; + } + /* the file may be open read only without ressource fork */ + if ((access & OPENACC_RD)) + ofork->of_flags |= AFPFORK_ACCRD; + + LOG(log_debug, logtype_afpd, "afp_openfork(\"%s\"): fork: %" PRIu16, + fullpathname(s_path->m_name), ofork->of_refnum); + + memcpy(rbuf, &ofrefnum, sizeof(ofrefnum)); + return( AFP_OK ); + +openfork_err: + of_dealloc(ofork); + if (errno == EACCES) + return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS; + return ret; +} + +int afp_setforkparams(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen) +{ + struct ofork *ofork; + struct vol *vol; + struct dir *dir; + off_t size; + uint16_t ofrefnum, bitmap; + int err; + int is64; + int eid; + off_t st_size; + + ibuf += 2; + + memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); + ibuf += sizeof( ofrefnum ); + + memcpy(&bitmap, ibuf, sizeof(bitmap)); + bitmap = ntohs(bitmap); + ibuf += sizeof( bitmap ); + + *rbuflen = 0; + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afp_setforkparams: of_find(%d) could not locate fork", ofrefnum ); + return( AFPERR_PARAM ); + } + + vol = ofork->of_vol; + if ((dir = dirlookup(vol, ofork->of_did)) == NULL) { + LOG(log_error, logtype_afpd, "%s: bad fork did", of_name(ofork)); + return AFPERR_MISC; + } + if (movecwd(vol, dir) != 0) { + LOG(log_error, logtype_afpd, "%s: bad fork directory", dir->d_fullpath); + return AFPERR_MISC; + } + + if (ofork->of_vol->v_flags & AFPVOL_RO) + return AFPERR_VLOCK; + + if ((ofork->of_flags & AFPFORK_ACCWR) == 0) + return AFPERR_ACCESS; + + if ( ofork->of_flags & AFPFORK_DATA) { + eid = ADEID_DFORK; + } else if (ofork->of_flags & AFPFORK_RSRC) { + eid = ADEID_RFORK; + } else + return AFPERR_PARAM; + + if ( ( (bitmap & ( (1<afp_version >= 30) { + is64 = 4; + } + else + return AFPERR_BITMAP; + } + + if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4) + return AFPERR_PARAM ; + + size = get_off_t(&ibuf, is64); + + if (size < 0) + return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */ + + + if (bitmap == (1<of_ad, eid); + err = -2; + if (st_size > size && + ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) + goto afp_setfork_err; + + err = ad_dtruncate( ofork->of_ad, size ); + if (st_size > size) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum); + if (err < 0) + goto afp_setfork_err; + } else if (bitmap == (1<of_ad ); + + st_size = ad_size(ofork->of_ad, eid); + err = -2; + if (st_size > size && + ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) { + goto afp_setfork_err; + } + + err = ad_rtruncate(ofork->of_ad, mtoupath(ofork->of_vol, of_name(ofork), ofork->of_did, utf8_encoding(obj)), size); + if (st_size > size) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum); + if (err < 0) + goto afp_setfork_err; + + if (ad_flush( ofork->of_ad ) < 0) { + LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", of_name(ofork), strerror(errno) ); + return AFPERR_PARAM; + } + } else + return AFPERR_BITMAP; + +#ifdef AFS + if ( flushfork( ofork ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_setforkparams(%s): flushfork: %s", of_name(ofork), strerror(errno) ); + } +#endif /* AFS */ + + return( AFP_OK ); + +afp_setfork_err: + if (err == -2) + return AFPERR_LOCK; + else { + switch (errno) { + case EROFS: + return AFPERR_VLOCK; + case EPERM: + case EACCES: + return AFPERR_ACCESS; + case EDQUOT: + case EFBIG: + case ENOSPC: + LOG(log_error, logtype_afpd, "afp_setforkparams: DISK FULL"); + return AFPERR_DFULL; + default: + return AFPERR_PARAM; + } + } +} + +/* for this to work correctly, we need to check for locks before each + * read and write. that's most easily handled by always doing an + * appropriate check before each ad_read/ad_write. other things + * that can change files like truncate are handled internally to those + * functions. + */ +#define ENDBIT(a) ((a) & 0x80) +#define UNLOCKBIT(a) ((a) & 0x01) + + +/* ---------------------- */ +static int byte_lock(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64) +{ + struct ofork *ofork; + off_t offset, length; + int eid; + uint16_t ofrefnum; + uint8_t flags; + int lockop; + + *rbuflen = 0; + + /* figure out parameters */ + ibuf++; + flags = *ibuf; /* first bit = endflag, lastbit = lockflag */ + ibuf++; + memcpy(&ofrefnum, ibuf, sizeof(ofrefnum)); + ibuf += sizeof(ofrefnum); + + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "byte_lock: of_find(%d) could not locate fork", ofrefnum ); + return( AFPERR_PARAM ); + } + + if ( ofork->of_flags & AFPFORK_DATA) { + eid = ADEID_DFORK; + } else if (ofork->of_flags & AFPFORK_RSRC) { + eid = ADEID_RFORK; + } else + return AFPERR_PARAM; + + offset = get_off_t(&ibuf, is64); + length = get_off_t(&ibuf, is64); + + if (length == -1) + length = BYTELOCK_MAX; + else if (!length || is_neg(is64, length)) { + return AFPERR_PARAM; + } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/ + return AFPERR_LOCK; + } + + if (ENDBIT(flags)) { + offset += ad_size(ofork->of_ad, eid); + /* FIXME what do we do if file size > 2 GB and + it's not byte_lock_ext? + */ + } + if (offset < 0) /* error if we have a negative offset */ + return AFPERR_PARAM; + + /* if the file is a read-only file, we use read locks instead of + * write locks. that way, we can prevent anyone from initiating + * a write lock. */ + lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR; + if (ad_lock(ofork->of_ad, eid, lockop, offset, length, + ofork->of_refnum) < 0) { + switch (errno) { + case EACCES: + case EAGAIN: + return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK; + break; + case ENOLCK: + return AFPERR_NLOCK; + break; + case EINVAL: + return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR; + break; + case EBADF: + default: + return AFPERR_PARAM; + break; + } + } + *rbuflen = set_off_t (offset, rbuf, is64); + return( AFP_OK ); +} + +/* --------------------------- */ +int afp_bytelock(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0); +} + +/* --------------------------- */ +int afp_bytelock_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1); +} + +#undef UNLOCKBIT + +/*! + * Read *rbuflen bytes from fork at offset + * + * @param ofork (r) fork handle + * @param eid (r) data fork or ressource fork entry id + * @param offset (r) offset + * @param rbuf (r) data buffer + * @param rbuflen (rw) in: number of bytes to read, out: bytes read + * + * @return AFP status code + */ +static int read_file(const struct ofork *ofork, int eid, off_t offset, char *rbuf, size_t *rbuflen) +{ + ssize_t cc; + + cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen); + if ( cc < 0 ) { + LOG(log_error, logtype_afpd, "afp_read(%s): ad_read: %s", of_name(ofork), strerror(errno) ); + *rbuflen = 0; + return( AFPERR_PARAM ); + } + *rbuflen = cc; + + if ((size_t)cc < *rbuflen) + return AFPERR_EOF; + return AFP_OK; +} + +static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64) +{ + DSI *dsi = obj->dsi; + struct ofork *ofork; + off_t offset, saveoff, reqcount, savereqcount, size; + ssize_t cc, err; + int eid; + uint16_t ofrefnum; + + /* we break the AFP spec here by not supporting nlmask and nlchar anymore */ + + ibuf += 2; + memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); + ibuf += sizeof( u_short ); + + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afp_read: of_find(%d) could not locate fork", ofrefnum ); + err = AFPERR_PARAM; + goto afp_read_err; + } + + if ((ofork->of_flags & AFPFORK_ACCRD) == 0) { + err = AFPERR_ACCESS; + goto afp_read_err; + } + + if ( ofork->of_flags & AFPFORK_DATA) { + eid = ADEID_DFORK; + } else if (ofork->of_flags & AFPFORK_RSRC) { + eid = ADEID_RFORK; + } else { /* fork wasn't opened. this should never really happen. */ + err = AFPERR_ACCESS; + goto afp_read_err; + } + + offset = get_off_t(&ibuf, is64); + reqcount = get_off_t(&ibuf, is64); + + /* zero request count */ + err = AFP_OK; + if (!reqcount) { + goto afp_read_err; + } + + AFP_READ_START((long)reqcount); + + /* reqcount isn't always truthful. we need to deal with that. */ + size = ad_size(ofork->of_ad, eid); + + LOG(log_debug, logtype_afpd, + "afp_read(fork: %" PRIu16 " [%s], off: %" PRIu64 ", len: %" PRIu64 ", size: %" PRIu64 ")", + ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "reso", offset, reqcount, size); + + if (offset >= size) { + err = AFPERR_EOF; + goto afp_read_err; + } + + /* subtract off the offset */ + if (reqcount + offset > size) { + reqcount = size - offset; + err = AFPERR_EOF; + } + + savereqcount = reqcount; + saveoff = offset; + + if (reqcount < 0 || offset < 0) { + err = AFPERR_PARAM; + goto afp_read_err; + } + + if (obj->options.flags & OPTION_AFP_READ_LOCK) { + if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, offset, reqcount, ofork->of_refnum) < 0) { + err = AFPERR_LOCK; + goto afp_read_err; + } + } + +#ifdef WITH_SENDFILE + if (!(eid == ADEID_DFORK && ad_data_fileno(ofork->of_ad) == AD_SYMLINK) && + !(obj->options.flags & OPTION_NOSENDFILE)) { + int fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0); + if (dsi_stream_read_file(dsi, fd, offset, reqcount, err) < 0) { + LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", + of_name(ofork), strerror(errno)); + goto afp_read_exit; + } + goto afp_read_done; + } +#endif + + *rbuflen = MIN(reqcount, dsi->server_quantum); + + cc = read_file(ofork, eid, offset, ibuf, rbuflen); + if (cc < 0) { + err = cc; + goto afp_read_done; + } + + LOG(log_debug, logtype_afpd, + "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file", + of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen); + + offset += *rbuflen; + + /* + * dsi_readinit() returns size of next read buffer. by this point, + * we know that we're sending some data. if we fail, something + * horrible happened. + */ + if ((cc = dsi_readinit(dsi, ibuf, *rbuflen, reqcount, err)) < 0) + goto afp_read_exit; + *rbuflen = cc; + + while (*rbuflen > 0) { + /* + * This loop isn't really entered anymore, we've already + * sent the whole requested block in dsi_readinit(). + */ + cc = read_file(ofork, eid, offset, ibuf, rbuflen); + if (cc < 0) + goto afp_read_exit; + + offset += *rbuflen; + /* dsi_read() also returns buffer size of next allocation */ + cc = dsi_read(dsi, ibuf, *rbuflen); /* send it off */ + if (cc < 0) + goto afp_read_exit; + *rbuflen = cc; + } + dsi_readdone(dsi); + goto afp_read_done; + +afp_read_exit: + LOG(log_error, logtype_afpd, "afp_read(%s): %s", of_name(ofork), strerror(errno)); + dsi_readdone(dsi); + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount, ofork->of_refnum); + obj->exit(EXITERR_CLNT); + +afp_read_done: + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount, ofork->of_refnum); + + AFP_READ_DONE(); + return err; + +afp_read_err: + *rbuflen = 0; + return err; +} + +/* ---------------------- */ +int afp_read(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0); +} + +/* ---------------------- */ +int afp_read_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1); +} + +/* ---------------------- */ +int afp_flush(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&vid, ibuf, sizeof(vid)); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + of_flush(vol); + return( AFP_OK ); +} + +int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct ofork *ofork; + uint16_t ofrefnum; + + *rbuflen = 0; + ibuf += 2; + memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); + + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afp_flushfork: of_find(%d) could not locate fork", ofrefnum ); + return( AFPERR_PARAM ); + } + + LOG(log_debug, logtype_afpd, "afp_flushfork(fork: %s)", + (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); + + if ( flushfork( ofork ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) ); + } + + return( AFP_OK ); +} + +/* + FIXME + There is a lot to tell about fsync, fdatasync, F_FULLFSYNC. + fsync(2) on OSX is implemented differently than on other platforms. + see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf. +*/ +int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct ofork *ofork; + uint16_t ofrefnum; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&ofrefnum, ibuf, sizeof(ofrefnum)); + ibuf += sizeof( ofrefnum ); + + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afpd_syncfork: of_find(%d) could not locate fork", ofrefnum ); + return( AFPERR_PARAM ); + } + + LOG(log_debug, logtype_afpd, "afp_syncfork(fork: %s)", + (ofork->of_flags & AFPFORK_DATA) ? "d" : "r"); + + if ( flushfork( ofork ) < 0 ) { + LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) ); + return AFPERR_MISC; + } + + return( AFP_OK ); +} + +/* this is very similar to closefork */ +int flushfork(struct ofork *ofork) +{ + struct timeval tv; + + int err = 0, doflush = 0; + + if ( ad_data_fileno( ofork->of_ad ) != -1 && + fsync( ad_data_fileno( ofork->of_ad )) < 0 ) { + LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s", + of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) ); + err = -1; + } + + if ( ad_reso_fileno( ofork->of_ad ) != -1 && /* HF */ + (ofork->of_flags & AFPFORK_RSRC)) { + + /* read in the rfork length */ + ad_refresh(NULL, ofork->of_ad); + + /* set the date if we're dirty */ + if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) { + ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec); + ofork->of_flags &= ~AFPFORK_DIRTY; + doflush++; + } + + /* flush the header */ + if (doflush && ad_flush(ofork->of_ad) < 0) + err = -1; + + if (fsync( ad_reso_fileno( ofork->of_ad )) < 0) + err = -1; + + if (err < 0) + LOG(log_error, logtype_afpd, "flushfork(%s): hfile(%d) %s", + of_name(ofork), ad_reso_fileno(ofork->of_ad), strerror(errno) ); + } + + return( err ); +} + +int afp_closefork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct ofork *ofork; + uint16_t ofrefnum; + + *rbuflen = 0; + ibuf += 2; + memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); + + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum ); + return( AFPERR_PARAM ); + } + + LOG(log_debug, logtype_afpd, "afp_closefork(fork: %" PRIu16 " [%s])", + ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "rsrc"); + + if (of_closefork(obj, ofork) < 0 ) { + LOG(log_error, logtype_afpd, "afp_closefork: of_closefork: %s", strerror(errno) ); + return( AFPERR_PARAM ); + } + + return( AFP_OK ); +} + + +static ssize_t write_file(struct ofork *ofork, int eid, + off_t offset, char *rbuf, + size_t rbuflen) +{ + ssize_t cc; + + LOG(log_debug, logtype_afpd, "write_file(off: %ju, size: %zu)", + (uintmax_t)offset, rbuflen); + + if (( cc = ad_write(ofork->of_ad, eid, offset, 0, + rbuf, rbuflen)) < 0 ) { + switch ( errno ) { + case EDQUOT : + case EFBIG : + case ENOSPC : + LOG(log_error, logtype_afpd, "write_file: DISK FULL"); + return( AFPERR_DFULL ); + case EACCES: + return AFPERR_ACCESS; + default : + LOG(log_error, logtype_afpd, "afp_write(%s): ad_write: %s", of_name(ofork), strerror(errno) ); + return( AFPERR_PARAM ); + } + } + + return cc; +} + + +/* + * FPWrite. NOTE: on an error, we always use afp_write_err as + * the client may have sent us a bunch of data that's not reflected + * in reqcount et al. + */ +static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64) +{ + struct ofork *ofork; + off_t offset, saveoff, reqcount, oldsize, newsize; + int endflag, eid, err = AFP_OK; + uint16_t ofrefnum; + ssize_t cc; + DSI *dsi = obj->dsi; + char *rcvbuf = (char *)dsi->commands; + size_t rcvbuflen = dsi->server_quantum; + + /* figure out parameters */ + ibuf++; + endflag = ENDBIT(*ibuf); + ibuf++; + memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); + ibuf += sizeof( ofrefnum ); + + offset = get_off_t(&ibuf, is64); + reqcount = get_off_t(&ibuf, is64); + + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afp_write: of_find(%d) could not locate fork", ofrefnum ); + err = AFPERR_PARAM; + goto afp_write_err; + } + + LOG(log_debug, logtype_afpd, "afp_write(fork: %" PRIu16 " [%s], off: %" PRIu64 ", size: %" PRIu64 ")", + ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "reso", offset, reqcount); + + if ((ofork->of_flags & AFPFORK_ACCWR) == 0) { + err = AFPERR_ACCESS; + goto afp_write_err; + } + +#ifdef AFS + writtenfork = ofork; +#endif /* AFS */ + + if ( ofork->of_flags & AFPFORK_DATA) { + eid = ADEID_DFORK; + } else if (ofork->of_flags & AFPFORK_RSRC) { + eid = ADEID_RFORK; + } else { + err = AFPERR_ACCESS; /* should never happen */ + goto afp_write_err; + } + + oldsize = ad_size(ofork->of_ad, eid); + if (endflag) + offset += oldsize; + + /* handle bogus parameters */ + if (reqcount < 0 || offset < 0) { + err = AFPERR_PARAM; + goto afp_write_err; + } + + newsize = ((offset + reqcount) > oldsize) ? (offset + reqcount) : oldsize; + + /* offset can overflow on 64-bit capable filesystems. + * report disk full if that's going to happen. */ + if (sum_neg(is64, offset, reqcount)) { + LOG(log_error, logtype_afpd, "write_fork: DISK FULL"); + err = AFPERR_DFULL; + goto afp_write_err; + } + + if (!reqcount) { /* handle request counts of 0 */ + err = AFP_OK; + *rbuflen = set_off_t (offset, rbuf, is64); + goto afp_write_err; + } + + AFP_WRITE_START((long)reqcount); + + saveoff = offset; + if (obj->options.flags & OPTION_AFP_READ_LOCK) { + if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff, reqcount, ofork->of_refnum) < 0) { + err = AFPERR_LOCK; + goto afp_write_err; + } + } + + /* find out what we have already */ + if ((cc = dsi_writeinit(dsi, rcvbuf, rcvbuflen)) > 0) { + ssize_t written; + if ((written = write_file(ofork, eid, offset, rcvbuf, cc)) != cc) { + dsi_writeflush(dsi); + *rbuflen = 0; + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + if (written > 0) + /* It's used for the read size and as error code in write_file(), ugh */ + written = AFPERR_MISC; + return written; + } + } + + offset += cc; + +#ifdef WITH_RECVFILE + if (obj->options.flags & OPTION_RECVFILE) { + LOG(log_maxdebug, logtype_afpd, "afp_write(fork: %" PRIu16 " [%s], off: %" PRIu64 ", size: %" PRIu32 ")", + ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "reso", offset, dsi->datasize); + + if ((cc = ad_recvfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize, obj->options.splice_size)) < dsi->datasize) { + switch (errno) { + case EDQUOT: + case EFBIG: + case ENOSPC: + cc = AFPERR_DFULL; + dsi_writeflush(dsi); + break; + case ENOSYS: + goto afp_write_loop; + default: + /* Low level error, can't do much to back up */ + cc = AFPERR_MISC; + LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno)); + } + *rbuflen = 0; + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + return cc; + } + + offset += cc; + goto afp_write_done; + } +#endif + +afp_write_loop: + /* loop until everything gets written. currently + * dsi_write handles the end case by itself. */ + while ((cc = dsi_write(dsi, rcvbuf, rcvbuflen))) { + + if ((cc = write_file(ofork, eid, offset, rcvbuf, cc)) < 0) { + dsi_writeflush(dsi); + *rbuflen = 0; + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + return cc; + } + + LOG(log_debug, logtype_afpd, "afp_write: wrote: %jd, offset: %jd", + (intmax_t)cc, (intmax_t)offset); + + offset += cc; + } + +afp_write_done: + if (obj->options.flags & OPTION_AFP_READ_LOCK) + ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); + if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */ + ofork->of_flags |= AFPFORK_DIRTY; + + /* we have modified any fork, remember until close_fork */ + ofork->of_flags |= AFPFORK_MODIFIED; + + /* update write count */ + ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0; + + *rbuflen = set_off_t (offset, rbuf, is64); + AFP_WRITE_DONE(); + return( AFP_OK ); + +afp_write_err: + dsi_writeinit(dsi, rcvbuf, rcvbuflen); + dsi_writeflush(dsi); + + if (err != AFP_OK) { + *rbuflen = 0; + } + return err; +} + +/* ---------------------------- */ +int afp_write(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0); +} + +/* ---------------------------- + * FIXME need to deal with SIGXFSZ signal + */ +int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1); +} + +/* ---------------------------- */ +int afp_getforkparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct ofork *ofork; + int ret; + uint16_t ofrefnum, bitmap; + size_t buflen; + ibuf += 2; + memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); + ibuf += sizeof( ofrefnum ); + memcpy(&bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + + *rbuflen = 0; + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afp_getforkparams: of_find(%d) could not locate fork", ofrefnum ); + return( AFPERR_PARAM ); + } + + if (AD_META_OPEN(ofork->of_ad)) { + if ( ad_refresh(NULL, ofork->of_ad ) < 0 ) { + LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", of_name(ofork), strerror(errno) ); + return( AFPERR_PARAM ); + } + } + + if (AFP_OK != (ret = getforkparams(obj, ofork, bitmap, rbuf + sizeof( u_short ), &buflen ))) { + return( ret ); + } + + *rbuflen = buflen + sizeof( u_short ); + bitmap = htons( bitmap ); + memcpy(rbuf, &bitmap, sizeof( bitmap )); + return( AFP_OK ); +} + diff --git a/etc/afpd/fork.h b/etc/afpd/fork.h new file mode 100644 index 0000000..5b63601 --- /dev/null +++ b/etc/afpd/fork.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifndef AFPD_FORK_H +#define AFPD_FORK_H 1 + +#include +#include + +#include +#include "volume.h" +#include "directory.h" + +struct file_key { + dev_t dev; + ino_t inode; +}; + +struct ofork { + struct file_key key; + struct adouble *of_ad; + struct vol *of_vol; + cnid_t of_did; + uint16_t of_refnum; + int of_flags; + struct ofork **prevp, *next; +}; + +#define OPENFORK_DATA (0) +#define OPENFORK_RSCS (1<<7) + +#define OPENACC_RD (1<<0) +#define OPENACC_WR (1<<1) +#define OPENACC_DRD (1<<4) +#define OPENACC_DWR (1<<5) + +/* ofork.of_flags bits */ +#define AFPFORK_DATA (1<<0) /* open datafork */ +#define AFPFORK_RSRC (1<<1) /* open rsrcfork */ +#define AFPFORK_META (1<<2) /* open metadata */ +#define AFPFORK_DIRTY (1<<3) +#define AFPFORK_ACCRD (1<<4) +#define AFPFORK_ACCWR (1<<5) +#define AFPFORK_ACCMASK (AFPFORK_ACCRD | AFPFORK_ACCWR) +#define AFPFORK_MODIFIED (1<<6) /* used in FCE for modified files */ +#define AFPFORK_ERROR (1<<7) /* used to indicate an error in opening the fork */ + +#ifdef AFS +extern struct ofork *writtenfork; +#endif + +#define of_name(a) (a)->of_ad->ad_name +/* in ofork.c */ +extern struct ofork *of_alloc (struct vol *, struct dir *, + char *, uint16_t *, const int, + struct adouble *, + struct stat *); +extern void of_dealloc (struct ofork *); +extern struct ofork *of_find (const uint16_t); +extern struct ofork *of_findname (const struct vol *vol, struct path *); +extern int of_rename (const struct vol *, + struct ofork *, + struct dir *, const char *, + struct dir *, const char *); +extern int of_flush (const struct vol *); +extern int of_stat (const struct vol *vol, struct path *); +extern int of_statdir (struct vol *vol, struct path *); +extern int of_closefork (const AFPObj *obj, struct ofork *ofork); +extern void of_closevol (const AFPObj *obj, const struct vol *vol); +extern void of_close_all_forks(const AFPObj *obj); +extern struct adouble *of_ad (const struct vol *, struct path *, struct adouble *); + +#ifdef HAVE_ATFUNCS +extern struct ofork *of_findnameat(int dirfd, struct path *path); +extern int of_fstatat(int dirfd, struct path *path); +#endif /* HAVE_ATFUNCS */ + + +/* in fork.c */ +extern int flushfork (struct ofork *); + +/* FP functions */ +int afp_openfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_bytelock (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getforkparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setforkparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_read (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_write (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_flushfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_flush (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_closefork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +int afp_bytelock_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_read_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_write_ext (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_syncfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +#endif diff --git a/etc/afpd/hash.c b/etc/afpd/hash.c new file mode 100644 index 0000000..a7c624d --- /dev/null +++ b/etc/afpd/hash.c @@ -0,0 +1,1095 @@ +/* + * Hash Table Data Type + * Copyright (C) 1997 Kaz Kylheku + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Name: $ + */ +#define NDEBUG +#include +#include +#include +#include +#define HASH_IMPLEMENTATION +#include "hash.h" + +#ifdef KAZLIB_RCSID +#endif + +#define INIT_BITS 6 +#define INIT_SIZE (1UL << (INIT_BITS)) /* must be power of two */ +#define INIT_MASK ((INIT_SIZE) - 1) + +#define next hash_next +#define key hash_key +#define data hash_data +#define hkey hash_hkey + +#define table hash_table +#define nchains hash_nchains +#define nodecount hash_nodecount +#define maxcount hash_maxcount +#define highmark hash_highmark +#define lowmark hash_lowmark +#define compare hash_compare +#define function hash_function +#define allocnode hash_allocnode +#define freenode hash_freenode +#define context hash_context +#define mask hash_mask +#define dynamic hash_dynamic + +#define table hash_table +#define chain hash_chain + +static hnode_t *hnode_alloc(void *context); +static void hnode_free(hnode_t *node, void *context); +static hash_val_t hash_fun_default(const void *key); +static int hash_comp_default(const void *key1, const void *key2); + +int hash_val_t_bit; + +/* + * Compute the number of bits in the hash_val_t type. We know that hash_val_t + * is an unsigned integral type. Thus the highest value it can hold is a + * Mersenne number (power of two, less one). We initialize a hash_val_t + * object with this value and then shift bits out one by one while counting. + * Notes: + * 1. HASH_VAL_T_MAX is a Mersenne number---one that is one less than a power + * of two. This means that its binary representation consists of all one + * bits, and hence ``val'' is initialized to all one bits. + * 2. While bits remain in val, we increment the bit count and shift it to the + * right, replacing the topmost bit by zero. + */ + +static void compute_bits(void) +{ + hash_val_t val = HASH_VAL_T_MAX; /* 1 */ + int bits = 0; + + while (val) { /* 2 */ + bits++; + val >>= 1; + } + + hash_val_t_bit = bits; +} + +/* + * Verify whether the given argument is a power of two. + */ + +static int is_power_of_two(hash_val_t arg) +{ + if (arg == 0) + return 0; + while ((arg & 1) == 0) + arg >>= 1; + return (arg == 1); +} + +/* + * Compute a shift amount from a given table size + */ + +static hash_val_t compute_mask(hashcount_t size) +{ + assert (is_power_of_two(size)); + assert (size >= 2); + + return size - 1; +} + +/* + * Initialize the table of pointers to null. + */ + +static void clear_table(hash_t *hash) +{ + hash_val_t i; + + for (i = 0; i < hash->nchains; i++) + hash->table[i] = NULL; +} + +/* + * Double the size of a dynamic table. This works as follows. Each chain splits + * into two adjacent chains. The shift amount increases by one, exposing an + * additional bit of each hashed key. For each node in the original chain, the + * value of this newly exposed bit will decide which of the two new chains will + * receive the node: if the bit is 1, the chain with the higher index will have + * the node, otherwise the lower chain will receive the node. In this manner, + * the hash table will continue to function exactly as before without having to + * rehash any of the keys. + * Notes: + * 1. Overflow check. + * 2. The new number of chains is twice the old number of chains. + * 3. The new mask is one bit wider than the previous, revealing a + * new bit in all hashed keys. + * 4. Allocate a new table of chain pointers that is twice as large as the + * previous one. + * 5. If the reallocation was successful, we perform the rest of the growth + * algorithm, otherwise we do nothing. + * 6. The exposed_bit variable holds a mask with which each hashed key can be + * AND-ed to test the value of its newly exposed bit. + * 7. Now loop over each chain in the table and sort its nodes into two + * chains based on the value of each node's newly exposed hash bit. + * 8. The low chain replaces the current chain. The high chain goes + * into the corresponding sister chain in the upper half of the table. + * 9. We have finished dealing with the chains and nodes. We now update + * the various bookeeping fields of the hash structure. + */ + +static void grow_table(hash_t *hash) +{ + hnode_t **newtable; + + assert (2 * hash->nchains > hash->nchains); /* 1 */ + + newtable = realloc(hash->table, + sizeof *newtable * hash->nchains * 2); /* 4 */ + + if (newtable) { /* 5 */ + hash_val_t mask = (hash->mask << 1) | 1; /* 3 */ + hash_val_t exposed_bit = mask ^ hash->mask; /* 6 */ + hash_val_t chain; + + assert (mask != hash->mask); + + for (chain = 0; chain < hash->nchains; chain++) { /* 7 */ + hnode_t *low_chain = NULL, *high_chain = NULL, *hptr, *next; + + for (hptr = newtable[chain]; hptr != NULL; hptr = next) { + next = hptr->next; + + if (hptr->hkey & exposed_bit) { + hptr->next = high_chain; + high_chain = hptr; + } else { + hptr->next = low_chain; + low_chain = hptr; + } + } + + newtable[chain] = low_chain; /* 8 */ + newtable[chain + hash->nchains] = high_chain; + } + + hash->table = newtable; /* 9 */ + hash->mask = mask; + hash->nchains *= 2; + hash->lowmark *= 2; + hash->highmark *= 2; + } + assert (hash_verify(hash)); +} + +/* + * Cut a table size in half. This is done by folding together adjacent chains + * and populating the lower half of the table with these chains. The chains are + * simply spliced together. Once this is done, the whole table is reallocated + * to a smaller object. + * Notes: + * 1. It is illegal to have a hash table with one slot. This would mean that + * hash->shift is equal to hash_val_t_bit, an illegal shift value. + * Also, other things could go wrong, such as hash->lowmark becoming zero. + * 2. Looping over each pair of sister chains, the low_chain is set to + * point to the head node of the chain in the lower half of the table, + * and high_chain points to the head node of the sister in the upper half. + * 3. The intent here is to compute a pointer to the last node of the + * lower chain into the low_tail variable. If this chain is empty, + * low_tail ends up with a null value. + * 4. If the lower chain is not empty, we simply tack the upper chain onto it. + * If the upper chain is a null pointer, nothing happens. + * 5. Otherwise if the lower chain is empty but the upper one is not, + * If the low chain is empty, but the high chain is not, then the + * high chain is simply transferred to the lower half of the table. + * 6. Otherwise if both chains are empty, there is nothing to do. + * 7. All the chain pointers are in the lower half of the table now, so + * we reallocate it to a smaller object. This, of course, invalidates + * all pointer-to-pointers which reference into the table from the + * first node of each chain. + * 8. Though it's unlikely, the reallocation may fail. In this case we + * pretend that the table _was_ reallocated to a smaller object. + * 9. Finally, update the various table parameters to reflect the new size. + */ + +static void shrink_table(hash_t *hash) +{ + hash_val_t chain, nchains; + hnode_t **newtable, *low_tail, *low_chain, *high_chain; + + assert (hash->nchains >= 2); /* 1 */ + nchains = hash->nchains / 2; + + for (chain = 0; chain < nchains; chain++) { + low_chain = hash->table[chain]; /* 2 */ + high_chain = hash->table[chain + nchains]; + for (low_tail = low_chain; low_tail && low_tail->next; low_tail = low_tail->next) + ; /* 3 */ + if (low_chain != NULL) /* 4 */ + low_tail->next = high_chain; + else if (high_chain != NULL) /* 5 */ + hash->table[chain] = high_chain; + else + assert (hash->table[chain] == NULL); /* 6 */ + } + newtable = realloc(hash->table, + sizeof *newtable * nchains); /* 7 */ + if (newtable) /* 8 */ + hash->table = newtable; + hash->mask >>= 1; /* 9 */ + hash->nchains = nchains; + hash->lowmark /= 2; + hash->highmark /= 2; + assert (hash_verify(hash)); +} + + +/* + * Create a dynamic hash table. Both the hash table structure and the table + * itself are dynamically allocated. Furthermore, the table is extendible in + * that it will automatically grow as its load factor increases beyond a + * certain threshold. + * Notes: + * 1. If the number of bits in the hash_val_t type has not been computed yet, + * we do so here, because this is likely to be the first function that the + * user calls. + * 2. Allocate a hash table control structure. + * 3. If a hash table control structure is successfully allocated, we + * proceed to initialize it. Otherwise we return a null pointer. + * 4. We try to allocate the table of hash chains. + * 5. If we were able to allocate the hash chain table, we can finish + * initializing the hash structure and the table. Otherwise, we must + * backtrack by freeing the hash structure. + * 6. INIT_SIZE should be a power of two. The high and low marks are always set + * to be twice the table size and half the table size respectively. When the + * number of nodes in the table grows beyond the high size (beyond load + * factor 2), it will double in size to cut the load factor down to about + * about 1. If the table shrinks down to or beneath load factor 0.5, + * it will shrink, bringing the load up to about 1. However, the table + * will never shrink beneath INIT_SIZE even if it's emptied. + * 7. This indicates that the table is dynamically allocated and dynamically + * resized on the fly. A table that has this value set to zero is + * assumed to be statically allocated and will not be resized. + * 8. The table of chains must be properly reset to all null pointers. + */ + +hash_t *hash_create(hashcount_t maxcount, hash_comp_t compfun, + hash_fun_t hashfun) +{ + hash_t *hash; + + if (hash_val_t_bit == 0) /* 1 */ + compute_bits(); + + hash = malloc(sizeof *hash); /* 2 */ + + if (hash) { /* 3 */ + hash->table = malloc(sizeof *hash->table * INIT_SIZE); /* 4 */ + if (hash->table) { /* 5 */ + hash->nchains = INIT_SIZE; /* 6 */ + hash->highmark = INIT_SIZE * 2; + hash->lowmark = INIT_SIZE / 2; + hash->nodecount = 0; + hash->maxcount = maxcount; + hash->compare = compfun ? compfun : hash_comp_default; + hash->function = hashfun ? hashfun : hash_fun_default; + hash->allocnode = hnode_alloc; + hash->freenode = hnode_free; + hash->context = NULL; + hash->mask = INIT_MASK; + hash->dynamic = 1; /* 7 */ + clear_table(hash); /* 8 */ + assert (hash_verify(hash)); + return hash; + } + free(hash); + } + + return NULL; +} + +/* + * Select a different set of node allocator routines. + */ + +void hash_set_allocator(hash_t *hash, hnode_alloc_t al, + hnode_free_t fr, void *context) +{ + assert (hash_count(hash) == 0); + assert ((al == 0 && fr == 0) || (al != 0 && fr != 0)); + + hash->allocnode = al ? al : hnode_alloc; + hash->freenode = fr ? fr : hnode_free; + hash->context = context; +} + +/* + * Free every node in the hash using the hash->freenode() function pointer, and + * cause the hash to become empty. + */ + +void hash_free_nodes(hash_t *hash) +{ + hscan_t hs; + hnode_t *node; + hash_scan_begin(&hs, hash); + while ((node = hash_scan_next(&hs))) { + hash_scan_delete(hash, node); + hash->freenode(node, hash->context); + } + hash->nodecount = 0; + clear_table(hash); +} + +/* + * Obsolescent function for removing all nodes from a table, + * freeing them and then freeing the table all in one step. + */ + +void hash_free(hash_t *hash) +{ +#ifdef KAZLIB_OBSOLESCENT_DEBUG + assert ("call to obsolescent function hash_free()" && 0); +#endif + hash_free_nodes(hash); + hash_destroy(hash); +} + +/* + * Free a dynamic hash table structure. + */ + +void hash_destroy(hash_t *hash) +{ + assert (hash_val_t_bit != 0); + assert (hash_isempty(hash)); + free(hash->table); + free(hash); +} + +/* + * Initialize a user supplied hash structure. The user also supplies a table of + * chains which is assigned to the hash structure. The table is static---it + * will not grow or shrink. + * 1. See note 1. in hash_create(). + * 2. The user supplied array of pointers hopefully contains nchains nodes. + * 3. See note 7. in hash_create(). + * 4. We must dynamically compute the mask from the given power of two table + * size. + * 5. The user supplied table can't be assumed to contain null pointers, + * so we reset it here. + */ + +hash_t *hash_init(hash_t *hash, hashcount_t maxcount, + hash_comp_t compfun, hash_fun_t hashfun, hnode_t **table, + hashcount_t nchains) +{ + if (hash_val_t_bit == 0) /* 1 */ + compute_bits(); + + assert (is_power_of_two(nchains)); + + hash->table = table; /* 2 */ + hash->nchains = nchains; + hash->nodecount = 0; + hash->maxcount = maxcount; + hash->compare = compfun ? compfun : hash_comp_default; + hash->function = hashfun ? hashfun : hash_fun_default; + hash->dynamic = 0; /* 3 */ + hash->mask = compute_mask(nchains); /* 4 */ + clear_table(hash); /* 5 */ + + assert (hash_verify(hash)); + + return hash; +} + +/* + * Reset the hash scanner so that the next element retrieved by + * hash_scan_next() shall be the first element on the first non-empty chain. + * Notes: + * 1. Locate the first non empty chain. + * 2. If an empty chain is found, remember which one it is and set the next + * pointer to refer to its first element. + * 3. Otherwise if a chain is not found, set the next pointer to NULL + * so that hash_scan_next() shall indicate failure. + */ + +void hash_scan_begin(hscan_t *scan, hash_t *hash) +{ + hash_val_t nchains = hash->nchains; + hash_val_t chain; + + scan->table = hash; + + /* 1 */ + + for (chain = 0; chain < nchains && hash->table[chain] == NULL; chain++) + ; + + if (chain < nchains) { /* 2 */ + scan->chain = chain; + scan->next = hash->table[chain]; + } else { /* 3 */ + scan->next = NULL; + } +} + +/* + * Retrieve the next node from the hash table, and update the pointer + * for the next invocation of hash_scan_next(). + * Notes: + * 1. Remember the next pointer in a temporary value so that it can be + * returned. + * 2. This assertion essentially checks whether the module has been properly + * initialized. The first point of interaction with the module should be + * either hash_create() or hash_init(), both of which set hash_val_t_bit to + * a non zero value. + * 3. If the next pointer we are returning is not NULL, then the user is + * allowed to call hash_scan_next() again. We prepare the new next pointer + * for that call right now. That way the user is allowed to delete the node + * we are about to return, since we will no longer be needing it to locate + * the next node. + * 4. If there is a next node in the chain (next->next), then that becomes the + * new next node, otherwise ... + * 5. We have exhausted the current chain, and must locate the next subsequent + * non-empty chain in the table. + * 6. If a non-empty chain is found, the first element of that chain becomes + * the new next node. Otherwise there is no new next node and we set the + * pointer to NULL so that the next time hash_scan_next() is called, a null + * pointer shall be immediately returned. + */ + + +hnode_t *hash_scan_next(hscan_t *scan) +{ + hnode_t *next = scan->next; /* 1 */ + hash_t *hash = scan->table; + hash_val_t chain = scan->chain + 1; + hash_val_t nchains = hash->nchains; + + assert (hash_val_t_bit != 0); /* 2 */ + + if (next) { /* 3 */ + if (next->next) { /* 4 */ + scan->next = next->next; + } else { + while (chain < nchains && hash->table[chain] == NULL) /* 5 */ + chain++; + if (chain < nchains) { /* 6 */ + scan->chain = chain; + scan->next = hash->table[chain]; + } else { + scan->next = NULL; + } + } + } + return next; +} + +/* + * Insert a node into the hash table. + * Notes: + * 1. It's illegal to insert more than the maximum number of nodes. The client + * should verify that the hash table is not full before attempting an + * insertion. + * 2. The same key may not be inserted into a table twice. + * 3. If the table is dynamic and the load factor is already at >= 2, + * grow the table. + * 4. We take the bottom N bits of the hash value to derive the chain index, + * where N is the base 2 logarithm of the size of the hash table. + */ + +void hash_insert(hash_t *hash, hnode_t *node, const void *key) +{ + hash_val_t hkey, chain; + + assert (hash_val_t_bit != 0); + assert (node->next == NULL); + assert (hash->nodecount < hash->maxcount); /* 1 */ + assert (hash_lookup(hash, key) == NULL); /* 2 */ + + if (hash->dynamic && hash->nodecount >= hash->highmark) /* 3 */ + grow_table(hash); + + hkey = hash->function(key); + chain = hkey & hash->mask; /* 4 */ + + node->key = key; + node->hkey = hkey; + node->next = hash->table[chain]; + hash->table[chain] = node; + hash->nodecount++; + + assert (hash_verify(hash)); +} + +/* + * Find a node in the hash table and return a pointer to it. + * Notes: + * 1. We hash the key and keep the entire hash value. As an optimization, when + * we descend down the chain, we can compare hash values first and only if + * hash values match do we perform a full key comparison. + * 2. To locate the chain from among 2^N chains, we look at the lower N bits of + * the hash value by anding them with the current mask. + * 3. Looping through the chain, we compare the stored hash value inside each + * node against our computed hash. If they match, then we do a full + * comparison between the unhashed keys. If these match, we have located the + * entry. + */ + +hnode_t *hash_lookup(hash_t *hash, const void *key) +{ + hash_val_t hkey, chain; + hnode_t *nptr; + + hkey = hash->function(key); /* 1 */ + chain = hkey & hash->mask; /* 2 */ + + for (nptr = hash->table[chain]; nptr; nptr = nptr->next) { /* 3 */ + if (nptr->hkey == hkey && hash->compare(nptr->key, key) == 0) + return nptr; + } + + return NULL; +} + +/* + * Delete the given node from the hash table. Since the chains + * are singly linked, we must locate the start of the node's chain + * and traverse. + * Notes: + * 1. The node must belong to this hash table, and its key must not have + * been tampered with. + * 2. If this deletion will take the node count below the low mark, we + * shrink the table now. + * 3. Determine which chain the node belongs to, and fetch the pointer + * to the first node in this chain. + * 4. If the node being deleted is the first node in the chain, then + * simply update the chain head pointer. + * 5. Otherwise advance to the node's predecessor, and splice out + * by updating the predecessor's next pointer. + * 6. Indicate that the node is no longer in a hash table. + */ + +hnode_t *hash_delete(hash_t *hash, hnode_t *node) +{ + hash_val_t chain; + hnode_t *hptr; + + assert (hash_lookup(hash, node->key) == node); /* 1 */ + assert (hash_val_t_bit != 0); + + if (hash->dynamic && hash->nodecount <= hash->lowmark + && hash->nodecount > INIT_SIZE) + shrink_table(hash); /* 2 */ + + chain = node->hkey & hash->mask; /* 3 */ + hptr = hash->table[chain]; + + if (hptr == node) { /* 4 */ + hash->table[chain] = node->next; + } else { + while (hptr->next != node) { /* 5 */ + assert (hptr != 0); + hptr = hptr->next; + } + assert (hptr->next == node); + hptr->next = node->next; + } + + hash->nodecount--; + assert (hash_verify(hash)); + + node->next = NULL; /* 6 */ + return node; +} + +int hash_alloc_insert(hash_t *hash, const void *key, void *data) +{ + hnode_t *node = hash->allocnode(hash->context); + + if (node) { + hnode_init(node, data); + hash_insert(hash, node, key); + return 1; + } + return 0; +} + +void hash_delete_free(hash_t *hash, hnode_t *node) +{ + hash_delete(hash, node); + hash->freenode(node, hash->context); +} + +/* + * Exactly like hash_delete, except does not trigger table shrinkage. This is to be + * used from within a hash table scan operation. See notes for hash_delete. + */ + +hnode_t *hash_scan_delete(hash_t *hash, hnode_t *node) +{ + hash_val_t chain; + hnode_t *hptr; + + assert (hash_lookup(hash, node->key) == node); + assert (hash_val_t_bit != 0); + + chain = node->hkey & hash->mask; + hptr = hash->table[chain]; + + if (hptr == node) { + hash->table[chain] = node->next; + } else { + while (hptr->next != node) + hptr = hptr->next; + hptr->next = node->next; + } + + hash->nodecount--; + assert (hash_verify(hash)); + node->next = NULL; + + return node; +} + +/* + * Like hash_delete_free but based on hash_scan_delete. + */ + +void hash_scan_delfree(hash_t *hash, hnode_t *node) +{ + hash_scan_delete(hash, node); + hash->freenode(node, hash->context); +} + +/* + * Verify whether the given object is a valid hash table. This means + * Notes: + * 1. If the hash table is dynamic, verify whether the high and + * low expansion/shrinkage thresholds are powers of two. + * 2. Count all nodes in the table, and test each hash value + * to see whether it is correct for the node's chain. + */ + +int hash_verify(hash_t *hash) +{ + hashcount_t count = 0; + hash_val_t chain; + hnode_t *hptr; + + if (hash->dynamic) { /* 1 */ + if (hash->lowmark >= hash->highmark) + return 0; + if (!is_power_of_two(hash->highmark)) + return 0; + if (!is_power_of_two(hash->lowmark)) + return 0; + } + + for (chain = 0; chain < hash->nchains; chain++) { /* 2 */ + for (hptr = hash->table[chain]; hptr != NULL; hptr = hptr->next) { + if ((hptr->hkey & hash->mask) != chain) + return 0; + count++; + } + } + + if (count != hash->nodecount) + return 0; + + return 1; +} + +/* + * Test whether the hash table is full and return 1 if this is true, + * 0 if it is false. + */ + +#undef hash_isfull +int hash_isfull(hash_t *hash) +{ + return hash->nodecount == hash->maxcount; +} + +/* + * Test whether the hash table is empty and return 1 if this is true, + * 0 if it is false. + */ + +#undef hash_isempty +int hash_isempty(hash_t *hash) +{ + return hash->nodecount == 0; +} + +static hnode_t *hnode_alloc(void *context _U_) +{ + return malloc(sizeof *hnode_alloc(NULL)); +} + +static void hnode_free(hnode_t *node, void *context _U_) +{ + free(node); +} + + +/* + * Create a hash table node dynamically and assign it the given data. + */ + +hnode_t *hnode_create(void *data) +{ + hnode_t *node = malloc(sizeof *node); + if (node) { + node->data = data; + node->next = NULL; + } + return node; +} + +/* + * Initialize a client-supplied node + */ + +hnode_t *hnode_init(hnode_t *hnode, void *data) +{ + hnode->data = data; + hnode->next = NULL; + return hnode; +} + +/* + * Destroy a dynamically allocated node. + */ + +void hnode_destroy(hnode_t *hnode) +{ + free(hnode); +} + +#undef hnode_put +void hnode_put(hnode_t *node, void *data) +{ + node->data = data; +} + +#undef hnode_get +void *hnode_get(hnode_t *node) +{ + return node->data; +} + +#undef hnode_getkey +const void *hnode_getkey(hnode_t *node) +{ + return node->key; +} + +#undef hash_count +hashcount_t hash_count(hash_t *hash) +{ + return hash->nodecount; +} + +#undef hash_size +hashcount_t hash_size(hash_t *hash) +{ + return hash->nchains; +} + +static hash_val_t hash_fun_default(const void *key) +{ + static unsigned long randbox[] = { + 0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U, + 0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU, + 0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU, + 0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU, + }; + + const unsigned char *str = key; + hash_val_t acc = 0; + + while (*str) { + acc ^= randbox[(*str + acc) & 0xf]; + acc = (acc << 1) | (acc >> 31); + acc &= 0xffffffffU; + acc ^= randbox[((*str++ >> 4) + acc) & 0xf]; + acc = (acc << 2) | (acc >> 30); + acc &= 0xffffffffU; + } + return acc; +} + +/* From http://www.azillionmonkeys.com/qed/hash.html */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif + +static int hash_comp_default(const void *key1, const void *key2) +{ + return strcmp(key1, key2); +} + +#ifdef KAZLIB_TEST_MAIN + +static hash_val_t hash_fun2(const void *key) +{ + int len, rem; + const unsigned char *data = key; + hash_val_t hash = 0, tmp = 0; + + len = strlen((char *)data); + + rem = len & 3; + len >>= 2; + + /* Main loop */ + for (;len > 0; len--) { + hash += get16bits (data); + tmp = (get16bits (data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2*sizeof (uint16_t); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) { + case 3: hash += get16bits (data); + hash ^= hash << 16; + hash ^= data[sizeof (uint16_t)] << 18; + hash += hash >> 11; + break; + case 2: hash += get16bits (data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += *data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; +} + +#include +#include +#include + +typedef char input_t[256]; + +static int tokenize(char *string, ...) +{ + char **tokptr; + va_list arglist; + int tokcount = 0; + + va_start(arglist, string); + tokptr = va_arg(arglist, char **); + while (tokptr) { + while (*string && isspace((unsigned char) *string)) + string++; + if (!*string) + break; + *tokptr = string; + while (*string && !isspace((unsigned char) *string)) + string++; + tokptr = va_arg(arglist, char **); + tokcount++; + if (!*string) + break; + *string++ = 0; + } + va_end(arglist); + + return tokcount; +} + +static char *dupstring(char *str) +{ + int sz = strlen(str) + 1; + char *new = malloc(sz); + if (new) + memcpy(new, str, sz); + return new; +} + +static hnode_t *new_node(void *c) +{ + static hnode_t few[5]; + static int count; + + if (count < 5) + return few + count++; + + return NULL; +} + +static void del_node(hnode_t *n, void *c) +{ +} + +int main(void) +{ + input_t in; + hash_t *h = hash_create(HASHCOUNT_T_MAX, 0, hash_fun2); + hnode_t *hn; + hscan_t hs; + char *tok1, *tok2, *val; + const char *key; + int prompt = 0; + + char *help = + "a add value to hash table\n" + "d delete value from hash table\n" + "l lookup value in hash table\n" + "n show size of hash table\n" + "c show number of entries\n" + "t dump whole hash table\n" + "+ increase hash table (private func)\n" + "- decrease hash table (private func)\n" + "b print hash_t_bit value\n" + "p turn prompt on\n" + "s switch to non-functioning allocator\n" + "q quit"; + + if (!h) { + puts("hash_create failed"); + return 1; + } + + for (;;) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; + + switch(in[0]) { + case '?': + puts(help); + break; + case 'b': + printf("%d\n", hash_val_t_bit); + break; + case 'a': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + + if (!key || !val) { + puts("out of memory"); + free((void *) key); + free(val); + break; + } + + if (!hash_alloc_insert(h, key, val)) { + puts("hash_alloc_insert failed"); + free((void *) key); + free(val); + break; + } + break; + case 'd': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + hn = hash_lookup(h, tok1); + if (!hn) { + puts("hash_lookup failed"); + break; + } + val = hnode_get(hn); + key = hnode_getkey(hn); + hash_scan_delfree(h, hn); + free((void *) key); + free(val); + break; + case 'l': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + hn = hash_lookup(h, tok1); + if (!hn) { + puts("hash_lookup failed"); + break; + } + val = hnode_get(hn); + puts(val); + break; + case 'n': + printf("%lu\n", (unsigned long) hash_size(h)); + break; + case 'c': + printf("%lu\n", (unsigned long) hash_count(h)); + break; + case 't': + hash_scan_begin(&hs, h); + while ((hn = hash_scan_next(&hs))) + printf("%s\t%s\n", (char*) hnode_getkey(hn), + (char*) hnode_get(hn)); + break; + case '+': + grow_table(h); /* private function */ + break; + case '-': + shrink_table(h); /* private function */ + break; + case 'q': + exit(0); + break; + case '\0': + break; + case 'p': + prompt = 1; + break; + case 's': + hash_set_allocator(h, new_node, del_node, NULL); + break; + default: + putchar('?'); + putchar('\n'); + break; + } + } + + return 0; +} + +#endif diff --git a/etc/afpd/hash.h b/etc/afpd/hash.h new file mode 100644 index 0000000..886344e --- /dev/null +++ b/etc/afpd/hash.h @@ -0,0 +1,73 @@ +/* + * Hash Table Data Type + * Copyright (C) 1997 Kaz Kylheku + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Name: $ + */ + +#ifndef HASH_H +#define HASH_H + +#include +#include + +extern hash_t *hash_create(hashcount_t, hash_comp_t, hash_fun_t); +extern void hash_set_allocator(hash_t *, hnode_alloc_t, hnode_free_t, void *); +extern void hash_destroy(hash_t *); +extern void hash_free_nodes(hash_t *); +extern void hash_free(hash_t *); +extern hash_t *hash_init(hash_t *, hashcount_t, hash_comp_t, + hash_fun_t, hnode_t **, hashcount_t); +extern void hash_insert(hash_t *, hnode_t *, const void *); +extern hnode_t *hash_lookup(hash_t *, const void *); +extern hnode_t *hash_delete(hash_t *, hnode_t *); +extern int hash_alloc_insert(hash_t *, const void *, void *); +extern void hash_delete_free(hash_t *, hnode_t *); + +extern void hnode_put(hnode_t *, void *); +extern void *hnode_get(hnode_t *); +extern const void *hnode_getkey(hnode_t *); +extern hashcount_t hash_count(hash_t *); +extern hashcount_t hash_size(hash_t *); + +extern int hash_isfull(hash_t *); +extern int hash_isempty(hash_t *); + +extern void hash_scan_begin(hscan_t *, hash_t *); +extern hnode_t *hash_scan_next(hscan_t *); +extern hnode_t *hash_scan_delete(hash_t *, hnode_t *); +extern void hash_scan_delfree(hash_t *, hnode_t *); + +extern int hash_verify(hash_t *); + +extern hnode_t *hnode_create(void *); +extern hnode_t *hnode_init(hnode_t *, void *); +extern void hnode_destroy(hnode_t *); + +#if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) +#ifdef KAZLIB_SIDEEFFECT_DEBUG +#define hash_isfull(H) (SFX_CHECK(H)->hash_nodecount == (H)->hash_maxcount) +#else +#define hash_isfull(H) ((H)->hash_nodecount == (H)->hash_maxcount) +#endif +#define hash_isempty(H) ((H)->hash_nodecount == 0) +#define hash_count(H) ((H)->hash_nodecount) +#define hash_size(H) ((H)->hash_nchains) +#define hnode_get(N) ((N)->hash_data) +#define hnode_getkey(N) ((N)->hash_key) +#define hnode_put(N, V) ((N)->hash_data = (V)) +#endif + +#endif diff --git a/etc/afpd/icon.h b/etc/afpd/icon.h new file mode 100644 index 0000000..8d3bc93 --- /dev/null +++ b/etc/afpd/icon.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1990,1994 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifndef AFPD_ICON_H +#define AFPD_ICON_H 1 + +#include + +static const unsigned char icon[] = { /* daemon */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x2, 0x0, + 0x1, 0x80, 0x3, 0x0, 0x2, 0x80, 0x2, 0x80, + 0x2, 0x80, 0x2, 0x80, 0x4, 0x80, 0x2, 0x40, + 0x4, 0x87, 0xC2, 0x40, 0x4, 0x58, 0x34, 0x40, + 0x4, 0x20, 0x8, 0x40, 0x2, 0x16, 0xD0, 0x80, + 0x1, 0x1, 0x1, 0x0, 0x2, 0x80, 0x2, 0x80, + 0x2, 0x9C, 0x72, 0x80, 0x4, 0x22, 0x88, 0x40, + 0x4, 0x41, 0x4, 0x40, 0x4, 0x41, 0x4, 0x40, + 0x4, 0x41, 0x4, 0x40, 0x4, 0x49, 0x24, 0x40, + 0xE, 0x55, 0x54, 0xE0, 0x10, 0x5D, 0x74, 0x10, + 0x10, 0x3E, 0xF8, 0x10, 0x7F, 0xFC, 0x7F, 0xFE, + 0x20, 0x4, 0x40, 0x4, 0x1F, 0xFC, 0x7F, 0xF8, + 0x0, 0x7, 0xC0, 0x0, 0x0, 0x4, 0x40, 0x0, + 0x0, 0x3, 0x80, 0x0, 0x0, 0x4, 0x40, 0x0, + 0xAF, 0xF9, 0x3F, 0xF5, 0x0, 0x2, 0x80, 0x0, + 0xAF, 0xFC, 0x7F, 0xF5, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x2, 0x0, + 0x1, 0x80, 0x3, 0x0, 0x3, 0x80, 0x3, 0x80, + 0x3, 0x80, 0x3, 0x80, 0x7, 0x80, 0x3, 0xC0, + 0x7, 0x87, 0xC3, 0xC0, 0x7, 0xDF, 0xF7, 0xC0, + 0x7, 0xFF, 0xFF, 0xC0, 0x3, 0xFF, 0xFF, 0x80, + 0x1, 0xFF, 0xFF, 0x0, 0x3, 0xFF, 0xFF, 0x80, + 0x3, 0xFF, 0xFF, 0x80, 0x7, 0xFF, 0xFF, 0xC0, + 0x7, 0xFF, 0xFF, 0xC0, 0x7, 0xFF, 0xFF, 0xC0, + 0x7, 0xFF, 0xFF, 0xC0, 0x7, 0xFF, 0xFF, 0xC0, + 0xF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xF0, + 0x1F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xFE, + 0x3F, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xF8, + 0x0, 0x7, 0xC0, 0x0, 0x0, 0x7, 0xC0, 0x0, + 0x0, 0x3, 0x80, 0x0, 0x0, 0x4, 0x40, 0x0, + 0xAF, 0xF9, 0x3F, 0xF5, 0x0, 0x2, 0x80, 0x0, + 0xAF, 0xFC, 0x7F, 0xF5, 0x0, 0x0, 0x0, 0x0 +}; + +#endif diff --git a/etc/afpd/main.c b/etc/afpd/main.c new file mode 100644 index 0000000..51c588f --- /dev/null +++ b/etc/afpd/main.c @@ -0,0 +1,479 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "afp_config.h" +#include "status.h" +#include "fork.h" +#include "uam_auth.h" +#include "afpstats.h" + +#define ASEV_THRESHHOLD 10 + +unsigned char nologin = 0; + +static AFPObj obj; +static server_child_t *server_children; +static sig_atomic_t reloadconfig = 0; +static sig_atomic_t gotsigchld = 0; +static struct asev *asev; + +static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child_t *server_children); + +static void afp_exit(int ret) +{ + exit(ret); +} + + +/* ------------------ + initialize fd set we are waiting for. +*/ +static bool init_listening_sockets(const AFPObj *config) +{ + DSI *dsi; + int numlisteners; + + for (numlisteners = 0, dsi = config->dsi; dsi; dsi = dsi->next) { + numlisteners++; + } + + asev = asev_init(config->options.connections + numlisteners + ASEV_THRESHHOLD); + if (asev == NULL) { + return false; + } + + for (dsi = config->dsi; dsi; dsi = dsi->next) { + if (!(asev_add_fd(asev, dsi->serversock, LISTEN_FD, dsi))) { + return false; + } + } + + return true; +} + +static bool reset_listening_sockets(const AFPObj *config) +{ + const DSI *dsi; + + for (dsi = config->dsi; dsi; dsi = dsi->next) { + if (!(asev_del_fd(asev, dsi->serversock))) { + return false; + } + } + return true; +} + +/* ------------------ */ +static void afp_goaway(int sig) +{ + switch( sig ) { + + case SIGTERM: + case SIGQUIT: + LOG(log_note, logtype_afpd, "AFP Server shutting down"); + if (server_children) + server_child_kill(server_children, SIGTERM); + _exit(0); + break; + + case SIGUSR1 : + nologin++; + auth_unload(); + LOG(log_info, logtype_afpd, "disallowing logins"); + + if (server_children) + server_child_kill(server_children, sig); + break; + + case SIGHUP : + /* w/ a configuration file, we can force a re-read if we want */ + reloadconfig = 1; + break; + + case SIGCHLD: + /* w/ a configuration file, we can force a re-read if we want */ + gotsigchld = 1; + break; + + default : + LOG(log_error, logtype_afpd, "afp_goaway: bad signal" ); + } + return; +} + +static void child_handler(void) +{ + int fd; + int status; + pid_t pid; + +#ifndef WAIT_ANY +#define WAIT_ANY (-1) +#endif /* ! WAIT_ANY */ + + while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status)) + LOG(log_info, logtype_afpd, "child[%d]: exited %d", pid, WEXITSTATUS(status)); + else + LOG(log_info, logtype_afpd, "child[%d]: done", pid); + } else { + if (WIFSIGNALED(status)) + LOG(log_info, logtype_afpd, "child[%d]: killed by signal %d", pid, WTERMSIG(status)); + else + LOG(log_info, logtype_afpd, "child[%d]: died", pid); + } + + fd = server_child_remove(server_children, pid); + if (fd == -1) { + continue; + } + if (!(asev_del_fd(asev, fd))) { + LOG(log_error, logtype_afpd, "child[%d]: asev_del_fd: %d", pid, fd); + } + } +} + +static int setlimits(void) +{ + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { + LOG(log_warning, logtype_afpd, "setlimits: reading current limits failed: %s", strerror(errno)); + return -1; + } + if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < 65535) { + rlim.rlim_cur = 65535; + if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < 65535) + rlim.rlim_max = 65535; + if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { + LOG(log_warning, logtype_afpd, "setlimits: increasing limits failed: %s", strerror(errno)); + return -1; + } + } + return 0; +} + +int main(int ac, char **av) +{ + struct sigaction sv; + sigset_t sigs; + int ret; + + /* Parse argv args and initialize default options */ + afp_options_parse_cmdline(&obj, ac, av); + + if (!(obj.cmdlineflags & OPTION_DEBUG) && (daemonize(0, 0) != 0)) + exit(EXITERR_SYS); + + /* Log SIGBUS/SIGSEGV SBT */ + fault_setup(NULL); + + if (afp_config_parse(&obj, "afpd") != 0) + afp_exit(EXITERR_CONF); + + /* Save the user's current umask */ + obj.options.save_mask = umask(obj.options.umask); + + /* install child handler for asp and dsi. we do this before afp_goaway + * as afp_goaway references stuff from here. + * XXX: this should really be setup after the initial connections. */ + if (!(server_children = server_child_alloc(obj.options.connections))) { + LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } + + sigemptyset(&sigs); + pthread_sigmask(SIG_SETMASK, &sigs, NULL); + + memset(&sv, 0, sizeof(sv)); + /* linux at least up to 2.4.22 send a SIGXFZ for vfat fs, + even if the file is open with O_LARGEFILE ! */ +#ifdef SIGXFSZ + sv.sa_handler = SIG_IGN; + sigemptyset( &sv.sa_mask ); + if (sigaction(SIGXFSZ, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } +#endif + + sv.sa_handler = SIG_IGN; + sigemptyset( &sv.sa_mask ); + if (sigaction(SIGPIPE, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } + + sv.sa_handler = afp_goaway; /* handler for all sigs */ + + sigemptyset( &sv.sa_mask ); + sigaddset(&sv.sa_mask, SIGALRM); + sigaddset(&sv.sa_mask, SIGHUP); + sigaddset(&sv.sa_mask, SIGTERM); + sigaddset(&sv.sa_mask, SIGUSR1); + sigaddset(&sv.sa_mask, SIGQUIT); + sv.sa_flags = SA_RESTART; + if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } + + sigemptyset( &sv.sa_mask ); + sigaddset(&sv.sa_mask, SIGALRM); + sigaddset(&sv.sa_mask, SIGTERM); + sigaddset(&sv.sa_mask, SIGHUP); + sigaddset(&sv.sa_mask, SIGCHLD); + sigaddset(&sv.sa_mask, SIGQUIT); + sv.sa_flags = SA_RESTART; + if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } + + sigemptyset( &sv.sa_mask ); + sigaddset(&sv.sa_mask, SIGALRM); + sigaddset(&sv.sa_mask, SIGTERM); + sigaddset(&sv.sa_mask, SIGUSR1); + sigaddset(&sv.sa_mask, SIGCHLD); + sigaddset(&sv.sa_mask, SIGQUIT); + sv.sa_flags = SA_RESTART; + if ( sigaction( SIGHUP, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } + + sigemptyset( &sv.sa_mask ); + sigaddset(&sv.sa_mask, SIGALRM); + sigaddset(&sv.sa_mask, SIGHUP); + sigaddset(&sv.sa_mask, SIGUSR1); + sigaddset(&sv.sa_mask, SIGCHLD); + sigaddset(&sv.sa_mask, SIGQUIT); + sv.sa_flags = SA_RESTART; + if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } + + sigemptyset( &sv.sa_mask ); + sigaddset(&sv.sa_mask, SIGALRM); + sigaddset(&sv.sa_mask, SIGHUP); + sigaddset(&sv.sa_mask, SIGUSR1); + sigaddset(&sv.sa_mask, SIGCHLD); + sigaddset(&sv.sa_mask, SIGTERM); + sv.sa_flags = SA_RESTART; + if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) ); + afp_exit(EXITERR_SYS); + } + + /* afp.conf: not in config file: lockfile, configfile + * preference: command-line provides defaults. + * config file over-writes defaults. + * + * we also need to make sure that killing afpd during startup + * won't leave any lingering registered names around. + */ + + sigemptyset(&sigs); + sigaddset(&sigs, SIGALRM); + sigaddset(&sigs, SIGHUP); + sigaddset(&sigs, SIGUSR1); +#if 0 + /* don't block SIGTERM */ + sigaddset(&sigs, SIGTERM); +#endif + sigaddset(&sigs, SIGCHLD); + + pthread_sigmask(SIG_BLOCK, &sigs, NULL); +#ifdef HAVE_DBUS_GLIB + /* Run dbus AFP statics thread */ + if (obj.options.flags & OPTION_DBUS_AFPSTATS) + (void)afpstats_init(server_children); +#endif + if (configinit(&obj) != 0) { + LOG(log_error, logtype_afpd, "main: no servers configured"); + afp_exit(EXITERR_CONF); + } + pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); + + /* Initialize */ + cnid_init(); + + /* watch atp, dsi sockets and ipc parent/child file descriptor. */ + if (!(init_listening_sockets(&obj))) { + LOG(log_error, logtype_afpd, "main: couldn't initialize socket handler"); + afp_exit(EXITERR_CONF); + } + + /* set limits */ + (void)setlimits(); + + afp_child_t *child; + int saveerrno; + + /* wait for an appleshare connection. parent remains in the loop + * while the children get handled by afp_over_{asp,dsi}. this is + * currently vulnerable to a denial-of-service attack if a + * connection is made without an actual login attempt being made + * afterwards. establishing timeouts for logins is a possible + * solution. */ + while (1) { + pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); + ret = poll(asev->fdset, asev->used, -1); + pthread_sigmask(SIG_BLOCK, &sigs, NULL); + saveerrno = errno; + + if (gotsigchld) { + gotsigchld = 0; + child_handler(); + continue; + } + + if (reloadconfig) { + nologin++; + + if (!(reset_listening_sockets(&obj))) { + LOG(log_error, logtype_afpd, "main: reset socket handlers"); + afp_exit(EXITERR_CONF); + } + + LOG(log_info, logtype_afpd, "re-reading configuration file"); + + configfree(&obj, NULL); + afp_config_free(&obj); + + if (afp_config_parse(&obj, "afpd") != 0) + afp_exit(EXITERR_CONF); + + if (configinit(&obj) != 0) { + LOG(log_error, logtype_afpd, "config re-read: no servers configured"); + afp_exit(EXITERR_CONF); + } + + if (!(init_listening_sockets(&obj))) { + LOG(log_error, logtype_afpd, "main: couldn't initialize socket handler"); + afp_exit(EXITERR_CONF); + } + + nologin = 0; + reloadconfig = 0; + errno = saveerrno; + + if (server_children) { + server_child_kill(server_children, SIGHUP); + } + + continue; + } + + if (ret == 0) + continue; + + if (ret < 0) { + if (errno == EINTR) + continue; + LOG(log_error, logtype_afpd, "main: can't wait for input: %s", strerror(errno)); + break; + } + + for (int i = 0; i < asev->used; i++) { + if (asev->fdset[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) { + switch (asev->data[i].fdtype) { + + case LISTEN_FD: + if ((child = dsi_start(&obj, (DSI *)(asev->data[i].private), server_children))) { + if (!(asev_add_fd(asev, child->afpch_ipc_fd, IPC_FD, child))) { + LOG(log_error, logtype_afpd, "out of asev slots"); + + /* + * Close IPC fd here and mark it as unused + */ + close(child->afpch_ipc_fd); + child->afpch_ipc_fd = -1; + + /* + * Being unfriendly here, but we really + * want to get rid of it. The 'child' + * handle gets cleaned up in the SIGCLD + * handler. + */ + kill(child->afpch_pid, SIGKILL); + } + } + break; + + case IPC_FD: + child = (afp_child_t *)(asev->data[i].private); + LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->afpch_pid); + + if (ipc_server_read(server_children, child->afpch_ipc_fd) != 0) { + if (!(asev_del_fd(asev, child->afpch_ipc_fd))) { + LOG(log_error, logtype_afpd, "child[%u]: no IPC fd"); + } + close(child->afpch_ipc_fd); + child->afpch_ipc_fd = -1; + } + break; + + default: + LOG(log_debug, logtype_afpd, "main: IPC request for unknown type"); + break; + } /* switch */ + } /* if */ + } /* for (i)*/ + } /* while (1) */ + + return 0; +} + +static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child_t *server_children) +{ + afp_child_t *child = NULL; + + if (dsi_getsession(dsi, server_children, obj->options.tickleval, &child) != 0) { + LOG(log_error, logtype_afpd, "dsi_start: session error: %s", strerror(errno)); + return NULL; + } + + /* we've forked. */ + if (child == NULL) { + configfree(obj, dsi); + afp_over_dsi(obj); /* start a session */ + exit (0); + } + + return child; +} diff --git a/etc/afpd/mangle.c b/etc/afpd/mangle.c new file mode 100644 index 0000000..21bd80f --- /dev/null +++ b/etc/afpd/mangle.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2002. Joe Marcus Clarke (marcus@marcuscom.com) + * All Rights Reserved. See COPYRIGHT. + * + * mangle, demangle (filename): + * mangle or demangle filenames if they are greater than the max allowed + * characters for a given version of AFP. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include +#include + +#include "mangle.h" +#include "desktop.h" + + +#define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'A' ) +#define isuxdigit(x) (isdigit(x) || (isupper(x) && isxdigit(x))) + +static size_t mangle_extension(const struct vol *vol, const char* uname, + char* extension, charset_t charset) +{ + char *p = strrchr(uname, '.'); + + if (p && p != uname) { + uint16_t flags = CONV_FORCE | CONV_UNESCAPEHEX; + size_t len = convert_charset(vol->v_volcharset, charset, + vol->v_maccharset, p, strlen(p), + extension, MAX_EXT_LENGTH, &flags); + + if (len != (size_t)-1) return len; + } + return 0; +} + +static char *demangle_checks(const struct vol *vol, char* uname, char * mfilename, size_t prefix, char * ext) +{ + uint16_t flags; + static char buffer[MAXPATHLEN +2]; /* for convert_charset dest_len parameter +2 */ + size_t len; + size_t mfilenamelen; + + /* We need to check, whether we really need to demangle the filename */ + /* i.e. it's not just a file with a valid #HEX in the name ... */ + /* but we don't want to miss valid demangle as well. */ + /* check whether file extensions match */ + + char buf[MAX_EXT_LENGTH + 2]; /* for convert_charset dest_len parameter +2 */ + size_t ext_len = mangle_extension(vol, uname, buf, CH_UTF8_MAC); + + if (ext_len) { + buf[ext_len] = '\0'; + if (strcmp(ext, buf)) + return mfilename; + } else { + if (*ext) + return mfilename; + } + + /* First we convert the unix name to our volume maccharset */ + /* This assumes, OSX will not send us a mangled name for *any* */ + /* other reason than a hint/filename mismatch on the OSX side!! */ + /* If the filename needed mangling, we'll get the mac filename */ + /* till the first unconvertable char, so these have to match */ + /* the mangled name we got .. */ + + flags = CONV_IGNORE | CONV_UNESCAPEHEX; + if ( (size_t) -1 == (len = convert_charset(vol->v_volcharset, vol->v_maccharset, 0, + uname, strlen(uname), buffer, MAXPATHLEN, &flags)) ) { + return mfilename; + } + /* If the filename is too long we also needed to mangle */ + mfilenamelen = strlen(mfilename); + if ( len >= vol->max_filename || mfilenamelen == MACFILELEN ) { + flags |= CONV_REQMANGLE; + len = prefix; + } + + /* Ok, mangling was needed, now we do some further checks */ + /* this is still necessary, as we might have a file abcde:xx */ + /* with id 12, mangled to abcde#12, and a passed filename */ + /* abcd#12 */ + /* if we only checked if "prefix" number of characters match */ + /* we get a false postive in above case */ + + if ( (flags & CONV_REQMANGLE) ) { + if (len) { + /* convert the buffer to UTF8_MAC ... */ + if ((size_t) -1 == (len = convert_charset(vol->v_maccharset, CH_UTF8_MAC, 0, + buffer, len, buffer, MAXPATHLEN, &flags)) ) { + return mfilename; + } + /* Now compare the two names, they have to match the number of characters in buffer */ + /* prefix can be longer than len, OSX might send us the first character(s) of a */ + /* decomposed char as the *last* character(s) before the #, so our match below will */ + /* still work, but leaves room for a race ... FIXME */ + if ( (prefix >= len || mfilenamelen == MACFILELEN) + && !strncmp (mfilename, buffer, len)) { + return uname; + } + } + else { + /* We couldn't convert the name to maccharset at all, so we'd expect a name */ + /* in the "???#ID" form ... */ + if ( !strncmp("???", mfilename, prefix)) { + return uname; + } + /* ..but OSX might send us only the first characters of a decomposed character. */ + /* So convert to UTF8_MAC again, now at least the prefix number of */ + /* characters have to match ... again a possible race FIXME */ + + if ( (size_t) -1 == (len = convert_charset(vol->v_volcharset, CH_UTF8_MAC, 0, + uname, strlen(uname), buffer, MAXPATHLEN, &flags)) ) { + return mfilename; + } + + if ( !strncmp (mfilename, buffer, prefix) ) { + return uname; + } + } + } + return mfilename; +} + +/* ------------------------------------------------------- +*/ +static char * +private_demangle(const struct vol *vol, char *mfilename, cnid_t did, cnid_t *osx) +{ + char *t; + char *u_name; + uint32_t id, file_id; + static char buffer[12 + MAXPATHLEN + 1]; + int len = 12 + MAXPATHLEN + 1; + struct dir *dir; + size_t prefix; + + id = file_id = 0; + + t = strchr(mfilename, MANGLE_CHAR); + if (t == NULL) { + return mfilename; + } + prefix = t - mfilename; + /* FIXME + * is prefix == 0 a valid mangled filename ? + */ + /* may be a mangled filename */ + t++; + if (*t == '0') { /* can't start with a 0 */ + return mfilename; + } + while(isuxdigit(*t)) { + id = (id *16) + hextoint(*t); + t++; + } + if ((*t != 0 && *t != '.') || strlen(t) > MAX_EXT_LENGTH || id < 17) { + return mfilename; + } + + file_id = id = htonl(id); + if (osx) { + *osx = id; + } + + /* is it a dir?, there's a conflict with pre OSX 'trash #2' */ + if ((dir = dirlookup(vol, id))) { + if (dir->d_pdid != did) { + /* not in the same folder, there's a race with outdate cache + * but we have to live with it, hopefully client will recover + */ + return mfilename; + } + if (!osx) { + /* it's not from cname so mfilename and dir must be the same */ + if (strcmp(cfrombstr(dir->d_m_name), mfilename) == 0) { + return cfrombstr(dir->d_u_name); + } + } else { + return demangle_checks(vol, cfrombstr(dir->d_u_name), mfilename, prefix, t); + } + } + else if (NULL != (u_name = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) { + if (id != did) { + return mfilename; + } + if (!osx) { + /* convert back to mac name and check it's the same */ + t = utompath(vol, u_name, file_id, utf8_encoding(vol->v_obj)); + if (!strcmp(t, mfilename)) { + return u_name; + } + } + else { + return demangle_checks (vol, u_name, mfilename, prefix, t); + } + } + + return mfilename; +} + +/* ------------------------------------------------------- +*/ +char * +demangle(const struct vol *vol, char *mfilename, cnid_t did) +{ + return private_demangle(vol, mfilename, did, NULL); +} + +/* ------------------------------------------------------- + * OS X +*/ +char * +demangle_osx(const struct vol *vol, char *mfilename, cnid_t did, cnid_t *fileid) +{ + return private_demangle(vol, mfilename, did, fileid); +} + +/* ------------------------------------------------------- + FIXME !!! + + Early Mac OS X (10.0-10.4.?) had the limitation up to 255 Byte. + Current implementation is: + volcharset -> UTF16-MAC -> truncated 255 UTF8-MAC + + Recent Mac OS X (10.4.?-) don't have this limitation. + Desirable implementation is: + volcharset -> truncated 510 UTF16-MAC -> UTF8-MAC + + ------------------------ + with utf8 filename not always round trip + filename mac filename too long or first chars if unmatchable chars. + uname unix filename + id file/folder ID or 0 +*/ +char * +mangle(const struct vol *vol, char *filename, size_t filenamelen, char *uname, cnid_t id, int flags) { + char *m = NULL; + static char mfilename[MAXPATHLEN]; /* way > maxlen */ + char mangle_suffix[MANGLE_LENGTH + 1]; + char ext[MAX_EXT_LENGTH +2]; /* for convert_charset dest_len parameter +2 */ + size_t ext_len; + size_t maxlen; + int k; + + maxlen = (flags & 2)?UTF8FILELEN_EARLY:MACFILELEN; /* was vol->max_filename */ + /* Do we really need to mangle this filename? */ + if (!(flags & 1) && filenamelen <= maxlen) { + return filename; + } + + if (!id) { + /* we don't have the file id! only catsearch call mangle with id == 0 */ + return NULL; + } + /* First, attempt to locate a file extension. */ + ext_len = mangle_extension(vol, uname, ext, (flags & 2) ? CH_UTF8_MAC : vol->v_maccharset); + m = mfilename; + k = sprintf(mangle_suffix, "%c%X", MANGLE_CHAR, ntohl(id)); + + if (filenamelen + k + ext_len > maxlen) { + uint16_t opt = CONV_FORCE | CONV_UNESCAPEHEX; + size_t n = convert_charset(vol->v_volcharset, + (flags & 2) ? CH_UTF8_MAC : vol->v_maccharset, + vol->v_maccharset, uname, strlen(uname), + m, maxlen - k - ext_len, &opt); + m[n != (size_t)-1 ? n : 0] = 0; + } else { + strlcpy(m, filename, filenamelen + 1); + } + if (*m == 0) { + strcat(m, "???"); + } + strcat(m, mangle_suffix); + if (ext_len) { + strncat(m, ext, ext_len); + } + + return m; +} diff --git a/etc/afpd/mangle.h b/etc/afpd/mangle.h new file mode 100644 index 0000000..18d6fcd --- /dev/null +++ b/etc/afpd/mangle.h @@ -0,0 +1,30 @@ +/* + * + */ + +#ifndef AFPD_MANGLE_H +#define AFPD_MANGLE_H 1 + +#include +#include +#include + +#include +#include +#include +#include + +#include "volume.h" +#include "directory.h" + +#define MANGLE_CHAR '#' +#define MAX_MANGLE_SUFFIX_LENGTH 999 +#define MAX_EXT_LENGTH 5 /* XXX This cannot be greater than 27 */ +#define MANGLE_LENGTH 9 /* #ffffffff This really can't be changed. */ +#define MAX_LENGTH MACFILELEN + +extern char *mangle (const struct vol *, char *, size_t, char *, cnid_t, int); +extern char *demangle (const struct vol *, char *, cnid_t did); +extern char *demangle_osx (const struct vol *, char *, cnid_t did, cnid_t *fileid); + +#endif /* AFPD_MANGLE_H */ diff --git a/etc/afpd/messages.c b/etc/afpd/messages.c new file mode 100644 index 0000000..5bd965b --- /dev/null +++ b/etc/afpd/messages.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" + +#define MAXMESGSIZE 199 + +/* this is only used by afpd children, so it's okay. */ +static char servermesg[MAXPATHLEN] = ""; +static char localized_message[MAXPATHLEN] = ""; + +/*! + * Copy AFP message to message buffer + * @param message (r) message to send + * @returns 0 if this message is being set the first time, return 1 if the preceeding + * message was the same + */ +int setmessage(const char *message) +{ + if (strncmp(message, servermesg, MAXMESGSIZE) == 0) + return 1; + strlcpy(servermesg, message, MAXMESGSIZE); + return 0; +} + +void readmessage(AFPObj *obj) +{ + /* Read server message from file defined as SERVERTEXT */ +#ifdef SERVERTEXT + FILE *message; + char * filename; + unsigned int i; + int rc; + static int c; + uint32_t maxmsgsize; + + maxmsgsize = MIN(MAX(obj->dsi->attn_quantum, MAXMESGSIZE), MAXPATHLEN); + + i=0; + /* Construct file name SERVERTEXT/message.[pid] */ + if ( NULL == (filename=(char*) malloc(sizeof(SERVERTEXT)+15)) ) { + LOG(log_error, logtype_afpd, "readmessage: malloc: %s", strerror(errno) ); + return; + } + + sprintf(filename, "%s/message.%d", SERVERTEXT, getpid()); + +#ifdef DEBUG + LOG(log_debug9, logtype_afpd, "Reading file %s ", filename); +#endif + + message=fopen(filename, "r"); + if (message==NULL) { + /* try without the process id */ + sprintf(filename, "%s/message", SERVERTEXT); + message=fopen(filename, "r"); + } + + /* if either message.pid or message exists */ + if (message!=NULL) { + /* added while loop to get characters and put in servermesg */ + while ((( c=fgetc(message)) != EOF) && (i < (maxmsgsize - 1))) { + if ( c == '\n') c = ' '; + servermesg[i++] = c; + } + servermesg[i] = 0; + + /* cleanup */ + fclose(message); + + become_root(); + + if ((rc = unlink(filename)) != 0) + LOG(log_error, logtype_afpd, "File '%s' could not be deleted", strerror(errno)); + + unbecome_root(); + + if (rc < 0) { + LOG(log_error, logtype_afpd, "Error deleting %s: %s", filename, strerror(rc)); + } +#ifdef DEBUG + else { + LOG(log_debug9, logtype_afpd, "Deleted %s", filename); + } + + LOG(log_debug9, logtype_afpd, "Set server message to \"%s\"", servermesg); +#endif + } + free(filename); +#endif /* SERVERTEXT */ +} + +int afp_getsrvrmesg(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + char *message; + uint16_t type, bitmap; + uint16_t msgsize; + size_t outlen = 0; + size_t msglen = 0; + int utf8 = 0; + + *rbuflen = 0; + + msgsize = MAX(obj->dsi->attn_quantum, MAXMESGSIZE); + + memcpy(&type, ibuf + 2, sizeof(type)); + memcpy(&bitmap, ibuf + 4, sizeof(bitmap)); + + message = servermesg; + switch (ntohs(type)) { + case AFPMESG_LOGIN: /* login */ + /* at least TIGER loses server messages + * if it receives a server msg attention before + * it has asked the login msg... + * Workaround: concatenate the two if any, ugly. + */ + if (obj->options.loginmesg) { + if (*message) + strlcat(message, " - ", MAXMESGSIZE); + strlcat(message, obj->options.loginmesg, MAXMESGSIZE); + } + break; + case AFPMESG_SERVER: /* server */ + break; + default: + return AFPERR_BITMAP; + } + + /* output format: + * message type: 2 bytes + * bitmap: 2 bytes + * message length: 1 byte ( 2 bytes for utf8) + * message: up to 199 bytes (dsi attn_quantum for utf8) + */ + memcpy(rbuf, &type, sizeof(type)); + rbuf += sizeof(type); + *rbuflen += sizeof(type); + memcpy(rbuf, &bitmap, sizeof(bitmap)); + rbuf += sizeof(bitmap); + *rbuflen += sizeof(bitmap); + + utf8 = ntohs(bitmap) & 2; + msglen = strlen(message); + if (msglen > msgsize) + msglen = msgsize; + + if (msglen) { + if ( (size_t)-1 == (outlen = convert_string(obj->options.unixcharset, utf8?CH_UTF8_MAC:obj->options.maccharset, + message, msglen, localized_message, msgsize)) ) + { + memcpy(rbuf+((utf8)?2:1), message, msglen); /*FIXME*/ + outlen = msglen; + } + else + { + memcpy(rbuf+((utf8)?2:1), localized_message, outlen); + } + } + + if ( utf8 ) { + /* UTF8 message, 2 byte length */ + msgsize = htons(outlen); + memcpy(rbuf, &msgsize, sizeof(msgsize)); + *rbuflen += sizeof(msgsize); + } + else { + *rbuf = outlen; + *rbuflen += 1; + } + *rbuflen += outlen; +// *message = 0; + return AFP_OK; +} diff --git a/etc/afpd/misc.h b/etc/afpd/misc.h new file mode 100644 index 0000000..b18826d --- /dev/null +++ b/etc/afpd/misc.h @@ -0,0 +1,25 @@ +#ifndef AFPD_MISC_H +#define AFPD_MISC_H 1 + +#include + +/* FP functions */ +/* messages.c */ +int afp_getsrvrmesg (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +/* afs.c */ +#ifdef AFS +int afp_getdiracl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setdiracl (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +#else /* AFS */ +#define afp_getdiracl NULL +#define afp_setdiracl NULL +#endif /* AFS */ + +#if defined( AFS ) && defined( UAM_AFSKRB ) +int afp_afschangepw (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +#else /* AFS && UAM_AFSKRB */ +#define afp_afschangepw NULL +#endif /* AFS && UAM_AFSKRB */ + +#endif diff --git a/etc/afpd/nfsquota.c b/etc/afpd/nfsquota.c new file mode 100644 index 0000000..50440ab --- /dev/null +++ b/etc/afpd/nfsquota.c @@ -0,0 +1,174 @@ +/* + * + * parts of this are lifted from the bsd quota program and are + * therefore under the following copyright: + * + * Copyright (c) 1980, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Ported for AIX (jfs) by Joerg Schumacher (J.Schumacher@tu-bs.de) at the + * Technische Universitaet Braunschweig, FRG + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if !defined(NO_QUOTA_SUPPORT) && !defined(HAVE_LIBQUOTA) +#include +#include +#include +#include +#include /* for DEV_BSIZE */ +#include /* on ultrix doesn't include this */ +#ifdef HAVE_NETDB_H +#include +#endif /* HAVE_NETDB_H */ +#include +#ifndef PORTMAP +#define PORTMAP 1 +#endif +#include +#include +#include + + +#include +#include + +#include "unix.h" + +/* lifted (with modifications) from the bsd quota program */ +static int +callaurpc(struct vol *vol, + u_long prognum, u_long versnum, u_long procnum, + xdrproc_t inproc, char *in, + xdrproc_t outproc, char *out) +{ + enum clnt_stat clnt_stat; + struct timeval tottimeout; + + if (!vol->v_nfsclient) { + struct hostent *hp; + struct sockaddr_in server_addr; + struct timeval timeout; + int socket = RPC_ANYSOCK; + + if ((hp = gethostbyname(vol->v_gvs)) == NULL) + return ((int) RPC_UNKNOWNHOST); + timeout.tv_usec = 0; + timeout.tv_sec = 6; + memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); + server_addr.sin_family = AF_INET; + server_addr.sin_port = 0; + + if ((vol->v_nfsclient = (void *) + clntudp_create(&server_addr, prognum, versnum, + timeout, &socket)) == NULL) + return ((int) rpc_createerr.cf_stat); + + ((CLIENT *) vol->v_nfsclient)->cl_auth = authunix_create_default(); + } + + tottimeout.tv_sec = 10; + tottimeout.tv_usec = 0; + clnt_stat = clnt_call((CLIENT *) vol->v_nfsclient, procnum, + inproc, in, outproc, out, tottimeout); + return ((int) clnt_stat); +} + + +/* sunos 4 machines structure things a little differently. */ +#ifdef USE_OLD_RQUOTA +#define GQR_STATUS gqr_status +#define GQR_RQUOTA gqr_rquota +#else /* USE_OLD_RQUOTA */ +#define GQR_STATUS status +#define GQR_RQUOTA getquota_rslt_u.gqr_rquota +#endif /* USE_OLD_RQUOTA */ + +int getnfsquota(struct vol *vol, const int uid, const uint32_t bsize, + struct dqblk *dqp) +{ + + struct getquota_args gq_args; + struct getquota_rslt gq_rslt; + struct timeval tv; + char *hostpath; + + /* figure out the host and path */ + if ((hostpath = strchr(vol->v_gvs, ':')) == NULL) { + LOG(log_error, logtype_afpd, "can't find hostname for %s", vol->v_gvs); + return AFPERR_PARAM; + } + + if (*(hostpath + 1) != '/') + return AFPERR_PARAM; + + /* separate host from hostpath */ + *hostpath = '\0'; + + gq_args.gqa_pathp = hostpath + 1; + gq_args.gqa_uid = uid; + + if(callaurpc(vol, RQUOTAPROG, RQUOTAVERS, RQUOTAPROC_GETQUOTA, + (xdrproc_t) xdr_getquota_args, (char *) &gq_args, + (xdrproc_t) xdr_getquota_rslt, (char *) &gq_rslt) != 0) { + LOG(log_info, logtype_afpd, "nfsquota: can't retrieve nfs quota information. \ + make sure that rpc.rquotad is running on %s.", vol->v_gvs); + *hostpath = ':'; + return AFPERR_PARAM; + } + + switch (gq_rslt.GQR_STATUS) { + case Q_NOQUOTA: + break; + + case Q_EPERM: + LOG(log_error, logtype_afpd, "nfsquota: quota permission error, host: %s", + vol->v_gvs); + break; + + case Q_OK: /* we only copy the bits that we need. */ + gettimeofday(&tv, NULL); + +#if defined(__svr4__) || defined(TRU64) + /* why doesn't using bsize work? */ +#define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / DEV_BSIZE +#else /* __svr4__ || TRU64 */ + /* NOTE: linux' rquotad program doesn't currently report the + * correct rq_bsize. */ + /* NOTE: This is integer division and can introduce rounding errors */ +#define NFS_BSIZE gq_rslt.GQR_RQUOTA.rq_bsize / bsize +#endif /* __svr4__ || TRU64 */ + + dqp->dqb_bhardlimit = + gq_rslt.GQR_RQUOTA.rq_bhardlimit*NFS_BSIZE; + dqp->dqb_bsoftlimit = + gq_rslt.GQR_RQUOTA.rq_bsoftlimit*NFS_BSIZE; + dqp->dqb_curblocks = + gq_rslt.GQR_RQUOTA.rq_curblocks*NFS_BSIZE; + +#ifdef ultrix + dqp->dqb_bwarn = gq_rslt.GQR_RQUOTA.rq_btimeleft; +#else /* ultrix */ + dqp->dqb_btimelimit = + tv.tv_sec + gq_rslt.GQR_RQUOTA.rq_btimeleft; +#endif /* ultrix */ + + *hostpath = ':'; + return AFP_OK; + break; + + default: + LOG(log_info, logtype_afpd, "bad rpc result, host: %s", vol->v_gvs); + break; + } + + *hostpath = ':'; + return AFPERR_PARAM; +} +#endif /* ! NO_QUOTA_SUPPORT && !HAVE_LIBQUOTA */ diff --git a/etc/afpd/ofork.c b/etc/afpd/ofork.c new file mode 100644 index 0000000..59e9f15 --- /dev/null +++ b/etc/afpd/ofork.c @@ -0,0 +1,539 @@ +/* + * Copyright (c) 1996 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include /* works around a bug */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "volume.h" +#include "directory.h" +#include "fork.h" +#include "desktop.h" + +/* we need to have a hashed list of oforks (by dev inode) */ +#define OFORK_HASHSIZE 64 +static struct ofork *ofork_table[OFORK_HASHSIZE]; /* forks hashed by dev/inode */ +static struct ofork **oforks = NULL; /* point to allocated table of open forks pointers */ +static int nforks = 0; +static u_short lastrefnum = 0; + + +/* OR some of each character for the hash*/ +static unsigned long hashfn(const struct file_key *key) +{ + return key->inode & (OFORK_HASHSIZE - 1); +} + +static void of_hash(struct ofork *of) +{ + struct ofork **table; + + table = &ofork_table[hashfn(&of->key)]; + if ((of->next = *table) != NULL) + (*table)->prevp = &of->next; + *table = of; + of->prevp = table; +} + +static void of_unhash(struct ofork *of) +{ + if (of->prevp) { + if (of->next) + of->next->prevp = of->prevp; + *(of->prevp) = of->next; + } +} + +int of_flush(const struct vol *vol) +{ + int refnum; + + if (!oforks) + return 0; + + for ( refnum = 0; refnum < nforks; refnum++ ) { + if (oforks[ refnum ] != NULL && (oforks[refnum]->of_vol == vol) && + flushfork( oforks[ refnum ] ) < 0 ) { + LOG(log_error, logtype_afpd, "of_flush: %s", strerror(errno) ); + } + } + return( 0 ); +} + +int of_rename(const struct vol *vol, + struct ofork *s_of, + struct dir *olddir, const char *oldpath _U_, + struct dir *newdir, const char *newpath) +{ + struct ofork *of, *next; + int done = 0; + + if (!s_of) + return AFP_OK; + + next = ofork_table[hashfn(&s_of->key)]; + while ((of = next)) { + next = next->next; /* so we can unhash and still be all right. */ + + if (vol == of->of_vol + && olddir->d_did == of->of_did + && s_of->key.dev == of->key.dev + && s_of->key.inode == of->key.inode ) { + if (!done) { + free(of_name(of)); + if ((of_name(of) = strdup(newpath)) == NULL) + return AFPERR_MISC; + done = 1; + } + if (newdir != olddir) + of->of_did = newdir->d_did; + } + } + + return AFP_OK; +} + +#define min(a,b) ((a)<(b)?(a):(b)) + +struct ofork * +of_alloc(struct vol *vol, + struct dir *dir, + char *path, + uint16_t *ofrefnum, + const int eid, + struct adouble *ad, + struct stat *st) +{ + struct ofork *of; + uint16_t refnum, of_refnum; + + int i; + + if (!oforks) { + nforks = getdtablesize() - 10; + /* protect against insane ulimit -n */ + nforks = min(nforks, 0xffff); + oforks = (struct ofork **) calloc(nforks, sizeof(struct ofork *)); + if (!oforks) + return NULL; + } + + for ( refnum = ++lastrefnum, i = 0; i < nforks; i++, refnum++ ) { + /* cf AFP3.0.pdf, File fork page 40 */ + if (!refnum) + refnum++; + if ( oforks[ refnum % nforks ] == NULL ) { + break; + } + } + /* grr, Apple and their 'uniquely identifies' + the next line is a protection against + of_alloc() + refnum % nforks = 3 + lastrefnum = 3 + oforks[3] != NULL + refnum = 4 + oforks[4] == NULL + return 4 + + close(oforks[4]) + + of_alloc() + refnum % nforks = 4 + ... + return 4 + same if lastrefnum++ rather than ++lastrefnum. + */ + lastrefnum = refnum; + if ( i == nforks ) { + LOG(log_error, logtype_afpd, "of_alloc: maximum number of forks exceeded."); + return( NULL ); + } + + of_refnum = refnum % nforks; + if (( oforks[ of_refnum ] = + (struct ofork *)malloc( sizeof( struct ofork ))) == NULL ) { + LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) ); + return NULL; + } + of = oforks[of_refnum]; + + /* see if we need to allocate space for the adouble struct */ + if (!ad) { + ad = malloc( sizeof( struct adouble ) ); + if (!ad) { + LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) ); + free(of); + oforks[ of_refnum ] = NULL; + return NULL; + } + + /* initialize to zero. This is important to ensure that + ad_open really does reinitialize the structure. */ + ad_init(ad, vol); + if ((ad->ad_name = strdup(path)) == NULL) { + LOG(log_error, logtype_afpd, "of_alloc: malloc: %s", strerror(errno) ); + free(ad); + free(of); + oforks[ of_refnum ] = NULL; + return NULL; + } + } else { + /* Increase the refcount on this struct adouble. This is + decremented again in oforc_dealloc. */ + ad_ref(ad); + } + + of->of_ad = ad; + of->of_vol = vol; + of->of_did = dir->d_did; + + *ofrefnum = refnum; + of->of_refnum = refnum; + of->key.dev = st->st_dev; + of->key.inode = st->st_ino; + if (eid == ADEID_DFORK) + of->of_flags = AFPFORK_DATA; + else + of->of_flags = AFPFORK_RSRC; + + of_hash(of); + return( of ); +} + +struct ofork *of_find(const uint16_t ofrefnum ) +{ + if (!oforks || !nforks) + return NULL; + + return( oforks[ ofrefnum % nforks ] ); +} + +/* -------------------------- */ +int of_stat(const struct vol *vol, struct path *path) +{ + int ret; + + path->st_errno = 0; + path->st_valid = 1; + + if ((ret = ostat(path->u_name, &path->st, vol_syml_opt(vol))) < 0) { + LOG(log_debug, logtype_afpd, "of_stat('%s/%s': %s)", + cfrombstr(curdir->d_fullpath), path->u_name, strerror(errno)); + path->st_errno = errno; + } + + return ret; +} + + +#ifdef HAVE_ATFUNCS +int of_fstatat(int dirfd, struct path *path) +{ + int ret; + + path->st_errno = 0; + path->st_valid = 1; + + if ((ret = fstatat(dirfd, path->u_name, &path->st, AT_SYMLINK_NOFOLLOW)) < 0) + path->st_errno = errno; + + return ret; +} +#endif /* HAVE_ATFUNCS */ + +/* -------------------------- + stat the current directory. + stat(".") works even if "." is deleted thus + we have to stat ../name because we want to know if it's there +*/ +int of_statdir(struct vol *vol, struct path *path) +{ + static char pathname[ MAXPATHLEN + 1] = "../"; + int ret; + size_t len; + struct dir *dir; + + if (*path->m_name) { + /* not curdir */ + return of_stat(vol, path); + } + path->st_errno = 0; + path->st_valid = 1; + /* FIXME, what about: we don't have r-x perm anymore ? */ + len = blength(path->d_dir->d_u_name); + if (len > (MAXPATHLEN - 3)) + len = MAXPATHLEN - 3; + strncpy(pathname + 3, cfrombstr(path->d_dir->d_u_name), len + 1); + + LOG(log_debug, logtype_afpd, "of_statdir: stating: '%s'", pathname); + + if (!(ret = ostat(pathname, &path->st, vol_syml_opt(vol)))) + return 0; + + path->st_errno = errno; + + /* hmm, can't stat curdir anymore */ + if (errno == EACCES && (dir = dirlookup(vol, curdir->d_pdid))) { + if (movecwd(vol, dir)) + return -1; + path->st_errno = 0; + + if ((ret = ostat(cfrombstr(path->d_dir->d_u_name), &path->st, vol_syml_opt(vol))) < 0) + path->st_errno = errno; + } + + return ret; +} + +/* -------------------------- */ +struct ofork *of_findname(const struct vol *vol, struct path *path) +{ + struct ofork *of; + struct file_key key; + + if (!path->st_valid) { + of_stat(vol, path); + } + + if (path->st_errno) + return NULL; + + key.dev = path->st.st_dev; + key.inode = path->st.st_ino; + + for (of = ofork_table[hashfn(&key)]; of; of = of->next) { + if (key.dev == of->key.dev && key.inode == of->key.inode ) { + return of; + } + } + + return NULL; +} + +/*! + * @brief Search for open fork by dirfd/name + * + * Function call of_fstatat with dirfd and path and uses dev and ino + * to search the open fork table. + * + * @param dirfd (r) directory fd + * @param path (rw) pointer to struct path + */ +#ifdef HAVE_ATFUNCS +struct ofork *of_findnameat(int dirfd, struct path *path) +{ + struct ofork *of; + struct file_key key; + + if ( ! path->st_valid) { + of_fstatat(dirfd, path); + } + + if (path->st_errno) + return NULL; + + key.dev = path->st.st_dev; + key.inode = path->st.st_ino; + + for (of = ofork_table[hashfn(&key)]; of; of = of->next) { + if (key.dev == of->key.dev && key.inode == of->key.inode ) { + return of; + } + } + + return NULL; +} +#endif + +void of_dealloc(struct ofork *of) +{ + if (!oforks) + return; + + of_unhash(of); + oforks[ of->of_refnum % nforks ] = NULL; + + /* decrease refcount */ + of->of_ad->ad_refcount--; + + if ( of->of_ad->ad_refcount <= 0) { + free( of->of_ad->ad_name ); + free( of->of_ad); + } + + free( of ); +} + +/* --------------------------- */ +int of_closefork(const AFPObj *obj, struct ofork *ofork) +{ + struct timeval tv; + int adflags = 0; + int ret; + struct dir *dir; + bstring forkpath = NULL; + + adflags = 0; + if (ofork->of_flags & AFPFORK_DATA) + adflags |= ADFLAGS_DF; + if (ofork->of_flags & AFPFORK_META) + adflags |= ADFLAGS_HF; + if (ofork->of_flags & AFPFORK_RSRC) { + adflags |= ADFLAGS_RF; + /* Only set the rfork's length if we're closing the rfork. */ + ad_refresh(NULL, ofork->of_ad ); + if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) { + ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec); + ad_flush( ofork->of_ad ); + } + } + + dir = dirlookup(ofork->of_vol, ofork->of_did); + if (dir == NULL) { + LOG(log_debug, logtype_afpd, "dirlookup failed for %ju", (uintmax_t)ofork->of_did); + } + + if (dir) { + forkpath = bformat("%s/%s", bdata(dir->d_fullpath), of_name(ofork)); + } + + /* Somone has used write_fork, we assume file was changed, register it to file change event api */ + if ((ofork->of_flags & AFPFORK_MODIFIED) && (forkpath)) { + fce_register(obj, FCE_FILE_MODIFY, bdata(forkpath), NULL); + } + + ad_unlock(ofork->of_ad, ofork->of_refnum, ofork->of_flags & AFPFORK_ERROR ? 0 : 1); + +#ifdef HAVE_FSHARE_T + if (obj->options.flags & OPTION_SHARE_RESERV) { + fshare_t shmd; + shmd.f_id = ofork->of_refnum; + if (AD_DATA_OPEN(ofork->of_ad)) + fcntl(ad_data_fileno(ofork->of_ad), F_UNSHARE, &shmd); + if (AD_RSRC_OPEN(ofork->of_ad)) + fcntl(ad_reso_fileno(ofork->of_ad), F_UNSHARE, &shmd); + } +#endif + + ret = 0; + + /* + * Check for 0 byte size resource forks, delete them. + * Here's the deal: + * (1) the size must be 0 + * (2) the fork must refer to a resource fork + * (3) the refcount must be 1 which means this fork has the last + * reference to the adouble struct and the subsequent + * ad_close() will close the assoiciated fd. + * (4) nobody else has the resource fork open + * + * We only do this for ._ AppleDouble resource forks, not for + * xattr resource forks, because the test-suite then fails several + * tests on Solaris, the reason for that still needs to be + * determined. + */ + if ((ofork->of_ad->ad_rlen == 0) + && (ofork->of_flags & AFPFORK_RSRC) + && (ofork->of_ad->ad_rfp->adf_refcount == 1) + && (ad_openforks(ofork->of_ad, ATTRBIT_DOPEN) == 0)) { + +#ifndef HAVE_EAFD + (void)unlink(ofork->of_ad->ad_ops->ad_path( + mtoupath(ofork->of_vol, + of_name(ofork), + ofork->of_did, + utf8_encoding(obj)), + 0)); +#endif + } + + if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) { + ret = -1; + } + + of_dealloc(ofork); + + if (forkpath) + bdestroy(forkpath); + + return ret; +} + +/* ---------------------- + + */ +struct adouble *of_ad(const struct vol *vol, struct path *path, struct adouble *ad) +{ + struct ofork *of; + struct adouble *adp; + + if ((of = of_findname(vol, path))) { + adp = of->of_ad; + } else { + ad_init(ad, vol); + adp = ad; + } + return adp; +} + +/* ---------------------- + close all forks for a volume +*/ +void of_closevol(const AFPObj *obj, const struct vol *vol) +{ + int refnum; + + if (!oforks) + return; + + for ( refnum = 0; refnum < nforks; refnum++ ) { + if (oforks[ refnum ] != NULL && oforks[refnum]->of_vol == vol) { + if (of_closefork(obj, oforks[ refnum ]) < 0 ) { + LOG(log_error, logtype_afpd, "of_closevol: %s", strerror(errno) ); + } + } + } + return; +} + +/* ---------------------- + close all forks for a volume +*/ +void of_close_all_forks(const AFPObj *obj) +{ + int refnum; + + if (!oforks) + return; + + for ( refnum = 0; refnum < nforks; refnum++ ) { + if (oforks[ refnum ] != NULL) { + if (of_closefork(obj, oforks[ refnum ]) < 0 ) { + LOG(log_error, logtype_afpd, "of_close_all_forks: %s", strerror(errno) ); + } + } + } + return; +} + diff --git a/etc/afpd/quota.c b/etc/afpd/quota.c new file mode 100644 index 0000000..bab14e1 --- /dev/null +++ b/etc/afpd/quota.c @@ -0,0 +1,814 @@ +/* + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NO_QUOTA_SUPPORT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "auth.h" +#include "volume.h" +#include "unix.h" + +#ifdef HAVE_LIBQUOTA +#include + +static int +getfreespace(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal, + uid_t uid, const char *classq) +{ + int retq; + struct ufs_quota_entry ufsq[QUOTA_NLIMITS]; + time_t now; + + if (time(&now) == -1) { + LOG(log_info, logtype_afpd, "time(): %s", + strerror(errno)); + return -1; + } + + become_root(); + + if ((retq = getfsquota(obj, vol, ufsq, uid, classq)) < 0) { + LOG(log_info, logtype_afpd, "getfsquota(%s, %s): %s", + vol->v_path, classq, strerror(errno)); + } + + unbecome_root(); + + if (retq < 1) + return retq; + + switch(QL_STATUS(quota_check_limit(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur, 1, + ufsq[QUOTA_LIMIT_BLOCK].ufsqe_softlimit, + ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit, + ufsq[QUOTA_LIMIT_BLOCK].ufsqe_time, now))) { + case QL_S_DENY_HARD: + case QL_S_DENY_GRACE: + *bfree = 0; + *btotal = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur); + break; + default: + *bfree = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit - + ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur); + *btotal = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit); + break; + } + return 1; +} + +int uquota_getvolspace(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal, const u_int32_t bsize) +{ + int uretq, gretq; + VolSpace ubfree, ubtotal; + VolSpace gbfree, gbtotal; + + uretq = getfreespace(obj, vol, &ubfree, &ubtotal, + uuid, QUOTADICT_CLASS_USER); + LOG(log_info, logtype_afpd, "getfsquota(%s): %d %d", + vol->v_path, (int)ubfree, (int)ubtotal); + if (obj->ngroups >= 1) { + gretq = getfreespace(vol, &ubfree, &ubtotal, + obj->groups[0], QUOTADICT_CLASS_GROUP); + } else + gretq = -1; + if (uretq < 1 && gretq < 1) { /* no quota for this fs */ + return AFPERR_PARAM; + } + if (uretq < 1) { + /* use group quotas */ + *bfree = gbfree; + *btotal = gbtotal; + } else if (gretq < 1) { + /* use user quotas */ + *bfree = ubfree; + *btotal = ubtotal; + } else { + /* return smallest remaining space of user and group */ + if (ubfree < gbfree) { + *bfree = ubfree; + *btotal = ubtotal; + } else { + *bfree = gbfree; + *btotal = gbtotal; + } + } + return AFP_OK; + +} + +#else /* HAVE_LIBQUOTA */ + +/* +#define DEBUG_QUOTA 0 +*/ + +#define WANT_USER_QUOTA 0 +#define WANT_GROUP_QUOTA 1 + +#ifdef NEED_QUOTACTL_WRAPPER +int quotactl(int cmd, const char *special, int id, caddr_t addr) +{ + return syscall(__NR_quotactl, cmd, special, id, addr); +} +#endif /* NEED_QUOTACTL_WRAPPER */ + +static int overquota( struct dqblk *); + +#ifdef linux + +#ifdef HAVE_LINUX_XQM_H +#include +#else +#ifdef HAVE_XFS_XQM_H +#include +#define HAVE_LINUX_XQM_H +#else +#ifdef HAVE_LINUX_DQBLK_XFS_H +#include +#define HAVE_LINUX_XQM_H +#endif /* HAVE_LINUX_DQBLK_XFS_H */ +#endif /* HAVE_XFS_XQM_H */ +#endif /* HAVE_LINUX_XQM_H */ + +#include + +static int is_xfs = 0; + +static int get_linux_xfs_quota(int, char*, uid_t, struct dqblk *); +static int get_linux_fs_quota(int, char*, uid_t, struct dqblk *); + +/* format supported by current kernel */ +static int kernel_iface = IFACE_UNSET; + +/* +** Check kernel quota version +** Taken from quota-tools 3.08 by Jan Kara +*/ +static void linuxquota_get_api( void ) +{ +#ifndef LINUX_API_VERSION + struct stat st; + + if (stat("/proc/sys/fs/quota", &st) == 0) { + kernel_iface = IFACE_GENERIC; + } + else { + struct dqstats_v2 v2_stats; + struct sigaction sig; + struct sigaction oldsig; + + /* This signal handling is needed because old kernels send us SIGSEGV as they try to resolve the device */ + sig.sa_handler = SIG_IGN; + sig.sa_sigaction = NULL; + sig.sa_flags = 0; + sigemptyset(&sig.sa_mask); + if (sigaction(SIGSEGV, &sig, &oldsig) < 0) { + LOG( log_error, logtype_afpd, "cannot set SEGV signal handler: %s", strerror(errno)); + goto failure; + } + if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (void *)&v2_stats) >= 0) { + kernel_iface = IFACE_VFSV0; + } + else if (errno != ENOSYS && errno != ENOTSUP) { + /* RedHat 7.1 (2.4.2-2) newquota check + * Q_V2_GETSTATS in it's old place, Q_GETQUOTA in the new place + * (they haven't moved Q_GETSTATS to its new value) */ + int err_stat = 0; + int err_quota = 0; + char tmp[1024]; /* Just temporary buffer */ + + if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, tmp)) + err_stat = errno; + if (quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", 0, tmp)) + err_quota = errno; + + /* On a RedHat 2.4.2-2 we expect 0, EINVAL + * On a 2.4.x we expect 0, ENOENT + * On a 2.4.x-ac we wont get here */ + if (err_stat == 0 && err_quota == EINVAL) { + kernel_iface = IFACE_VFSV0; + } + else { + kernel_iface = IFACE_VFSOLD; + } + } + else { + /* This branch is *not* in quota-tools 3.08 + ** but without it quota version is not correctly + ** identified for the original SuSE 8.0 kernel */ + unsigned int vers_no; + FILE * qf; + + if ((qf = fopen("/proc/fs/quota", "r"))) { + if (fscanf(qf, "Version %u", &vers_no) == 1) { + if ( (vers_no == (6*10000 + 5*100 + 0)) || + (vers_no == (6*10000 + 5*100 + 1)) ) { + kernel_iface = IFACE_VFSV0; + } + } + fclose(qf); + } + } + if (sigaction(SIGSEGV, &oldsig, NULL) < 0) { + LOG(log_error, logtype_afpd, "cannot reset signal handler: %s", strerror(errno)); + goto failure; + } + } + +failure: + if (kernel_iface == IFACE_UNSET) + kernel_iface = IFACE_VFSOLD; + +#else /* defined LINUX_API_VERSION */ + kernel_iface = LINUX_API_VERSION; +#endif +} + +/****************************************************************************/ + +static int get_linux_quota(int what, char *path, uid_t euser_id, struct dqblk *dp) +{ + int r; /* result */ + + if ( is_xfs ) + r=get_linux_xfs_quota(what, path, euser_id, dp); + else + r=get_linux_fs_quota(what, path, euser_id, dp); + + return r; +} + +/**************************************************************************** + Abstract out the XFS Quota Manager quota get call. +****************************************************************************/ + +static int get_linux_xfs_quota(int what, char *path, uid_t euser_id, struct dqblk *dqb) +{ + int ret = -1; +#ifdef HAVE_LINUX_XQM_H + struct fs_disk_quota D; + + memset (&D, 0, sizeof(D)); + + if ((ret = quotactl(QCMD(Q_XGETQUOTA,(what ? GRPQUOTA : USRQUOTA)), path, euser_id, (caddr_t)&D))) + return ret; + + dqb->bsize = (uint64_t)512; + dqb->dqb_bsoftlimit = (uint64_t)D.d_blk_softlimit; + dqb->dqb_bhardlimit = (uint64_t)D.d_blk_hardlimit; + dqb->dqb_ihardlimit = (uint64_t)D.d_ino_hardlimit; + dqb->dqb_isoftlimit = (uint64_t)D.d_ino_softlimit; + dqb->dqb_curinodes = (uint64_t)D.d_icount; + dqb->dqb_curblocks = (uint64_t)D.d_bcount; +#endif + return ret; +} + +/* +** Wrapper for the quotactl(GETQUOTA) call. +** For API v2 the results are copied back into a v1 structure. +** Taken from quota-1.4.8 perl module +*/ +static int get_linux_fs_quota(int what, char *path, uid_t euser_id, struct dqblk *dqb) +{ + int ret; + + if (kernel_iface == IFACE_UNSET) + linuxquota_get_api(); + + if (kernel_iface == IFACE_GENERIC) + { + struct dqblk_v3 dqb3; + + ret = quotactl(QCMD(Q_V3_GETQUOTA, (what ? GRPQUOTA : USRQUOTA)), path, euser_id, (caddr_t) &dqb3); + if (ret == 0) + { + dqb->dqb_bhardlimit = dqb3.dqb_bhardlimit; + dqb->dqb_bsoftlimit = dqb3.dqb_bsoftlimit; + dqb->dqb_curblocks = dqb3.dqb_curspace / DEV_QBSIZE; + dqb->dqb_ihardlimit = dqb3.dqb_ihardlimit; + dqb->dqb_isoftlimit = dqb3.dqb_isoftlimit; + dqb->dqb_curinodes = dqb3.dqb_curinodes; + dqb->dqb_btime = dqb3.dqb_btime; + dqb->dqb_itime = dqb3.dqb_itime; + dqb->bsize = DEV_QBSIZE; + } + } + else if (kernel_iface == IFACE_VFSV0) + { + struct dqblk_v2 dqb2; + + ret = quotactl(QCMD(Q_V2_GETQUOTA, (what ? GRPQUOTA : USRQUOTA)), path, euser_id, (caddr_t) &dqb2); + if (ret == 0) + { + dqb->dqb_bhardlimit = dqb2.dqb_bhardlimit; + dqb->dqb_bsoftlimit = dqb2.dqb_bsoftlimit; + dqb->dqb_curblocks = dqb2.dqb_curspace / DEV_QBSIZE; + dqb->dqb_ihardlimit = dqb2.dqb_ihardlimit; + dqb->dqb_isoftlimit = dqb2.dqb_isoftlimit; + dqb->dqb_curinodes = dqb2.dqb_curinodes; + dqb->dqb_btime = dqb2.dqb_btime; + dqb->dqb_itime = dqb2.dqb_itime; + dqb->bsize = DEV_QBSIZE; + } + } + else /* if (kernel_iface == IFACE_VFSOLD) */ + { + struct dqblk_v1 dqb1; + + ret = quotactl(QCMD(Q_V1_GETQUOTA, (what ? GRPQUOTA : USRQUOTA)), path, euser_id, (caddr_t) &dqb1); + if (ret == 0) + { + dqb->dqb_bhardlimit = dqb1.dqb_bhardlimit; + dqb->dqb_bsoftlimit = dqb1.dqb_bsoftlimit; + dqb->dqb_curblocks = dqb1.dqb_curblocks; + dqb->dqb_ihardlimit = dqb1.dqb_ihardlimit; + dqb->dqb_isoftlimit = dqb1.dqb_isoftlimit; + dqb->dqb_curinodes = dqb1.dqb_curinodes; + dqb->dqb_btime = dqb1.dqb_btime; + dqb->dqb_itime = dqb1.dqb_itime; + dqb->bsize = DEV_QBSIZE; + } + } + return ret; +} + +#endif /* linux */ + +#if defined(HAVE_SYS_MNTTAB_H) || defined(__svr4__) +/* + * Return the mount point associated with the filesystem + * on which "file" resides. Returns NULL on failure. + */ +static char * +mountp( char *file, int *nfs) +{ + struct stat sb; + FILE *mtab; + dev_t devno; + static struct mnttab mnt; + + if (stat(file, &sb) < 0) { + return( NULL ); + } + devno = sb.st_dev; + + if (( mtab = fopen( "/etc/mnttab", "r" )) == NULL ) { + return( NULL ); + } + + while ( getmntent( mtab, &mnt ) == 0 ) { + /* local fs */ + if ( (stat( mnt.mnt_special, &sb ) == 0) && (devno == sb.st_rdev)) { + fclose( mtab ); + return mnt.mnt_mountp; + } + + /* check for nfs. we probably should use + * strcmp(mnt.mnt_fstype, MNTTYPE_NFS), but that's not as fast. */ + if ((stat(mnt.mnt_mountp, &sb) == 0) && (devno == sb.st_dev) && + strchr(mnt.mnt_special, ':')) { + *nfs = 1; + fclose( mtab ); + return mnt.mnt_special; + } + } + + fclose( mtab ); + return( NULL ); +} + +#else /* __svr4__ */ +#ifdef ultrix +/* +* Return the block-special device name associated with the filesystem +* on which "file" resides. Returns NULL on failure. +*/ + +static char * +special( char *file, int *nfs) +{ + static struct fs_data fsd; + + if ( getmnt(0, &fsd, 0, STAT_ONE, file ) < 0 ) { + LOG(log_info, logtype_afpd, "special: getmnt %s: %s", file, strerror(errno) ); + return( NULL ); + } + + /* XXX: does this really detect an nfs mounted fs? */ + if (strchr(fsd.fd_req.devname, ':')) + *nfs = 1; + return( fsd.fd_req.devname ); +} + +#else /* ultrix */ +#if (defined(HAVE_SYS_MOUNT_H) && !defined(__linux__)) || defined(BSD4_4) || defined(_IBMR2) + +static char * +special(char *file, int *nfs) +{ + static struct statfs sfs; + + if ( statfs( file, &sfs ) < 0 ) { + return( NULL ); + } + +#ifdef TRU64 + /* Digital UNIX: The struct sfs contains a field sfs.f_type, + * the MOUNT_* constants are defined in */ + if ((sfs.f_type == MOUNT_NFS)||(sfs.f_type == MOUNT_NFS3)) +#else /* TRU64 */ + /* XXX: make sure this really detects an nfs mounted fs */ + if (strchr(sfs.f_mntfromname, ':')) +#endif /* TRU64 */ + *nfs = 1; + return( sfs.f_mntfromname ); +} + +#else /* BSD4_4 */ + +static char * +special(char *file, int *nfs) +{ + struct stat sb; + FILE *mtab; + dev_t devno; + struct mntent *mnt; + int found=0; + + if (stat(file, &sb) < 0 ) { + return( NULL ); + } + devno = sb.st_dev; + + if (( mtab = setmntent( "/etc/mtab", "r" )) == NULL ) { + return( NULL ); + } + + while (( mnt = getmntent( mtab )) != NULL ) { + /* check for local fs */ + if ( (stat( mnt->mnt_fsname, &sb ) == 0) && devno == sb.st_rdev) { + found = 1; + break; + } + + /* check for an nfs mount entry. the alternative is to use + * strcmp(mnt->mnt_type, MNTTYPE_NFS) instead of the strchr. */ + if ((stat(mnt->mnt_dir, &sb) == 0) && (devno == sb.st_dev) && + strchr(mnt->mnt_fsname, ':')) { + *nfs = 1; + found = 1; + break; + } + } + + endmntent( mtab ); + + if (!found) + return (NULL); +#ifdef linux + if (strcmp(mnt->mnt_type, "xfs") == 0) + is_xfs = 1; +#endif + + return( mnt->mnt_fsname ); +} + +#endif /* BSD4_4 */ +#endif /* ultrix */ +#endif /* __svr4__ */ + + +static int getfsquota(const AFPObj *obj, struct vol *vol, const int uid, struct dqblk *dq) + +{ + struct dqblk dqg; + +#ifdef __svr4__ + struct quotctl qc; +#endif + + memset(dq, 0, sizeof(struct dqblk)); + memset(&dqg, 0, sizeof(dqg)); + +#ifdef __svr4__ + qc.op = Q_GETQUOTA; + qc.uid = uid; + qc.addr = (caddr_t)dq; + if ( ioctl( vol->v_qfd, Q_QUOTACTL, &qc ) < 0 ) { + return( AFPERR_PARAM ); + } + +#else /* __svr4__ */ +#ifdef ultrix + if ( quota( Q_GETDLIM, uid, vol->v_gvs, dq ) != 0 ) { + return( AFPERR_PARAM ); + } +#else /* ultrix */ + +#ifndef USRQUOTA +#define USRQUOTA 0 +#endif + +#ifndef QCMD +#define QCMD(a,b) (a) +#endif + +#ifndef TRU64 + /* for group quotas. we only use these if the user belongs + * to one group. */ +#endif /* TRU64 */ + +#ifdef BSD4_4 + become_root(); + if ( quotactl( vol->v_path, QCMD(Q_GETQUOTA,USRQUOTA), + uid, (char *)dq ) != 0 ) { + /* try group quotas */ + if (obj->ngroups >= 1) { + if ( quotactl(vol->v_path, QCMD(Q_GETQUOTA, GRPQUOTA), + obj->groups[0], (char *) &dqg) != 0 ) { + unbecome_root(); + return( AFPERR_PARAM ); + } + } + } + unbecome_root(); + } + +#else /* BSD4_4 */ + if (get_linux_quota (WANT_USER_QUOTA, vol->v_gvs, uid, dq) !=0) { +#ifdef DEBUG_QUOTA + LOG(log_debug, logtype_afpd, "user quota did not work!" ); +#endif /* DEBUG_QUOTA */ + } + + if (get_linux_quota(WANT_GROUP_QUOTA, vol->v_gvs, getegid(), &dqg) != 0) { +#ifdef DEBUG_QUOTA + LOG(log_debug, logtype_afpd, "group quota did not work!" ); +#endif /* DEBUG_QUOTA */ + + return AFP_OK; /* no need to check user vs group quota */ + } +#endif /* BSD4_4 */ + + +#ifndef TRU64 + /* return either the group quota entry or user quota entry, + whichever has the least amount of space remaining + */ + + /* if user space remaining > group space remaining */ + if( + /* if overquota, free space is 0 otherwise hard-current */ + ( overquota( dq ) ? 0 : ( dq->dqb_bhardlimit ? dq->dqb_bhardlimit - + dq->dqb_curblocks : ~((uint64_t) 0) ) ) + + > + + ( overquota( &dqg ) ? 0 : ( dqg.dqb_bhardlimit ? dqg.dqb_bhardlimit - + dqg.dqb_curblocks : ~((uint64_t) 0) ) ) + + ) /* if */ + { + /* use group quota limits rather than user limits */ + dq->dqb_bhardlimit = dqg.dqb_bhardlimit; + dq->dqb_bsoftlimit = dqg.dqb_bsoftlimit; + dq->dqb_curblocks = dqg.dqb_curblocks; + dq->dqb_ihardlimit = dqg.dqb_ihardlimit; + dq->dqb_isoftlimit = dqg.dqb_isoftlimit; + dq->dqb_curinodes = dqg.dqb_curinodes; + dq->dqb_btime = dqg.dqb_btime; + dq->dqb_itime = dqg.dqb_itime; + dq->bsize = dqg.bsize; + } /* if */ + +#endif /* TRU64 */ + +#endif /* ultrix */ +#endif /* __svr4__ */ + + return AFP_OK; +} + + +static int getquota(const AFPObj *obj, struct vol *vol, struct dqblk *dq, const uint32_t bsize) +{ + char *p; + +#ifdef __svr4__ + char buf[ MAXPATHLEN + 1]; + + if ( vol->v_qfd == -1 && vol->v_gvs == NULL) { + if (( p = mountp( vol->v_path, &vol->v_nfs)) == NULL ) { + LOG(log_info, logtype_afpd, "getquota: mountp %s fails", vol->v_path ); + return( AFPERR_PARAM ); + } + + if (vol->v_nfs) { + if (( vol->v_gvs = (char *)malloc( strlen( p ) + 1 )) == NULL ) { + LOG(log_error, logtype_afpd, "getquota: malloc: %s", strerror(errno) ); + return AFPERR_MISC; + } + strcpy( vol->v_gvs, p ); + + } else { + sprintf( buf, "%s/quotas", p ); + if (( vol->v_qfd = open( buf, O_RDONLY, 0 )) < 0 ) { + LOG(log_info, logtype_afpd, "open %s: %s", buf, strerror(errno) ); + return( AFPERR_PARAM ); + } + } + + } +#else + if ( vol->v_gvs == NULL ) { + if (( p = special( vol->v_path, &vol->v_nfs )) == NULL ) { + LOG(log_info, logtype_afpd, "getquota: special %s fails", vol->v_path ); + return( AFPERR_PARAM ); + } + + if (( vol->v_gvs = (char *)malloc( strlen( p ) + 1 )) == NULL ) { + LOG(log_error, logtype_afpd, "getquota: malloc: %s", strerror(errno) ); + return AFPERR_MISC; + } + strcpy( vol->v_gvs, p ); + } +#endif + +#ifdef TRU64 + /* Digital UNIX: Two forms of specifying an NFS filesystem are possible, + either 'hostname:path' or 'path@hostname' (Ultrix heritage) */ + if (vol->v_nfs) { + char *hostpath; + char pathstring[MNAMELEN]; + /* MNAMELEN ist defined in */ + int result; + + if ((hostpath = strchr(vol->v_gvs,'@')) != NULL ) { + /* convert 'path@hostname' to 'hostname:path', + * call getnfsquota(), + * convert 'hostname:path' back to 'path@hostname' */ + *hostpath = '\0'; + sprintf(pathstring,"%s:%s",hostpath+1,vol->v_gvs); + strcpy(vol->v_gvs,pathstring); + + result = getnfsquota(vol, uuid, bsize, dq); + + hostpath = strchr(vol->v_gvs,':'); + *hostpath = '\0'; + sprintf(pathstring,"%s@%s",hostpath+1,vol->v_gvs); + strcpy(vol->v_gvs,pathstring); + + return result; + } + else + /* vol->v_gvs is of the form 'hostname:path' */ + return getnfsquota(vol, uuid, bsize, dq); + } else + /* local filesystem */ + return getfsquota(obj, vol, obj->uid, dq); + +#else /* TRU64 */ + return vol->v_nfs ? getnfsquota(vol, obj->uid, bsize, dq) : + getfsquota(obj, vol, obj->uid, dq); +#endif /* TRU64 */ +} + +static int overquota( struct dqblk *dqblk) +{ + struct timeval tv; + + if ( dqblk->dqb_curblocks > dqblk->dqb_bhardlimit && + dqblk->dqb_bhardlimit != 0 ) { + return( 1 ); + } + + if ( dqblk->dqb_curblocks < dqblk->dqb_bsoftlimit || + dqblk->dqb_bsoftlimit == 0 ) { + return( 0 ); + } +#ifdef ultrix + if ( dqblk->dqb_bwarn ) { + return( 0 ); + } +#else /* ultrix */ + if ( gettimeofday( &tv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "overquota: gettimeofday: %s", strerror(errno) ); + return( AFPERR_PARAM ); + } + if ( dqblk->dqb_btimelimit && dqblk->dqb_btimelimit > tv.tv_sec ) { + return( 0 ); + } +#endif /* ultrix */ + return( 1 ); +} + +/* + * This next bit is basically for linux -- everything is fine + * if you use 1k blocks... but if you try (for example) to mount + * a volume via nfs from a netapp (which might use 4k blocks) everything + * gets reported improperly. I have no idea about dbtob on other + * platforms. + */ + +#ifdef HAVE_BROKEN_DBTOB +#undef dbtob +#define dbtob(a, b) ((VolSpace)((VolSpace)(a) * (VolSpace)(b))) +#define HAVE_2ARG_DBTOB +#endif + +#ifndef dbtob +#define dbtob(a) ((a) << 10) +#endif + +/* i do the cast to VolSpace here to make sure that 64-bit shifts + work */ +#ifdef HAVE_2ARG_DBTOB +#define tobytes(a, b) dbtob((VolSpace) (a), (VolSpace) (b)) +#else +#define tobytes(a, b) dbtob((VolSpace) (a)) +#endif + +int uquota_getvolspace(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal, const uint32_t bsize) +{ + uint64_t this_bsize; + struct dqblk dqblk; + + this_bsize = bsize; + + if (getquota(obj, vol, &dqblk, bsize) != 0 ) { + return( AFPERR_PARAM ); + } + +#ifdef linux + this_bsize = dqblk.bsize; +#endif + +#ifdef DEBUG_QUOTA + LOG(log_debug, logtype_afpd, "after calling getquota in uquota_getvolspace!" ); + LOG(log_debug, logtype_afpd, "dqb_ihardlimit: %u", dqblk.dqb_ihardlimit ); + LOG(log_debug, logtype_afpd, "dqb_isoftlimit: %u", dqblk.dqb_isoftlimit ); + LOG(log_debug, logtype_afpd, "dqb_curinodes : %u", dqblk.dqb_curinodes ); + LOG(log_debug, logtype_afpd, "dqb_bhardlimit: %u", dqblk.dqb_bhardlimit ); + LOG(log_debug, logtype_afpd, "dqb_bsoftlimit: %u", dqblk.dqb_bsoftlimit ); + LOG(log_debug, logtype_afpd, "dqb_curblocks : %u", dqblk.dqb_curblocks ); + LOG(log_debug, logtype_afpd, "dqb_btime : %u", dqblk.dqb_btime ); + LOG(log_debug, logtype_afpd, "dqb_itime : %u", dqblk.dqb_itime ); + LOG(log_debug, logtype_afpd, "bsize/this_bsize : %u/%u", bsize, this_bsize ); + LOG(log_debug, logtype_afpd, "dqblk.dqb_bhardlimit size: %u", tobytes( dqblk.dqb_bhardlimit, this_bsize )); + LOG(log_debug, logtype_afpd, "dqblk.dqb_bsoftlimit size: %u", tobytes( dqblk.dqb_bsoftlimit, this_bsize )); + LOG(log_debug, logtype_afpd, "dqblk.dqb_curblocks size: %u", tobytes( dqblk.dqb_curblocks, this_bsize )); +#endif /* DEBUG_QUOTA */ + + /* no limit set for this user. it might be set in the future. */ + if (dqblk.dqb_bsoftlimit == 0 && dqblk.dqb_bhardlimit == 0) { + *btotal = *bfree = ~((VolSpace) 0); + } else if ( overquota( &dqblk )) { + if ( tobytes( dqblk.dqb_curblocks, this_bsize ) > tobytes( dqblk.dqb_bsoftlimit, this_bsize ) ) { + *btotal = tobytes( dqblk.dqb_curblocks, this_bsize ); + *bfree = 0; + } + else { + *btotal = tobytes( dqblk.dqb_bsoftlimit, this_bsize ); + *bfree = tobytes( dqblk.dqb_bsoftlimit, this_bsize ) - + tobytes( dqblk.dqb_curblocks, this_bsize ); + } + } else { + *btotal = tobytes( dqblk.dqb_bhardlimit, this_bsize ); + *bfree = tobytes( dqblk.dqb_bhardlimit, this_bsize ) - + tobytes( dqblk.dqb_curblocks, this_bsize ); + } + +#ifdef DEBUG_QUOTA + LOG(log_debug, logtype_afpd, "bfree : %u", *bfree ); + LOG(log_debug, logtype_afpd, "btotal : %u", *btotal ); + LOG(log_debug, logtype_afpd, "bfree : %uKB", *bfree/1024 ); + LOG(log_debug, logtype_afpd, "btotal : %uKB", *btotal/1024 ); +#endif + + return( AFP_OK ); +} +#endif /* HAVE_LIBQUOTA */ +#endif diff --git a/etc/afpd/spotlight.c b/etc/afpd/spotlight.c new file mode 100644 index 0000000..4aabeca --- /dev/null +++ b/etc/afpd/spotlight.c @@ -0,0 +1,1454 @@ +/* + Copyright (c) 2012-2014 Ralph Boehme + + 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. +*/ + +#define USE_LIST + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "directory.h" +#include "etc/spotlight/sparql_parser.h" + +#include + +#define MAX_SL_RESULTS 20 + +struct slq_state_names { + slq_state_t state; + const char *state_name; +}; + +static struct slq_state_names slq_state_names[] = { + {SLQ_STATE_NEW, "SLQ_STATE_NEW"}, + {SLQ_STATE_RUNNING, "SLQ_STATE_RUNNING"}, + {SLQ_STATE_RESULTS, "SLQ_STATE_RESULTS"}, + {SLQ_STATE_FULL, "SLQ_STATE_FULL"}, + {SLQ_STATE_DONE, "SLQ_STATE_DONE"}, + {SLQ_STATE_CANCEL_PENDING, "SLQ_STATE_CANCEL_PENDING"}, + {SLQ_STATE_CANCELLED, "SLQ_STATE_CANCELLED"}, + {SLQ_STATE_ERROR, "SLQ_STATE_ERROR"} +}; + + +static char *tracker_to_unix_path(TALLOC_CTX *mem_ctx, const char *uri); +static int cnid_comp_fn(const void *p1, const void *p2); +static bool create_result_handle(slq_t *slq); +static bool add_filemeta(sl_array_t *reqinfo, + sl_array_t *fm_array, + const char *path, + const struct stat *sp); + +/************************************************ + * Misc utility functions + ************************************************/ + +static char *tab_level(TALLOC_CTX *mem_ctx, int level) +{ + int i; + char *string = talloc_array(mem_ctx, char, level + 1); + + for (i = 0; i < level; i++) { + string[i] = '\t'; + } + + string[i] = '\0'; + return string; +} + +static char *dd_dump(DALLOC_CTX *dd, int nestinglevel) +{ + const char *type; + int n; + uint64_t i; + sl_bool_t bl; + sl_time_t t; + struct tm *tm; + char datestring[256]; + sl_cnids_t cnids; + char *logstring, *nested_logstring; + char *tab_string1, *tab_string2; + + tab_string1 = tab_level(dd, nestinglevel); + tab_string2 = tab_level(dd, nestinglevel + 1); + if (tab_string1 == NULL || tab_string2 == NULL) { + return NULL; + } + + logstring = talloc_asprintf(dd, + "%s%s(#%lu): {\n", + tab_string1, + talloc_get_name(dd), + talloc_array_length(dd->dd_talloc_array)); + + for (n = 0; n < talloc_array_length(dd->dd_talloc_array); n++) { + type = talloc_get_name(dd->dd_talloc_array[n]); + if (strequal(type, "DALLOC_CTX") + || strequal(type, "sl_array_t") + || strequal(type, "sl_filemeta_t") + || strequal(type, "sl_dict_t")) { + nested_logstring = dd_dump(dd->dd_talloc_array[n], + nestinglevel + 1); + if (!nested_logstring) { + return NULL; + } + logstring = talloc_strdup_append(logstring, + nested_logstring); + if (!logstring) { + return NULL; + } + } else if (strequal(type, "uint64_t")) { + memcpy(&i, dd->dd_talloc_array[n], sizeof(uint64_t)); + logstring = talloc_asprintf_append( + logstring, + "%suint64_t: 0x%04" PRIx64 "\n", + tab_string2, i); + if (!logstring) { + return NULL; + } + } else if (strequal(type, "char *")) { + logstring = talloc_asprintf_append( + logstring, + "%sstring: %s\n", + tab_string2, + (char *)dd->dd_talloc_array[n]); + if (!logstring) { + return NULL; + } + } else if (strequal(type, "smb_ucs2_t *")) { + logstring = talloc_asprintf_append( + logstring, + "%sUTF16-string: %s\n", + tab_string2, + (char *)dd->dd_talloc_array[n]); + if (!logstring) { + return NULL; + } + } else if (strequal(type, "sl_bool_t")) { + memcpy(&bl, dd->dd_talloc_array[n], sizeof(sl_bool_t)); + logstring = talloc_asprintf_append( + logstring, + "%sbool: %s\n", + tab_string2, + bl ? "true" : "false"); + if (!logstring) { + return NULL; + } + } else if (strequal(type, "sl_nil_t")) { + logstring = talloc_asprintf_append( + logstring, + "%snil\n", + tab_string2); + if (!logstring) { + return NULL; + } + } else if (strequal(type, "sl_time_t")) { + memcpy(&t, dd->dd_talloc_array[n], sizeof(sl_time_t)); + tm = localtime(&t.tv_sec); + strftime(datestring, + sizeof(datestring), + "%Y-%m-%d %H:%M:%S", tm); + logstring = talloc_asprintf_append( + logstring, + "%ssl_time_t: %s.%06lu\n", + tab_string2, + datestring, + (unsigned long)t.tv_usec); + if (!logstring) { + return NULL; + } + } else if (strequal(type, "sl_cnids_t")) { + memcpy(&cnids, dd->dd_talloc_array[n], sizeof(sl_cnids_t)); + logstring = talloc_asprintf_append( + logstring, + "%sCNIDs: unkn1: 0x%" PRIx16 ", unkn2: 0x%" PRIx32 "\n", + tab_string2, + cnids.ca_unkn1, + cnids.ca_context); + if (!logstring) { + return NULL; + } + if (cnids.ca_cnids) { + nested_logstring = dd_dump( + cnids.ca_cnids, + nestinglevel + 2); + if (!nested_logstring) { + return NULL; + } + logstring = talloc_strdup_append(logstring, + nested_logstring); + if (!logstring) { + return NULL; + } + } + } else { + logstring = talloc_asprintf_append( + logstring, + "%stype: %s\n", + tab_string2, + type); + if (!logstring) { + return NULL; + } + } + } + logstring = talloc_asprintf_append(logstring, + "%s}\n", + tab_string1); + if (!logstring) { + return NULL; + } + return logstring; +} + +static int cnid_comp_fn(const void *p1, const void *p2) +{ + const uint64_t *cnid1 = p1, *cnid2 = p2; + if (*cnid1 == *cnid2) { + return 0; + } + if (*cnid1 < *cnid2) { + return -1; + } + return 1; +} + +static int sl_createCNIDArray(slq_t *slq, const DALLOC_CTX *p) +{ + EC_INIT; + uint64_t *cnids = NULL; + + EC_NULL( cnids = talloc_array(slq, uint64_t, talloc_array_length(p)) ); + + for (int i = 0; i < talloc_array_length(p); i++) { + memcpy(&cnids[i], p->dd_talloc_array[i], sizeof(uint64_t)); + } + qsort(cnids, talloc_array_length(p), sizeof(uint64_t), cnid_comp_fn); + + slq->slq_cnids = cnids; + slq->slq_cnids_num = talloc_array_length(p); + +EC_CLEANUP: + if (ret != 0) { + if (cnids) + talloc_free(cnids); + } + EC_EXIT; +} + +static char *tracker_to_unix_path(TALLOC_CTX *mem_ctx, const char *uri) +{ + GFile *f; + char *path; + char *talloc_path = NULL; + + f = g_file_new_for_uri(uri); + if (!f) { + return NULL; + } + + path = g_file_get_path(f); + g_object_unref(f); + + if (!path) { + return NULL; + } + + talloc_path = talloc_strdup(mem_ctx, path); + g_free(path); + + return talloc_path; +} + +/** + * Add requested metadata for a query result element + * + * This could be rewritten to something more sophisticated like + * querying metadata from Tracker. + * + * If path or sp is NULL, simply add nil values for all attributes. + **/ +static bool add_filemeta(sl_array_t *reqinfo, + sl_array_t *fm_array, + const char *path, + const struct stat *sp) +{ + sl_array_t *meta; + sl_nil_t nil; + int i, metacount; + uint64_t uint64var; + sl_time_t sl_time; + char *p, *name; + + metacount = talloc_array_length(reqinfo->dd_talloc_array); + if (metacount == 0 || path == NULL || sp == NULL) { + dalloc_add_copy(fm_array, &nil, sl_nil_t); + return true; + } + + meta = talloc_zero(fm_array, sl_array_t); + + for (i = 0; i < metacount; i++) { + if (strequal(reqinfo->dd_talloc_array[i], "kMDItemDisplayName") + || strequal(reqinfo->dd_talloc_array[i], "kMDItemFSName")) { + if ((p = strrchr(path, '/'))) { + name = dalloc_strdup(meta, p + 1); + dalloc_add(meta, name, "char *"); + } + } else if (strequal(reqinfo->dd_talloc_array[i], + "kMDItemPath")) { + name = dalloc_strdup(meta, path); + dalloc_add(meta, name, "char *"); + } else if (strequal(reqinfo->dd_talloc_array[i], + "kMDItemFSSize")) { + uint64var = sp->st_size; + dalloc_add_copy(meta, &uint64var, uint64_t); + } else if (strequal(reqinfo->dd_talloc_array[i], + "kMDItemFSOwnerUserID")) { + uint64var = sp->st_uid; + dalloc_add_copy(meta, &uint64var, uint64_t); + } else if (strequal(reqinfo->dd_talloc_array[i], + "kMDItemFSOwnerGroupID")) { + uint64var = sp->st_gid; + dalloc_add_copy(meta, &uint64var, uint64_t); + } else if (strequal(reqinfo->dd_talloc_array[i], + "kMDItemFSContentChangeDate")) { + sl_time.tv_sec = sp->st_mtime; + dalloc_add_copy(meta, &sl_time, sl_time_t); + } else { + dalloc_add_copy(meta, &nil, sl_nil_t); + } + } + + dalloc_add(fm_array, meta, sl_array_t); + return true; +} + +/** + * Allocate result handle used in the async Tracker cursor result + * handler for storing results + **/ +static bool create_result_handle(slq_t *slq) +{ + sl_nil_t nil = 0; + struct sl_rslts *query_results; + + if (slq->query_results) { + LOG(log_error, logtype_sl,"unexpected existing result handle"); + return false; + } + + query_results = talloc_zero(slq, struct sl_rslts); + + /* CNIDs */ + query_results->cnids = talloc_zero(query_results, sl_cnids_t); + if (query_results->cnids == NULL) { + return false; + } + query_results->cnids->ca_cnids = talloc_zero(query_results->cnids, + DALLOC_CTX); + if (query_results->cnids->ca_cnids == NULL) { + return false; + } + + query_results->cnids->ca_unkn1 = 0xadd; + query_results->cnids->ca_context = slq->slq_ctx2; + + /* FileMeta */ + query_results->fm_array = talloc_zero(query_results, sl_array_t); + if (query_results->fm_array == NULL) { + return false; + } + + /* For some reason the list of results always starts with a nil entry */ + dalloc_add_copy(query_results->fm_array, &nil, sl_nil_t); + + slq->query_results = query_results; + return true; +} + +static bool add_results(sl_array_t *array, slq_t *slq) +{ + sl_filemeta_t *fm; + uint64_t status; + + /* FileMeta */ + fm = talloc_zero(array, sl_filemeta_t); + if (!fm) { + return false; + } + + switch (slq->slq_state) { + case SLQ_STATE_RUNNING: + /* + * Wtf, why 35? Taken from an AFP capture. + */ + status = 35; + break; + + default: + status = 0; + break; + } + + dalloc_add_copy(array, &status, uint64_t); + dalloc_add(array, slq->query_results->cnids, sl_cnids_t); + if (slq->query_results->num_results > 0) { + dalloc_add(fm, slq->query_results->fm_array, sl_array_t); + } + dalloc_add(array, fm, sl_filemeta_t); + + /* This ensure the results get clean up after been sent to the client */ + talloc_steal(array, slq->query_results); + slq->query_results = NULL; + + if (!create_result_handle(slq)) { + LOG(log_error, logtype_sl, "couldn't add result handle"); + slq->slq_state = SLQ_STATE_ERROR; + return false; + } + + return true; +} + +/****************************************************************************** + * Spotlight queries + ******************************************************************************/ + +static ATALK_LIST_HEAD(sl_queries); +static ATALK_LIST_HEAD(sl_cancelled_queries); + +/** + * Add a query to the list of active queries + **/ +static void slq_add(slq_t *slq) +{ + list_add(&(slq->slq_list), &sl_queries); +} + +/** + * Add a query to the list of active queries + **/ +static void slq_cancelled_add(slq_t *slq) +{ + list_add(&(slq->slq_list), &sl_cancelled_queries); +} + +/** + * Remove a query from the active list + **/ +static void slq_remove(slq_t *slq) +{ + struct list_head *p; + slq_t *q = NULL; + + list_for_each(p, &sl_queries) { + q = list_entry(p, slq_t, slq_list); + if ((q->slq_ctx1 == slq->slq_ctx1) && (q->slq_ctx2 == slq->slq_ctx2)) { + list_del(p); + break; + } + } + + return; +} + +static slq_t *slq_for_ctx(uint64_t ctx1, uint64_t ctx2) +{ + slq_t *q = NULL; + struct list_head *p; + + list_for_each(p, &sl_queries) { + q = list_entry(p, slq_t, slq_list); + if ((q->slq_ctx1 == ctx1) && (q->slq_ctx2 == ctx2)) { + break; + } + q = NULL; + } + + return q; +} + +/** + * Remove a query from the active queue and free it + **/ +static void slq_destroy(slq_t *slq) +{ + if (slq == NULL) { + return; + } + slq_remove(slq); + talloc_free(slq); +} + +/** + * Cancel a query + **/ +static void slq_cancel(slq_t *slq) +{ + slq->slq_state = SLQ_STATE_CANCEL_PENDING; + slq_remove(slq); + slq_cancelled_add(slq); +} + +/** + * talloc destructor cb + **/ +static int slq_free_cb(slq_t *slq) +{ + if (slq->tracker_cursor) { + g_object_unref(slq->tracker_cursor); + } + return 0; +} + +/** + * Free all cancelled queries + **/ +static void slq_cancelled_cleanup(void) +{ + struct list_head *p; + slq_t *q = NULL; + + list_for_each(p, &sl_cancelled_queries) { + q = list_entry(p, slq_t, slq_list); + if (q->slq_state == SLQ_STATE_CANCELLED) { + LOG(log_debug, logtype_sl, + "ctx1: %" PRIx64 ", ctx2: %" PRIx64 ": cancelled", + q->slq_ctx1, q->slq_ctx2); + list_del(p); + talloc_free(q); + } else { + LOG(log_debug, logtype_sl, + "ctx1: %" PRIx64 ", ctx2: %" PRIx64 ": %s", + q->slq_ctx1, q->slq_ctx2, slq_state_names[q->slq_state].state_name); + } + } + + return; +} + +static void slq_dump(void) +{ + struct list_head *p; + slq_t *q = NULL; + int i = 0; + + list_for_each(p, &sl_queries) { + q = list_entry(p, slq_t, slq_list); + LOG(log_debug, logtype_sl, + "query[%d]: ctx1: %" PRIx64 ", ctx2: %" PRIx64 ", state: %s", + i++, q->slq_ctx1, q->slq_ctx2, + slq_state_names[q->slq_state].state_name); + } + + return; +} + +/************************************************ + * Tracker async callbacks + ************************************************/ + +static void tracker_con_cb(GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + struct sl_ctx *sl_ctx = user_data; + GError *error = NULL; + + sl_ctx->tracker_con = tracker_sparql_connection_get_finish(res, + &error); + if (error) { + LOG(log_error, logtype_sl, "Could not connect to Tracker: %s", + error->message); + sl_ctx->tracker_con = NULL; + g_error_free(error); + return; + } + + LOG(log_info, logtype_sl, "connected to Tracker"); +} + +static void tracker_cursor_cb(GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + slq_t *slq = user_data; + gboolean more_results; + const gchar *uri; + char *path; + int result; + struct stat sb; + uint64_t uint64var; + bool ok; + cnid_t did, id; + + LOG(log_debug, logtype_sl, + "cursor cb[%d]: ctx1: %" PRIx64 ", ctx2: %" PRIx64, + slq->query_results->num_results, slq->slq_ctx1, slq->slq_ctx2); + + more_results = tracker_sparql_cursor_next_finish(slq->tracker_cursor, + res, + &error); + + if (slq->slq_state == SLQ_STATE_CANCEL_PENDING) { + LOG(log_debug, logtype_sl, + "cursor cb: ctx1: %" PRIx64 ", ctx2: %" PRIx64 ": cancelled", + slq->slq_ctx1, slq->slq_ctx2); + slq->slq_state = SLQ_STATE_CANCELLED; + return; + } + + if (error) { + LOG(log_error, logtype_sl, "Tracker cursor: %s", error->message); + g_error_free(error); + slq->slq_state = SLQ_STATE_ERROR; + return; + } + + if (!more_results) { + LOG(log_debug, logtype_sl, "tracker_cursor_cb: done"); + slq->slq_state = SLQ_STATE_DONE; + return; + } + + uri = tracker_sparql_cursor_get_string(slq->tracker_cursor, 0, NULL); + if (uri == NULL) { + /* + * Not sure how this could happen if + * tracker_sparql_cursor_next_finish() returns true, but I've + * seen it. + */ + LOG(log_debug, logtype_sl, "no URI for result"); + return; + } + + LOG(log_debug, logtype_sl, "URI: %s", uri); + + path = tracker_to_unix_path(slq->query_results, uri); + if (path == NULL) { + LOG(log_error, logtype_sl, "error converting Tracker URI: %s", uri); + slq->slq_state = SLQ_STATE_ERROR; + return; + } + + result = access(path, R_OK); + if (result != 0) { + goto exit; + } + + id = cnid_for_path(slq->slq_vol->v_cdb, slq->slq_vol->v_path, path, &did); + if (id == CNID_INVALID) { + LOG(log_error, logtype_sl, "cnid_for_path error: %s", path); + goto exit; + } + uint64var = ntohl(id); + + if (slq->slq_cnids) { + ok = bsearch(&uint64var, slq->slq_cnids, slq->slq_cnids_num, + sizeof(uint64_t), cnid_comp_fn); + if (!ok) { + goto exit; + } + } + + dalloc_add_copy(slq->query_results->cnids->ca_cnids, + &uint64var, uint64_t); + ok = add_filemeta(slq->slq_reqinfo, slq->query_results->fm_array, + path, &sb); + if (!ok) { + LOG(log_error, logtype_sl, "add_filemeta error"); + slq->slq_state = SLQ_STATE_ERROR; + return; + } + + slq->query_results->num_results++; + +exit: + if (slq->query_results->num_results < MAX_SL_RESULTS) { + LOG(log_debug, logtype_sl, + "cursor cb[%d]: ctx1: %" PRIx64 ", ctx2: %" PRIx64 ": requesting more results", + slq->query_results->num_results - 1, slq->slq_ctx1, slq->slq_ctx2); + + slq->slq_state = SLQ_STATE_RESULTS; + + tracker_sparql_cursor_next_async(slq->tracker_cursor, + slq->slq_obj->sl_ctx->cancellable, + tracker_cursor_cb, + slq); + } else { + LOG(log_debug, logtype_sl, + "cursor cb[%d]: ctx1: %" PRIx64 ", ctx2: %" PRIx64 ": full", + slq->query_results->num_results - 1, slq->slq_ctx1, slq->slq_ctx2); + + slq->slq_state = SLQ_STATE_FULL; + } +} + +static void tracker_query_cb(GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + slq_t *slq = user_data; + + LOG(log_debug, logtype_sl, + "query cb: ctx1: %" PRIx64 ", ctx2: %" PRIx64, + slq->slq_ctx1, slq->slq_ctx2); + + slq->tracker_cursor = tracker_sparql_connection_query_finish( + TRACKER_SPARQL_CONNECTION(object), + res, + &error); + + if (slq->slq_state == SLQ_STATE_CANCEL_PENDING) { + slq->slq_state = SLQ_STATE_CANCELLED; + return; + } + + if (error) { + slq->slq_state = SLQ_STATE_ERROR; + LOG(log_error, logtype_sl, "Tracker query error: %s", error->message); + g_error_free(error); + return; + } + + slq->slq_state = SLQ_STATE_RESULTS; + + tracker_sparql_cursor_next_async(slq->tracker_cursor, + slq->slq_obj->sl_ctx->cancellable, + tracker_cursor_cb, + slq); +} + +/******************************************************************************* + * Spotlight RPC functions + ******************************************************************************/ + +static int sl_rpc_fetchPropertiesForContext(const AFPObj *obj, + const DALLOC_CTX *query, + DALLOC_CTX *reply, + const struct vol *v) +{ + EC_INIT; + + char *s; + sl_dict_t *dict; + sl_array_t *array; + sl_uuid_t uuid; + + if (!v->v_uuid) { + EC_FAIL_LOG("missing UUID for volume: %s", v->v_localname); + } + dict = talloc_zero(reply, sl_dict_t); + + /* key/val 1 */ + s = dalloc_strdup(dict, "kMDSStoreMetaScopes"); + dalloc_add(dict, s, char *); + + array = talloc_zero(dict, sl_array_t); + s = dalloc_strdup(array, "kMDQueryScopeComputer"); + dalloc_add(array, s, char *); + dalloc_add(dict, array, sl_array_t); + + /* key/val 2 */ + s = dalloc_strdup(dict, "kMDSStorePathScopes"); + dalloc_add(dict, s, char *); + + array = talloc_zero(dict, sl_array_t); + s = dalloc_strdup(array, v->v_path); + dalloc_add(array, s, char *); + dalloc_add(dict, array, sl_array_t); + + /* key/val 3 */ + s = dalloc_strdup(dict, "kMDSStoreUUID"); + dalloc_add(dict, s, char *); + + memcpy(uuid.sl_uuid, v->v_uuid, 16); + dalloc_add_copy(dict, &uuid, sl_uuid_t); + + /* key/val 4 */ + s = dalloc_strdup(dict, "kMDSStoreHasPersistentUUID"); + dalloc_add(dict, s, char *); + sl_bool_t b = true; + dalloc_add_copy(dict, &b, sl_bool_t); + + dalloc_add(reply, dict, sl_dict_t); + +EC_CLEANUP: + EC_EXIT; +} + +static int sl_rpc_openQuery(AFPObj *obj, + const DALLOC_CTX *query, + DALLOC_CTX *reply, + struct vol *v) +{ + EC_INIT; + char *sl_query; + uint64_t *uint64; + DALLOC_CTX *reqinfo; + sl_array_t *array; + sl_cnids_t *cnids; + slq_t *slq; + char slq_host[MAXPATHLEN + 1]; + uint16_t convflags = v->v_mtou_flags; + uint64_t result; + gchar *sparql_query; + GError *error = NULL; + bool ok; + sl_array_t *scope_array; + + array = talloc_zero(reply, sl_array_t); + + if (obj->sl_ctx->tracker_con == NULL) { + LOG(log_error, logtype_sl, "no tracker connection"); + EC_FAIL; + } + + /* Allocate and initialize query object */ + slq = talloc_zero(obj->sl_ctx, slq_t); + slq->slq_state = SLQ_STATE_NEW; + slq->slq_obj = obj; + slq->slq_vol = v; + slq->slq_allow_expr = obj->options.flags & OPTION_SPOTLIGHT_EXPR ? true : false; + slq->slq_result_limit = obj->options.sparql_limit; + talloc_set_destructor(slq, slq_free_cb); + + LOG(log_debug, logtype_sl, "Spotlight: expr: %s, limit: %" PRIu64, + slq->slq_allow_expr ? "yes" : "no", slq->slq_result_limit); + + /* convert spotlight query charset to host charset */ + sl_query = dalloc_value_for_key(query, "DALLOC_CTX", 0, + "DALLOC_CTX", 1, + "kMDQueryString"); + if (sl_query == NULL) { + EC_FAIL; + } + ret = convert_charset(CH_UTF8_MAC, v->v_volcharset, v->v_maccharset, + sl_query, strlen(sl_query), slq_host, MAXPATHLEN, + &convflags); + if (ret == -1) { + LOG(log_error, logtype_sl, "charset conversion failed"); + EC_FAIL; + } + slq->slq_qstring = talloc_strdup(slq, slq_host); + LOG(log_debug, logtype_sl, "Spotlight query: \"%s\"", slq->slq_qstring); + + slq->slq_time = time(NULL); + uint64 = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0, "uint64_t", 1); + if (uint64 == NULL) { + EC_FAIL; + } + slq->slq_ctx1 = *uint64; + + uint64 = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0, "uint64_t", 2); + if (uint64 == NULL) { + EC_FAIL; + } + slq->slq_ctx2 = *uint64; + + reqinfo = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, + "kMDAttributeArray"); + if (reqinfo == NULL) { + EC_FAIL; + } + slq->slq_reqinfo = talloc_steal(slq, reqinfo); + + scope_array = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, + "kMDScopeArray"); + if (scope_array == NULL) { + slq->slq_scope = talloc_strdup(slq, v->v_path); + } else { + slq->slq_scope = talloc_strdup(slq, scope_array->dd_talloc_array[0]); + } + if (slq->slq_scope == NULL) { + LOG(log_error, logtype_sl, "failed to setup search scope"); + EC_FAIL; + } + + LOG(log_debug, logtype_sl, "Search scope: \"%s\"", slq->slq_scope); + + cnids = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, + "kMDQueryItemArray"); + if (cnids) { + EC_ZERO_LOG( sl_createCNIDArray(slq, cnids->ca_cnids) ); + } + + ret = map_spotlight_to_sparql_query(slq, &sparql_query); + if (ret != 0) { + LOG(log_debug, logtype_sl, "mapping retured non-zero"); + EC_FAIL; + } + LOG(log_debug, logtype_sl, "SPARQL query: \"%s\"", sparql_query); + + tracker_sparql_connection_query_async(obj->sl_ctx->tracker_con, + sparql_query, + slq->slq_obj->sl_ctx->cancellable, + tracker_query_cb, + slq); + if (error) { + LOG(log_error, logtype_sl, "Couldn't query the Tracker Store: '%s'", + error->message); + g_clear_error(&error); + EC_FAIL; + } + + slq->slq_state = SLQ_STATE_RUNNING; + + ok = create_result_handle(slq); + if (!ok) { + LOG(log_error, logtype_sl, "create_result_handle error"); + slq->slq_state = SLQ_STATE_ERROR; + EC_FAIL; + } + + slq_add(slq); + +EC_CLEANUP: + if (ret != 0) { + slq_destroy(slq); + result = UINT64_MAX; + ret = 0; + } else { + result = 0; + } + + dalloc_add_copy(array, &result, uint64_t); + dalloc_add(reply, array, sl_array_t); + EC_EXIT; +} + +static int sl_rpc_fetchQueryResultsForContext(const AFPObj *obj, + const DALLOC_CTX *query, + DALLOC_CTX *reply, + const struct vol *v) +{ + EC_INIT; + slq_t *slq = NULL; + uint64_t *uint64, ctx1, ctx2, status; + sl_array_t *array; + bool ok; + + array = talloc_zero(reply, sl_array_t); + if (array == NULL) { + return false; + } + + /* Context */ + uint64 = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0, "uint64_t", 1); + if (uint64 == NULL) { + EC_FAIL; + } + ctx1 = *uint64; + uint64 = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0, "uint64_t", 2); + if (uint64 == NULL) { + EC_FAIL; + } + ctx2 = *uint64; + + /* Get query for context */ + slq = slq_for_ctx(ctx1, ctx2); + if (slq == NULL) { + EC_FAIL; + } + + switch (slq->slq_state) { + case SLQ_STATE_RUNNING: + case SLQ_STATE_RESULTS: + case SLQ_STATE_FULL: + case SLQ_STATE_DONE: + ok = add_results(array, slq); + if (!ok) { + LOG(log_error, logtype_sl, "error adding results"); + EC_FAIL; + } + if (slq->slq_state == SLQ_STATE_FULL) { + slq->slq_state = SLQ_STATE_RESULTS; + + tracker_sparql_cursor_next_async( + slq->tracker_cursor, + slq->slq_obj->sl_ctx->cancellable, + tracker_cursor_cb, + slq); + } + break; + + case SLQ_STATE_ERROR: + LOG(log_error, logtype_sl, "query in error state"); + EC_FAIL; + + default: + LOG(log_error, logtype_sl, "unexpected query state %d", slq->slq_state); + EC_FAIL; + } + + dalloc_add(reply, array, sl_array_t); + EC_EXIT; + +EC_CLEANUP: + slq_destroy(slq); + status = UINT64_MAX; + dalloc_add_copy(array, &status, uint64_t); + dalloc_add(reply, array, sl_array_t); + EC_EXIT; +} + +static int sl_rpc_storeAttributesForOIDArray(const AFPObj *obj, + const DALLOC_CTX *query, + DALLOC_CTX *reply, + const struct vol *vol) +{ + EC_INIT; + uint64_t uint64; + sl_array_t *array; + sl_cnids_t *cnids; + sl_time_t *sl_time; + cnid_t id; + char *path; + struct dir *dir; + + EC_NULL_LOG( cnids = dalloc_get(query, "DALLOC_CTX", 0, "sl_cnids_t", 2) ); + memcpy(&uint64, cnids->ca_cnids->dd_talloc_array[0], sizeof(uint64_t)); + id = (cnid_t)uint64; + LOG(log_debug, logtype_sl, "CNID: %" PRIu32, id); + + if (htonl(id) == DIRDID_ROOT) { + path = vol->v_path; + } else if (id < CNID_START) { + EC_FAIL; + } else { + cnid_t did; + char buffer[12 + MAXPATHLEN + 1]; + + did = htonl(id); + EC_NULL_LOG( path = cnid_resolve(vol->v_cdb, &did, buffer, sizeof(buffer)) ); + EC_NULL_LOG( dir = dirlookup(vol, did) ); + EC_NEG1_LOG( movecwd(vol, dir) ); + } + + /* + * We're possibly supposed to update attributes in two places: the + * database and the filesystem. Due to the lack of documentation + * and not yet implemented database updates, we cherry pick attributes + * that seems to be candidates for updating filesystem metadata. + */ + + if ((sl_time = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, "DALLOC_CTX", 1, "kMDItemFSContentChangeDate"))) { + struct utimbuf utimes; + utimes.actime = utimes.modtime = sl_time->tv_sec; + utime(path, &utimes); + } + + array = talloc_zero(reply, sl_array_t); + uint64_t sl_res = 0; + dalloc_add_copy(array, &sl_res, uint64_t); + dalloc_add(reply, array, sl_array_t); + +EC_CLEANUP: + EC_EXIT; +} + +static int sl_rpc_fetchAttributeNamesForOIDArray(const AFPObj *obj, const DALLOC_CTX *query, DALLOC_CTX *reply, const struct vol *vol) +{ + EC_INIT; + uint64_t uint64; + sl_cnids_t *cnids; + cnid_t id; + char *path; + struct dir *dir; + + EC_NULL_LOG( cnids = dalloc_get(query, "DALLOC_CTX", 0, "sl_cnids_t", 1) ); + memcpy(&uint64, cnids->ca_cnids->dd_talloc_array[0], sizeof(uint64_t)); + id = (cnid_t)uint64; + LOG(log_debug, logtype_sl, "sl_rpc_fetchAttributeNamesForOIDArray: CNID: %" PRIu32, id); + + if (htonl(id) == DIRDID_ROOT) { + path = vol->v_path; + } else if (id < CNID_START) { + EC_FAIL; + } else { + cnid_t did; + char buffer[12 + MAXPATHLEN + 1]; + + did = htonl(id); + EC_NULL_LOG( path = cnid_resolve(vol->v_cdb, &did, buffer, sizeof(buffer)) ); + EC_NULL_LOG( dir = dirlookup(vol, did) ); + EC_NEG1_LOG( movecwd(vol, dir) ); + } + + /* Result array */ + sl_array_t *array = talloc_zero(reply, sl_array_t); + dalloc_add(reply, array, sl_array_t); + + /* Return result value 0 */ + uint64_t sl_res = 0; + dalloc_add_copy(array, &sl_res, uint64_t); + + /* Return CNID array */ + sl_cnids_t *replycnids = talloc_zero(reply, sl_cnids_t); + replycnids->ca_cnids = talloc_zero(cnids, DALLOC_CTX); + replycnids->ca_unkn1 = 0xfec; + replycnids->ca_context = cnids->ca_context; + uint64 = (uint64_t)id; + dalloc_add_copy(replycnids->ca_cnids, &uint64, uint64_t); + dalloc_add(array, replycnids, sl_cnids_t); + + /* Return filemeta array */ + + /* + * FIXME: this should return the real attributes from all known metadata sources + * (Tracker and filesystem) + */ + sl_array_t *mdattrs = talloc_zero(reply, sl_array_t); + dalloc_add(mdattrs, dalloc_strdup(mdattrs, "kMDItemFSName"), "char *"); + dalloc_add(mdattrs, dalloc_strdup(mdattrs, "kMDItemDisplayName"), "char *"); + dalloc_add(mdattrs, dalloc_strdup(mdattrs, "kMDItemFSSize"), "char *"); + dalloc_add(mdattrs, dalloc_strdup(mdattrs, "kMDItemFSOwnerUserID"), "char *"); + dalloc_add(mdattrs, dalloc_strdup(mdattrs, "kMDItemFSOwnerGroupID"), "char *"); + dalloc_add(mdattrs, dalloc_strdup(mdattrs, "kMDItemFSContentChangeDate"), "char *"); + + sl_filemeta_t *fmeta = talloc_zero(reply, sl_filemeta_t); + dalloc_add(fmeta, mdattrs, sl_array_t); + dalloc_add(array, fmeta, sl_filemeta_t); + +EC_CLEANUP: + EC_EXIT; +} + +static int sl_rpc_fetchAttributesForOIDArray(AFPObj *obj, const DALLOC_CTX *query, DALLOC_CTX *reply, const struct vol *vol) +{ + EC_INIT; + uint64_t uint64; + sl_cnids_t *cnids, *replycnids; + cnid_t id, did; + struct dir *dir; + sl_array_t *array, *reqinfo, *fm_array; + char buffer[12 + MAXPATHLEN + 1]; + char *name, *path; + sl_filemeta_t *fm; + sl_nil_t nil; + uint64_t sl_res; + struct stat sb; + + array = talloc_zero(reply, sl_array_t); + replycnids = talloc_zero(reply, sl_cnids_t); + replycnids->ca_cnids = talloc_zero(replycnids, DALLOC_CTX); + fm = talloc_zero(array, sl_filemeta_t); + fm_array = talloc_zero(fm, sl_array_t); + + if (array == NULL || replycnids == NULL || replycnids->ca_cnids == NULL + || fm == NULL || fm_array == NULL) { + EC_FAIL; + } + + reqinfo = dalloc_get(query, "DALLOC_CTX", 0, "sl_array_t", 1); + if (reqinfo == NULL) { + EC_FAIL; + } + cnids = dalloc_get(query, "DALLOC_CTX", 0, "sl_cnids_t", 2); + if (cnids == NULL) { + EC_FAIL; + } + + memcpy(&uint64, cnids->ca_cnids->dd_talloc_array[0], sizeof(uint64_t)); + id = (cnid_t)uint64; + + if (htonl(id) == DIRDID_ROOT) { + path = talloc_strdup(reply, vol->v_path); + } else if (id < CNID_START) { + EC_FAIL; + } else { + did = htonl(id); + EC_NULL( name = cnid_resolve(vol->v_cdb, &did, buffer, sizeof(buffer)) ); + EC_NULL( dir = dirlookup(vol, did) ); + EC_NULL( path = talloc_asprintf(reply, "%s/%s", bdata(dir->d_fullpath), name) ); + } + + EC_ZERO( stat(path, &sb) ); + + sl_res = 0; + dalloc_add_copy(array, &sl_res, uint64_t); + + replycnids->ca_unkn1 = 0xfec; + replycnids->ca_context = cnids->ca_context; + uint64 = (uint64_t)id; + dalloc_add_copy(replycnids->ca_cnids, &uint64, uint64_t); + dalloc_add(array, replycnids, sl_cnids_t); + dalloc_add(fm, fm_array, fm_array_t); + dalloc_add_copy(fm_array, &nil, sl_nil_t); + add_filemeta(reqinfo, fm_array, path, &sb); + + /* Now add result */ + dalloc_add(array, fm, sl_filemeta_t); + dalloc_add(reply, array, sl_array_t); + EC_EXIT; + +EC_CLEANUP: + sl_res = UINT64_MAX; + dalloc_add_copy(array, &sl_res, uint64_t); + dalloc_add(array, fm, sl_filemeta_t); + dalloc_add(reply, array, sl_array_t); + EC_EXIT; +} + +static int sl_rpc_closeQueryForContext(const AFPObj *obj, + const DALLOC_CTX *query, + DALLOC_CTX *reply, + const struct vol *v) +{ + EC_INIT; + slq_t *slq = NULL; + uint64_t *uint64, ctx1, ctx2; + sl_array_t *array; + uint64_t sl_result; + + array = talloc_zero(reply, sl_array_t); + + /* Context */ + uint64 = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0, "uint64_t", 1); + if (uint64 == NULL) { + EC_FAIL; + } + ctx1 = *uint64; + uint64 = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0, "uint64_t", 2); + if (uint64 == NULL) { + EC_FAIL; + } + ctx2 = *uint64; + + /* Get query for context and free it */ + slq = slq_for_ctx(ctx1, ctx2); + if (slq == NULL) { + EC_FAIL; + } + + switch (slq->slq_state) { + case SLQ_STATE_FULL: + case SLQ_STATE_DONE: + case SLQ_STATE_ERROR: + LOG(log_debug, logtype_sl, "close: destroying query: state %s", + slq_state_names[slq->slq_state].state_name); + slq_destroy(slq); + break; + + case SLQ_STATE_RUNNING: + case SLQ_STATE_RESULTS: + LOG(log_debug, logtype_sl, "close: cancel query: state %s", + slq_state_names[slq->slq_state].state_name); + slq_cancel(slq); + break; + + default: + LOG(log_error, logtype_sl, "Unexpected state %d", slq->slq_state); + EC_FAIL; + } + + sl_result = 0; + +EC_CLEANUP: + if (ret != 0) { + sl_result = UINT64_MAX; + } + dalloc_add_copy(array, &sl_result, uint64_t); + dalloc_add(reply, array, sl_array_t); + EC_EXIT; +} + +/****************************************************************************** + * Spotlight functions + ******************************************************************************/ + +int spotlight_init(AFPObj *obj) +{ + static bool initialized = false; + const char *attributes; + struct sl_ctx *sl_ctx; + + if (initialized) { + return 0; + } + + LOG(log_info, logtype_sl, "Initializing Spotlight"); + + sl_ctx = talloc_zero(NULL, struct sl_ctx); + obj->sl_ctx = sl_ctx; + + attributes = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, + "spotlight attributes", NULL); + if (attributes) { + configure_spotlight_attributes(attributes); + } + + /* + * Tracker uses glibs event dispatching, so we need a mainloop + */ +#if ((GLIB_MAJOR_VERSION <= 2) && (GLIB_MINOR_VERSION < 36)) + g_type_init(); +#endif + sl_ctx->mainloop = g_main_loop_new(NULL, false); + sl_ctx->cancellable = g_cancellable_new(); + + setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=" _PATH_STATEDIR "spotlight.ipc", 1); + setenv("XDG_DATA_HOME", _PATH_STATEDIR, 0); + setenv("XDG_CACHE_HOME", _PATH_STATEDIR, 0); + setenv("TRACKER_USE_LOG_FILES", "1", 0); + + tracker_sparql_connection_get_async(sl_ctx->cancellable, + tracker_con_cb, sl_ctx); + + initialized = true; + return 0; +} + +/****************************************************************************** + * AFP functions + ******************************************************************************/ + +int afp_spotlight_rpc(AFPObj *obj, char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + EC_INIT; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + uint16_t vid; + int cmd; + struct vol *vol; + DALLOC_CTX *query; + DALLOC_CTX *reply; + char *rpccmd; + int len; + bool event; + + *rbuflen = 0; + + if (!(obj->options.flags & OPTION_SPOTLIGHT)) { + return AFPERR_NOOP; + } + + spotlight_init(obj); + slq_dump(); + + /* + * Process finished glib events + */ + event = true; + while (event) { + event = g_main_context_iteration(NULL, false); + } + slq_cancelled_cleanup(); + + ibuf += 2; + ibuflen -= 2; + + vid = SVAL(ibuf, 0); + LOG(log_debug, logtype_sl, "afp_spotlight_rpc(vid: %" PRIu16 ")", vid); + + if ((vol = getvolbyvid(vid)) == NULL) { + LOG(log_error, logtype_sl, "afp_spotlight_rpc: bad volume id: %" PRIu16 ")", vid); + ret = AFPERR_ACCESS; + goto EC_CLEANUP; + } + + /* IVAL(ibuf, 2): unknown, always 0x00008004, some flags ? */ + + cmd = RIVAL(ibuf, 6); + LOG(log_debug, logtype_sl, "afp_spotlight_rpc(cmd: %d)", cmd); + + /* IVAL(ibuf, 10: unknown, always 0x00000000 */ + + switch (cmd) { + + case SPOTLIGHT_CMD_OPEN: + case SPOTLIGHT_CMD_OPEN2: + RSIVAL(rbuf, 0, ntohs(vid)); + RSIVAL(rbuf, 4, 0); + len = strlen(vol->v_path) + 1; + strncpy(rbuf + 8, vol->v_path, len); + *rbuflen += 8 + len; + break; + + case SPOTLIGHT_CMD_FLAGS: + RSIVAL(rbuf, 0, 0x0100006b); /* Whatever this value means... flags? Helios uses 0x1eefface */ + *rbuflen += 4; + break; + + case SPOTLIGHT_CMD_RPC: + EC_NULL( query = talloc_zero(tmp_ctx, DALLOC_CTX) ); + EC_NULL( reply = talloc_zero(tmp_ctx, DALLOC_CTX) ); + EC_NEG1_LOG( sl_unpack(query, ibuf + 22) ); + + LOG(log_debug, logtype_sl, "Spotlight RPC request:\n%s", + dd_dump(query, 0)); + + EC_NULL_LOG( rpccmd = dalloc_get(query, "DALLOC_CTX", 0, "DALLOC_CTX", 0, "char *", 0) ); + + if (STRCMP(rpccmd, ==, "fetchPropertiesForContext:")) { + EC_ZERO_LOG( sl_rpc_fetchPropertiesForContext(obj, query, reply, vol) ); + } else if (STRCMP(rpccmd, ==, "openQueryWithParams:forContext:")) { + EC_ZERO_LOG( sl_rpc_openQuery(obj, query, reply, vol) ); + } else if (STRCMP(rpccmd, ==, "fetchQueryResultsForContext:")) { + EC_ZERO_LOG( sl_rpc_fetchQueryResultsForContext(obj, query, reply, vol) ); + } else if (STRCMP(rpccmd, ==, "storeAttributes:forOIDArray:context:")) { + EC_ZERO_LOG( sl_rpc_storeAttributesForOIDArray(obj, query, reply, vol) ); + } else if (STRCMP(rpccmd, ==, "fetchAttributeNamesForOIDArray:context:")) { + EC_ZERO_LOG( sl_rpc_fetchAttributeNamesForOIDArray(obj, query, reply, vol) ); + } else if (STRCMP(rpccmd, ==, "fetchAttributes:forOIDArray:context:")) { + EC_ZERO_LOG( sl_rpc_fetchAttributesForOIDArray(obj, query, reply, vol) ); + } else if (STRCMP(rpccmd, ==, "closeQueryForContext:")) { + EC_ZERO_LOG( sl_rpc_closeQueryForContext(obj, query, reply, vol) ); + } else { + LOG(log_error, logtype_sl, "afp_spotlight_rpc: unknown Spotlight RPC: %s", rpccmd); + } + + LOG(log_debug, logtype_sl, "Spotlight RPC reply dump:\n%s", + dd_dump(reply, 0)); + + memset(rbuf, 0, 4); + *rbuflen += 4; + + EC_NEG1_LOG( len = sl_pack(reply, rbuf + 4) ); + *rbuflen += len; + break; + } + +EC_CLEANUP: + talloc_free(tmp_ctx); + if (ret != AFP_OK) { + *rbuflen = 0; + return AFPERR_MISC; + } + EC_EXIT; +} diff --git a/etc/afpd/spotlight_marshalling.c b/etc/afpd/spotlight_marshalling.c new file mode 100644 index 0000000..9329dde --- /dev/null +++ b/etc/afpd/spotlight_marshalling.c @@ -0,0 +1,811 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SLQ_DAT (DSI_DATASIZ - 64) +#define MAX_SLQ_TOC 8192 + +/************************************************************************************************** + * RPC data marshalling and unmarshalling + **************************************************************************************************/ + +/* Spotlight epoch is UNIX epoch minus SPOTLIGHT_TIME_DELTA */ +#define SPOTLIGHT_TIME_DELTA INT64_C(280878921600U) + +#define SQ_TYPE_NULL 0x0000 +#define SQ_TYPE_COMPLEX 0x0200 +#define SQ_TYPE_INT64 0x8400 +#define SQ_TYPE_BOOL 0x0100 +#define SQ_TYPE_FLOAT 0x8500 +#define SQ_TYPE_DATA 0x0700 +#define SQ_TYPE_CNIDS 0x8700 +#define SQ_TYPE_UUID 0x0e00 +#define SQ_TYPE_DATE 0x8600 +#define SQ_TYPE_TOC 0x8800 + +#define SQ_CPX_TYPE_ARRAY 0x0a00 +#define SQ_CPX_TYPE_STRING 0x0c00 +#define SQ_CPX_TYPE_UTF16_STRING 0x1c00 +#define SQ_CPX_TYPE_DICT 0x0d00 +#define SQ_CPX_TYPE_CNIDS 0x1a00 +#define SQ_CPX_TYPE_FILEMETA 0x1b00 + +#define SUBQ_SAFETY_LIM 20 + +/* Forward declarations */ +static int sl_pack_loop(DALLOC_CTX *query, char *buf, int offset, char *toc_buf, int *toc_idx); +static int sl_unpack_loop(DALLOC_CTX *query, const char *buf, int offset, uint count, const uint toc_offset, const uint encoding); + +/************************************************************************************************** + * Wrapper functions for the *VAL macros with bound checking + **************************************************************************************************/ + +static int sivalc(char *buf, off_t off, off_t maxoff, uint32_t val) +{ + if (off + sizeof(val) >= maxoff) { + LOG(log_error, logtype_sl, "sivalc: off: %zd, maxoff: %zd", off, maxoff); + return -1; + } + SIVAL(buf, off, val); + return 0; +} + +static int slvalc(char *buf, off_t off, off_t maxoff, uint64_t val) +{ + if (off + sizeof(val) >= maxoff) { + LOG(log_error, logtype_sl, "slvalc: off: %zd, maxoff: %zd", off, maxoff); + return -1; + } + SLVAL(buf, off, val); + return 0; +} + +/* +* Returns the UTF-16 string encoding, by checking the 2-byte byte order mark. +* If there is no byte order mark, -1 is returned. +*/ +static uint spotlight_get_utf16_string_encoding(const char *buf, int offset, int query_length, uint encoding) { + uint utf16_encoding; + + /* Assumed encoding in absence of a bom is little endian */ + utf16_encoding = SL_ENC_LITTLE_ENDIAN; + + if (query_length >= 2) { + uint8_t le_bom[] = {0xff, 0xfe}; + uint8_t be_bom[] = {0xfe, 0xff}; + if (memcmp(le_bom, buf + offset, sizeof(uint16_t)) == 0) + utf16_encoding = SL_ENC_LITTLE_ENDIAN | SL_ENC_UTF_16; + else if (memcmp(be_bom, buf + offset, sizeof(uint16_t)) == 0) + utf16_encoding = SL_ENC_BIG_ENDIAN | SL_ENC_UTF_16; + } + + return utf16_encoding; +} + +/************************************************************************************************** + * marshalling functions + **************************************************************************************************/ + +#define SL_OFFSET_DELTA 16 + +static uint64_t sl_pack_tag(uint16_t type, uint16_t size_or_count, uint32_t val) +{ + uint64_t tag = ((uint64_t)val << 32) | ((uint64_t)type << 16) | size_or_count; + return tag; +} + +static int sl_pack_float(double d, char *buf, int offset) +{ + EC_INIT; + + union { + double d; + uint64_t w; + } ieee_fp_union; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_FLOAT, 2, 1)) ); + EC_ZERO( slvalc(buf, offset + 8, MAX_SLQ_DAT, ieee_fp_union.w) ); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset + 2 * sizeof(uint64_t); +} + +static int sl_pack_uint64(uint64_t u, char *buf, int offset) +{ + EC_INIT; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_INT64, 2, 1)) ); + EC_ZERO( slvalc(buf, offset + 8, MAX_SLQ_DAT, u) ); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset + 2 * sizeof(uint64_t); +} + +static int sl_pack_bool(sl_bool_t bl, char *buf, int offset) +{ + EC_INIT; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_BOOL, 1, bl ? 1 : 0)) ); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset + sizeof(uint64_t); +} + +static int sl_pack_nil(char *buf, int offset) +{ + EC_INIT; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_NULL, 1, 1)) ); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset + sizeof(uint64_t); +} + +static int sl_pack_date(sl_time_t t, char *buf, int offset) +{ + EC_INIT; + uint64_t data = 0; + + data = (t.tv_sec + SPOTLIGHT_TIME_DELTA) << 24; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_DATE, 2, 1)) ); + EC_ZERO( slvalc(buf, offset + 8, MAX_SLQ_DAT, data) ); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset + 2 * sizeof(uint64_t); +} + +static int sl_pack_uuid(sl_uuid_t *uuid, char *buf, int offset) +{ + EC_INIT; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_UUID, 3, 1)) ); + if (offset + 8 + 16 >= MAX_SLQ_DAT) + EC_FAIL; + memcpy(buf + offset + 8, uuid, 16); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset + sizeof(uint64_t) + 16; +} + +static int sl_pack_CNID(sl_cnids_t *cnids, char *buf, int offset, char *toc_buf, int *toc_idx) +{ + EC_INIT; + int len; + int cnid_count = talloc_array_length(cnids->ca_cnids->dd_talloc_array); + uint64_t id; + + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_CNIDS, (offset + SL_OFFSET_DELTA) / 8, 0)) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); + *toc_idx += 1; + offset += 8; + + len = cnid_count + 1; + if (cnid_count > 0) + len ++; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_CNIDS, len, 8 /* unknown meaning, but always 8 */)) ); + offset += 8; + + if (cnid_count > 0) { + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(cnids->ca_unkn1, cnid_count, cnids->ca_context)) ); + offset += 8; + + for (int i = 0; i < cnid_count; i++) { + memcpy(&id, cnids->ca_cnids->dd_talloc_array[i], sizeof(uint64_t)); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, id) ); + offset += 8; + } + } + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset; +} + +static int sl_pack_array(sl_array_t *array, char *buf, int offset, char *toc_buf, int *toc_idx) +{ + EC_INIT; + int count = talloc_array_length(array->dd_talloc_array); + int octets = (offset + SL_OFFSET_DELTA) / 8; + + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_ARRAY, octets, count)) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); + *toc_idx += 1; + offset += 8; + + EC_NEG1( offset = sl_pack_loop(array, buf, offset, toc_buf, toc_idx) ); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset; +} + +static int sl_pack_dict(sl_array_t *dict, char *buf, int offset, char *toc_buf, int *toc_idx) +{ + EC_INIT; + + EC_ZERO( slvalc(toc_buf, + *toc_idx * 8, + MAX_SLQ_TOC, + sl_pack_tag(SQ_CPX_TYPE_DICT, + (offset + SL_OFFSET_DELTA) / 8, + talloc_array_length(dict->dd_talloc_array))) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); + *toc_idx += 1; + offset += 8; + + EC_NEG1( offset = sl_pack_loop(dict, buf, offset, toc_buf, toc_idx) ); + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset; +} + +static int sl_pack_filemeta(sl_filemeta_t *fm, char *buf, int offset, char *toc_buf, int *toc_idx) +{ + EC_INIT; + int fmlen; /* lenght of filemeta */ + int saveoff = offset; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); + offset += 16; + + EC_NEG1( fmlen = sl_pack(fm, buf + offset) ); + + /* Check for empty filemeta array, if it's only 40 bytes, it's only the header but no content */ + LOG(log_debug, logtype_sl, "fmlen: %d", fmlen); + if (fmlen > 40) + offset += fmlen; + else + fmlen = 0; + + EC_ZERO( slvalc(buf, saveoff + 8, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_DATA, (fmlen / 8) + 1, 8 /* unknown meaning, but always 8 */)) ); + + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_FILEMETA, (saveoff + SL_OFFSET_DELTA) / 8, fmlen / 8)) ); + *toc_idx += 1; + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset; +} + +static int sl_pack_string(char *s, char *buf, int offset, char *toc_buf, int *toc_idx) +{ + EC_INIT; + int len, octets, used_in_last_octet; + + len = strlen(s); + octets = (len / 8) + (len & 7 ? 1 : 0); + used_in_last_octet = 8 - (octets * 8 - len); + + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_STRING, (offset + SL_OFFSET_DELTA) / 8, used_in_last_octet)) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); + *toc_idx += 1; + offset += 8; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_DATA, octets + 1, used_in_last_octet)) ); + offset += 8; + + if (offset + octets * 8 > MAX_SLQ_DAT) + EC_FAIL; + memset(buf + offset, 0, octets * 8); + strncpy(buf + offset, s, len); + offset += octets * 8; + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset; +} + +static int sl_pack_loop(DALLOC_CTX *query, char *buf, int offset, char *toc_buf, int *toc_idx) +{ + EC_INIT; + const char *type; + + for (int n = 0; n < talloc_array_length(query->dd_talloc_array); n++) { + + type = talloc_get_name(query->dd_talloc_array[n]); + + if (STRCMP(type, ==, "sl_array_t")) { + EC_NEG1( offset = sl_pack_array(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); + } else if (STRCMP(type, ==, "sl_dict_t")) { + EC_NEG1( offset = sl_pack_dict(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); + } else if (STRCMP(type, ==, "sl_filemeta_t")) { + EC_NEG1( offset = sl_pack_filemeta(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); + } else if (STRCMP(type, ==, "uint64_t")) { + uint64_t i; + memcpy(&i, query->dd_talloc_array[n], sizeof(uint64_t)); + EC_NEG1( offset = sl_pack_uint64(i, buf, offset) ); + } else if (STRCMP(type, ==, "char *")) { + EC_NEG1( offset = sl_pack_string(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); + } else if (STRCMP(type, ==, "sl_bool_t")) { + sl_bool_t bl; + memcpy(&bl, query->dd_talloc_array[n], sizeof(sl_bool_t)); + EC_NEG1( offset = sl_pack_bool(bl, buf, offset) ); + } else if (STRCMP(type, ==, "double")) { + double d; + memcpy(&d, query->dd_talloc_array[n], sizeof(double)); + EC_NEG1( offset = sl_pack_float(d, buf, offset) ); + } else if (STRCMP(type, ==, "sl_nil_t")) { + EC_NEG1( offset = sl_pack_nil(buf, offset) ); + } else if (STRCMP(type, ==, "sl_time_t")) { + sl_time_t t; + memcpy(&t, query->dd_talloc_array[n], sizeof(sl_time_t)); + EC_NEG1( offset = sl_pack_date(t, buf, offset) ); + } else if (STRCMP(type, ==, "sl_uuid_t")) { + EC_NEG1( offset = sl_pack_uuid(query->dd_talloc_array[n], buf, offset) ); + } else if (STRCMP(type, ==, "sl_cnids_t")) { + EC_NEG1( offset = sl_pack_CNID(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); + } + } + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset; +} + +/************************************************************************************************** + * unmarshalling functions + **************************************************************************************************/ + +static uint64_t sl_unpack_uint64(const char *buf, int offset, uint encoding) +{ + if (encoding == SL_ENC_LITTLE_ENDIAN) + return LVAL(buf, offset); + else + return RLVAL(buf, offset); +} + +static int sl_unpack_ints(DALLOC_CTX *query, const char *buf, int offset, uint encoding) +{ + int count, i; + uint64_t query_data64; + + query_data64 = sl_unpack_uint64(buf, offset, encoding); + count = query_data64 >> 32; + offset += 8; + + i = 0; + while (i++ < count) { + query_data64 = sl_unpack_uint64(buf, offset, encoding); + dalloc_add_copy(query, &query_data64, uint64_t); + offset += 8; + } + + return count; +} + +static int sl_unpack_date(DALLOC_CTX *query, const char *buf, int offset, uint encoding) +{ + int count, i; + uint64_t query_data64; + sl_time_t t; + + query_data64 = sl_unpack_uint64(buf, offset, encoding); + count = query_data64 >> 32; + offset += 8; + + i = 0; + while (i++ < count) { + query_data64 = sl_unpack_uint64(buf, offset, encoding) >> 24; + t.tv_sec = query_data64 - SPOTLIGHT_TIME_DELTA; + t.tv_usec = 0; + dalloc_add_copy(query, &t, sl_time_t); + offset += 8; + } + + return count; +} + +static int sl_unpack_uuid(DALLOC_CTX *query, const char *buf, int offset, uint encoding) +{ + int count, i; + uint64_t query_data64; + sl_uuid_t uuid; + query_data64 = sl_unpack_uint64(buf, offset, encoding); + count = query_data64 >> 32; + offset += 8; + + i = 0; + while (i++ < count) { + memcpy(uuid.sl_uuid, buf + offset, 16); + dalloc_add_copy(query, &uuid, sl_uuid_t); + offset += 16; + } + + return count; +} + +static int sl_unpack_floats(DALLOC_CTX *query, const char *buf, int offset, uint encoding) +{ + int count, i; + uint64_t query_data64; + union { + double d; + uint32_t w[2]; + } ieee_fp_union; + + query_data64 = sl_unpack_uint64(buf, offset, encoding); + count = query_data64 >> 32; + offset += 8; + + i = 0; + while (i++ < count) { + if (encoding == SL_ENC_LITTLE_ENDIAN) { +#ifdef WORDS_BIGENDIAN + ieee_fp_union.w[0] = IVAL(buf, offset + 4); + ieee_fp_union.w[1] = IVAL(buf, offset); +#else + ieee_fp_union.w[0] = IVAL(buf, offset); + ieee_fp_union.w[1] = IVAL(buf, offset + 4); +#endif + } else { +#ifdef WORDS_BIGENDIAN + ieee_fp_union.w[0] = RIVAL(buf, offset); + ieee_fp_union.w[1] = RIVAL(buf, offset + 4); +#else + ieee_fp_union.w[0] = RIVAL(buf, offset + 4); + ieee_fp_union.w[1] = RIVAL(buf, offset); +#endif + } + dalloc_add_copy(query, &ieee_fp_union.d, double); + offset += 8; + } + + return count; +} + +static int sl_unpack_CNID(DALLOC_CTX *query, const char *buf, int offset, int length, uint encoding) +{ + EC_INIT; + int count; + uint64_t query_data64; + sl_cnids_t *cnids; + + EC_NULL( cnids = talloc_zero(query, sl_cnids_t) ); + EC_NULL( cnids->ca_cnids = talloc_zero(cnids, DALLOC_CTX) ); + + if (length <= 16) + /* that's permitted, it's an empty array */ + goto EC_CLEANUP; + + query_data64 = sl_unpack_uint64(buf, offset, encoding); + count = query_data64 & 0xffff; + + cnids->ca_unkn1 = (query_data64 & 0xffff0000) >> 16; + cnids->ca_context = query_data64 >> 32; + + offset += 8; + + while (count --) { + query_data64 = sl_unpack_uint64(buf, offset, encoding); + dalloc_add_copy(cnids->ca_cnids, &query_data64, uint64_t); + offset += 8; + } + + dalloc_add(query, cnids, sl_cnids_t); + +EC_CLEANUP: + EC_EXIT; +} + +static const char *spotlight_get_qtype_string(uint64_t query_type) +{ + switch (query_type) { + case SQ_TYPE_NULL: + return "null"; + case SQ_TYPE_COMPLEX: + return "complex"; + case SQ_TYPE_INT64: + return "int64"; + case SQ_TYPE_BOOL: + return "bool"; + case SQ_TYPE_FLOAT: + return "float"; + case SQ_TYPE_DATA: + return "data"; + case SQ_TYPE_CNIDS: + return "CNIDs"; + default: + return "unknown"; + } +} + +static const char *spotlight_get_cpx_qtype_string(uint64_t cpx_query_type) +{ + switch (cpx_query_type) { + case SQ_CPX_TYPE_ARRAY: + return "array"; + case SQ_CPX_TYPE_STRING: + return "string"; + case SQ_CPX_TYPE_UTF16_STRING: + return "utf-16 string"; + case SQ_CPX_TYPE_DICT: + return "dictionary"; + case SQ_CPX_TYPE_CNIDS: + return "CNIDs"; + case SQ_CPX_TYPE_FILEMETA: + return "FileMeta"; + default: + return "unknown"; + } +} + +static int sl_unpack_cpx(DALLOC_CTX *query, + const char *buf, + const int offset, + uint cpx_query_type, + uint cpx_query_count, + const uint toc_offset, + const uint encoding) +{ + EC_INIT; + + int roffset = offset; + uint64_t query_data64; + uint unicode_encoding; + uint8_t mark_exists; + char *p, *tmp; + int qlen, used_in_last_block, slen; + sl_array_t *sl_array; + sl_dict_t *sl_dict; + sl_filemeta_t *sl_fm; + + switch (cpx_query_type) { + case SQ_CPX_TYPE_ARRAY: + sl_array = talloc_zero(query, sl_array_t); + EC_NEG1_LOG( roffset = sl_unpack_loop(sl_array, buf, offset, cpx_query_count, toc_offset, encoding) ); + dalloc_add(query, sl_array, sl_array_t); + break; + + case SQ_CPX_TYPE_DICT: + sl_dict = talloc_zero(query, sl_dict_t); + EC_NEG1_LOG( roffset = sl_unpack_loop(sl_dict, buf, offset, cpx_query_count, toc_offset, encoding) ); + dalloc_add(query, sl_dict, sl_dict_t); + break; + + case SQ_CPX_TYPE_STRING: + case SQ_CPX_TYPE_UTF16_STRING: + query_data64 = sl_unpack_uint64(buf, offset, encoding); + qlen = (query_data64 & 0xffff) * 8; + used_in_last_block = query_data64 >> 32; + slen = qlen - 16 + used_in_last_block; + + if (cpx_query_type == SQ_CPX_TYPE_STRING) { + p = dalloc_strndup(query, buf + offset + 8, slen); + } else { + unicode_encoding = spotlight_get_utf16_string_encoding(buf, offset + 8, slen, encoding); + mark_exists = (unicode_encoding & SL_ENC_UTF_16); + if (unicode_encoding & SL_ENC_BIG_ENDIAN) + EC_FAIL_LOG("Unsupported big endian UTF16 string"); + slen -= mark_exists ? 2 : 0; + EC_NEG1( convert_string_allocate(CH_UCS2, + CH_UTF8, + buf + offset + (mark_exists ? 10 : 8), + slen, + &tmp) ); + p = dalloc_strndup(query, tmp, strlen(tmp)); + free(tmp); + } + + dalloc_add(query, p, char *); + roffset += qlen; + break; + + case SQ_CPX_TYPE_FILEMETA: + query_data64 = sl_unpack_uint64(buf, offset, encoding); + qlen = (query_data64 & 0xffff) * 8; + if (qlen <= 8) { + EC_FAIL_LOG("SQ_CPX_TYPE_FILEMETA: query_length <= 8: %d", qlen); + } else { + sl_fm = talloc_zero(query, sl_filemeta_t); + EC_NEG1_LOG( sl_unpack(sl_fm, buf + offset + 8) ); + dalloc_add(query, sl_fm, sl_filemeta_t); + } + roffset += qlen; + break; + + case SQ_CPX_TYPE_CNIDS: + query_data64 = sl_unpack_uint64(buf, offset, encoding); + qlen = (query_data64 & 0xffff) * 8; + EC_NEG1_LOG( sl_unpack_CNID(query, buf, offset + 8, qlen, encoding) ); + roffset += qlen; + break; + + default: + EC_FAIL; + } + +EC_CLEANUP: + if (ret != 0) + roffset = -1; + return roffset; +} + +static int sl_unpack_loop(DALLOC_CTX *query, + const char *buf, + int offset, + uint count, + const uint toc_offset, + const uint encoding) +{ + EC_INIT; + int i, toc_index, query_length; + uint subcount; + uint64_t query_data64, query_type; + uint cpx_query_type, cpx_query_count; + sl_nil_t nil; + sl_bool_t b; + + while (count > 0 && (offset < toc_offset)) { + query_data64 = sl_unpack_uint64(buf, offset, encoding); + query_length = (query_data64 & 0xffff) * 8; + query_type = (query_data64 & 0xffff0000) >> 16; + if (query_length == 0) + EC_FAIL; + + switch (query_type) { + case SQ_TYPE_COMPLEX: + toc_index = (query_data64 >> 32) - 1; + query_data64 = sl_unpack_uint64(buf, toc_offset + toc_index * 8, encoding); + cpx_query_type = (query_data64 & 0xffff0000) >> 16; + cpx_query_count = query_data64 >> 32; + + EC_NEG1_LOG( offset = sl_unpack_cpx(query, buf, offset + 8, cpx_query_type, cpx_query_count, toc_offset, encoding)); + count--; + break; + case SQ_TYPE_NULL: + subcount = query_data64 >> 32; + if (subcount > 64) + EC_FAIL; + nil = 0; + for (i = 0; i < subcount; i++) + dalloc_add_copy(query, &nil, sl_nil_t); + offset += query_length; + count -= subcount; + break; + case SQ_TYPE_BOOL: + b = query_data64 >> 32; + dalloc_add_copy(query, &b, sl_bool_t); + offset += query_length; + count--; + break; + case SQ_TYPE_INT64: + EC_NEG1_LOG( subcount = sl_unpack_ints(query, buf, offset, encoding) ); + offset += query_length; + count -= subcount; + break; + case SQ_TYPE_UUID: + EC_NEG1_LOG( subcount = sl_unpack_uuid(query, buf, offset, encoding) ); + offset += query_length; + count -= subcount; + break; + case SQ_TYPE_FLOAT: + EC_NEG1_LOG( subcount = sl_unpack_floats(query, buf, offset, encoding) ); + offset += query_length; + count -= subcount; + break; + case SQ_TYPE_DATE: + EC_NEG1_LOG( subcount = sl_unpack_date(query, buf, offset, encoding) ); + offset += query_length; + count -= subcount; + break; + default: + EC_FAIL; + } + } + +EC_CLEANUP: + if (ret != 0) { + offset = -1; + } + return offset; +} + +/************************************************************************************************** + * Global functions for packing und unpacking + **************************************************************************************************/ + +int sl_pack(DALLOC_CTX *query, char *buf) +{ + EC_INIT; + char toc_buf[MAX_SLQ_TOC]; + int toc_index = 0; + int len = 0; + + memcpy(buf, "432130dm", 8); + EC_NEG1_LOG( len = sl_pack_loop(query, buf + 16, 0, toc_buf + 8, &toc_index) ); + EC_ZERO( sivalc(buf, 8, MAX_SLQ_DAT, len / 8 + 1 + toc_index + 1) ); + EC_ZERO( sivalc(buf, 12, MAX_SLQ_DAT, len / 8 + 1) ); + + EC_ZERO( slvalc(toc_buf, 0, MAX_SLQ_TOC, sl_pack_tag(SQ_TYPE_TOC, toc_index + 1, 0)) ); + if ((16 + len + ((toc_index + 1 ) * 8)) >= MAX_SLQ_DAT) + EC_FAIL; + memcpy(buf + 16 + len, toc_buf, (toc_index + 1 ) * 8); + len += 16 + (toc_index + 1 ) * 8; + +EC_CLEANUP: + if (ret != 0) + len = -1; + return len; +} + +int sl_unpack(DALLOC_CTX *query, const char *buf) +{ + EC_INIT; + int encoding, toc_entries; + uint64_t toc_offset; + + if (strncmp(buf, "md031234", 8) == 0) + encoding = SL_ENC_BIG_ENDIAN; + else + encoding = SL_ENC_LITTLE_ENDIAN; + + buf += 8; + + toc_offset = ((sl_unpack_uint64(buf, 0, encoding) >> 32) - 1 ) * 8; + if (toc_offset < 0 || (toc_offset > 65000)) { + EC_FAIL; + } + + buf += 8; + + toc_entries = (int)(sl_unpack_uint64(buf, toc_offset, encoding) & 0xffff); + + EC_NEG1( sl_unpack_loop(query, buf, 0, 1, toc_offset + 8, encoding) ); + +EC_CLEANUP: + EC_EXIT; +} diff --git a/etc/afpd/status.c b/etc/afpd/status.c new file mode 100644 index 0000000..edf7446 --- /dev/null +++ b/etc/afpd/status.c @@ -0,0 +1,656 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#ifdef BSD4_4 +#include +#ifndef HAVE_GETHOSTID +#include +#endif /* HAVE_GETHOSTID */ +#endif /* BSD4_4 */ +#endif + +#include + +#ifdef HAVE_KERBEROS +#ifdef HAVE_KRB5_KRB5_H +#include +#else +#include +#endif /* HAVE_KRB5_KRB5_H */ +#endif /* HAVE_KERBEROS */ + +#include +#include +#include +#include + +#include "status.h" +#include "afp_config.h" +#include "icon.h" +#include "uam_auth.h" + +static size_t maxstatuslen = 0; + +static int uam_gss_enabled() +{ + /* XXX: must be a better way to find out if uam_gss is active */ + return auth_uamfind(UAM_SERVER_LOGIN_EXT, + "Client Krb v2", + sizeof("Client Krb v2")) != NULL; +} + +static void status_flags(char *data, + const int notif, + const int ipok, + const unsigned char passwdbits, + const int dirsrvcs, + int flags) +{ + uint16_t status; + + status = AFPSRVRINFO_COPY + | AFPSRVRINFO_SRVSIGNATURE + | AFPSRVRINFO_SRVMSGS + | AFPSRVRINFO_FASTBOZO + | AFPSRVRINFO_SRVUTF8 + | AFPSRVRINFO_EXTSLEEP; + + if (passwdbits & PASSWD_SET) /* some uams may not allow this. */ + status |= AFPSRVRINFO_PASSWD; + if (passwdbits & PASSWD_NOSAVE) + status |= AFPSRVRINFO_NOSAVEPASSWD; + if (ipok) /* only advertise tcp/ip if we have a valid address */ + status |= AFPSRVRINFO_TCPIP; + if (notif) /* Default is yes */ + status |= AFPSRVRINFO_SRVNOTIFY; + if (dirsrvcs) + status |= AFPSRVRINFO_SRVRDIR; + if (flags & OPTION_UUID) + status |= AFPSRVRINFO_UUID; + + status = htons(status); + memcpy(data + AFPSTATUS_FLAGOFF, &status, sizeof(status)); +} + +static int status_server(char *data, const char *server, const struct afp_options *options) +{ + char *start = data; + char *Obj; + char buf[32]; + uint16_t status; + size_t len; + + /* make room for all offsets before server name */ + data += AFPSTATUS_PRELEN; + + /* extract the obj part of the server */ + Obj = (char *) server; + if ((size_t)-1 == (len = convert_string( + options->unixcharset, options->maccharset, + Obj, -1, buf, sizeof(buf))) ) { + len = MIN(strlen(Obj), 31); + *data++ = len; + memcpy( data, Obj, len ); + LOG ( log_error, logtype_afpd, "Could not set servername, using fallback"); + } else { + *data++ = len; + memcpy( data, buf, len ); + } + if ((len + 1) & 1) /* pad server name and length byte to even boundary */ + len++; + data += len; + + /* make room for signature and net address offset. save location of + * signature offset. we're also making room for directory names offset + * and the utf-8 server name offset. + * + * NOTE: technically, we don't need to reserve space for the + * signature and net address offsets if they're not going to be + * used. as there are no offsets after them, it doesn't hurt to + * have them specified though. so, we just do that to simplify + * things. + * + * NOTE2: AFP3.1 Documentation states that the directory names offset + * is a required feature, even though it can be set to zero. + */ + len = data - start; + status = htons(len + AFPSTATUS_POSTLEN); + memcpy(start + AFPSTATUS_MACHOFF, &status, sizeof(status)); + return len; /* return the offset to beginning of signature offset */ +} + +static void status_machine(char *data) +{ + char *start = data; + uint16_t status; + int len; +#ifdef AFS + const char *machine = "afs"; +#else /* !AFS */ + const char *machine = "Netatalk%s"; +#endif /* AFS */ + char buf[AFPSTATUS_MACHLEN+1]; + + memcpy(&status, start + AFPSTATUS_MACHOFF, sizeof(status)); + data += ntohs( status ); + + if ((strlen(machine) + strlen(VERSION)) <= AFPSTATUS_MACHLEN) { + len = snprintf(buf, AFPSTATUS_MACHLEN + 1, machine, VERSION); + } else { + if (strlen(VERSION) > AFPSTATUS_MACHLEN) { + len = snprintf(buf, AFPSTATUS_MACHLEN + 1, VERSION); + } else { + (void)snprintf(buf, AFPSTATUS_MACHLEN + 1, machine, ""); + (void)snprintf(buf + AFPSTATUS_MACHLEN - strlen(VERSION), + strlen(VERSION) + 1, + VERSION); + len = AFPSTATUS_MACHLEN; + } + } + + *data++ = len; + memcpy( data, buf, len ); + data += len; + + status = htons(data - start); + memcpy(start + AFPSTATUS_VERSOFF, &status, sizeof(status)); +} + +/* server signature is a 16-byte quantity */ +static uint16_t status_signature(char *data, int *servoffset, + const struct afp_options *options) +{ + char *status; + uint16_t offset, sigoff; + + status = data; + + /* get server signature offset */ + memcpy(&offset, data + *servoffset, sizeof(offset)); + sigoff = offset = ntohs(offset); + + /* jump to server signature offset */ + data += offset; + + memset(data, 0, 16); + memcpy(data, options->signature, 16); + data += 16; + + /* calculate net address offset */ + *servoffset += sizeof(offset); + offset = htons(data - status); + memcpy(status + *servoffset, &offset, sizeof(offset)); + return sigoff; +} + +static size_t status_netaddress(char *data, int *servoffset, + const DSI *dsi, + const struct afp_options *options) +{ + char *begin; + uint16_t offset; + size_t addresses_len = 0; + + begin = data; + + /* get net address offset */ + memcpy(&offset, data + *servoffset, sizeof(offset)); + data += ntohs(offset); + + /* format: + Address count (byte) + len (byte = sizeof(length + address type + address) + address type (byte, ip address = 0x01, ip + port = 0x02, + ddp address = 0x03, fqdn = 0x04) + address (up to 254 bytes, ip = 4, ip + port = 6, ddp = 4) + */ + + /* number of addresses. this currently screws up if we have a dsi + connection, but we don't have the ip address. to get around this, + we turn off the status flag for tcp/ip. */ + *data++ = ((options->fqdn && dsi)? 1 : 0) + (dsi ? 1 : 0) + + (((options->flags & OPTION_ANNOUNCESSH) && options->fqdn && dsi)? 1 : 0); + + /* ip address */ + if (dsi) { + if (dsi->server.ss_family == AF_INET) { /* IPv4 */ + const struct sockaddr_in *inaddr = (struct sockaddr_in *)&dsi->server; + if (inaddr->sin_port == htons(DSI_AFPOVERTCP_PORT)) { + *data++ = 6; /* length */ + *data++ = 0x01; /* basic ip address */ + memcpy(data, &inaddr->sin_addr.s_addr, + sizeof(inaddr->sin_addr.s_addr)); + data += sizeof(inaddr->sin_addr.s_addr); + addresses_len += 7; + } else { + /* ip address + port */ + *data++ = 8; + *data++ = 0x02; /* ip address with port */ + memcpy(data, &inaddr->sin_addr.s_addr, + sizeof(inaddr->sin_addr.s_addr)); + data += sizeof(inaddr->sin_addr.s_addr); + memcpy(data, &inaddr->sin_port, sizeof(inaddr->sin_port)); + data += sizeof(inaddr->sin_port); + addresses_len += 9; + } + } else { /* IPv6 */ + const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&dsi->server; + if (sa6->sin6_port == htons(DSI_AFPOVERTCP_PORT)) { + *data++ = 18; /* length */ + *data++ = 6; /* type */ + memcpy(data, &sa6->sin6_addr.s6_addr, sizeof(sa6->sin6_addr.s6_addr)); + data += sizeof(sa6->sin6_addr.s6_addr); + addresses_len += 19; + } else { + /* ip address + port */ + *data++ = 20; /* length */ + *data++ = 7; /* type*/ + memcpy(data, &sa6->sin6_addr.s6_addr, sizeof(sa6->sin6_addr.s6_addr)); + data += sizeof(sa6->sin6_addr.s6_addr); + memcpy(data, &sa6->sin6_port, sizeof(sa6->sin6_port)); + data += sizeof(sa6->sin6_port); + addresses_len += 21; + } + + } + } + + /* handle DNS names */ + if (options->fqdn && dsi) { + size_t len = strlen(options->fqdn); + if ( len + 2 + addresses_len < maxstatuslen - offset) { + *data++ = len +2; + *data++ = 0x04; + memcpy(data, options->fqdn, len); + data += len; + addresses_len += len+2; + } + + /* Annouce support for SSH tunneled AFP session, + * this feature is available since 10.3.2. + * According to the specs (AFP 3.1 p.225) this should + * be an IP+Port style value, but it only works with + * a FQDN. OSX Server uses FQDN as well. + */ + if ( len + 2 + addresses_len < maxstatuslen - offset) { + if (options->flags & OPTION_ANNOUNCESSH) { + *data++ = len +2; + *data++ = 0x05; + memcpy(data, options->fqdn, len); + data += len; + } + } + } + + /* calculate/store Directory Services Names offset */ + offset = htons(data - begin); + *servoffset += sizeof(offset); + memcpy(begin + *servoffset, &offset, sizeof(offset)); + + /* return length of buffer */ + return (data - begin); +} + + +/** + * DirectoryNamesCount offset: uint16_t + * ... + * DirectoryNamesCount: uint8_t + * DirectoryNames: list of UTF-8 Pascal strings (uint8_t + char[1,255]) + */ +static size_t status_directorynames(char *data, + int *diroffset, + const DSI *dsi _U_, + const struct afp_options *options) +{ + char *begin = data; + uint16_t offset; + + memcpy(&offset, begin + *diroffset, sizeof(offset)); + offset = ntohs(offset); + data += offset; + + if (!uam_gss_enabled() || !options->k5principal) { + *data = 0; + data++; + } else { + memcpy(data, options->k5principal, options->k5principal_buflen); + data += options->k5principal_buflen; + } + + /* Calculate and store offset for UTF8ServerName */ + *diroffset += sizeof(uint16_t); + offset = htons(data - begin); + memcpy(begin + *diroffset, &offset, sizeof(uint16_t)); + + /* return length of buffer */ + return (data - begin); +} + +static size_t status_utf8servername(char *data, int *nameoffset, + const DSI *dsi _U_, + const struct afp_options *options) +{ + uint16_t namelen; + size_t len; + char *begin = data; + uint16_t offset; + + memcpy(&offset, data + *nameoffset, sizeof(offset)); + offset = ntohs(offset); + data += offset; + + LOG(log_info, logtype_afpd, "servername: %s", options->hostname); + + if ((len = convert_string(options->unixcharset, + CH_UTF8_MAC, + options->hostname, + -1, + data + sizeof(namelen), + maxstatuslen-offset)) == (size_t)-1) { + LOG(log_error, logtype_afpd, "Could not set utf8 servername"); + + /* set offset to 0 */ + memset(begin + *nameoffset, 0, sizeof(offset)); + data = begin + offset; + } else { + namelen = htons(len); + memcpy( data, &namelen, sizeof(namelen)); + data += sizeof(namelen); + data += len; + offset = htons(offset); + memcpy(begin + *nameoffset, &offset, sizeof(uint16_t)); + } + + /* return length of buffer */ + return (data - begin); + +} + +/* returns actual offset to signature */ +static void status_icon(char *data, const unsigned char *icondata, + const int iconlen, const int sigoffset) +{ + char *start = data; + char *sigdata = data + sigoffset; + uint16_t ret, status; + + memcpy(&status, start + AFPSTATUS_ICONOFF, sizeof(status)); + if ( icondata == NULL ) { + ret = status; + memset(start + AFPSTATUS_ICONOFF, 0, sizeof(status)); + } else { + data += ntohs( status ); + memcpy( data, icondata, iconlen); + data += iconlen; + ret = htons(data - start); + } + + /* put in signature offset */ + if (sigoffset) + memcpy(sigdata, &ret, sizeof(ret)); +} + +/* --------------------- + */ +void status_init(AFPObj *obj, DSI *dsi) +{ + char *status = dsi->status; + size_t statuslen; + int c, sigoff, ipok = 0; + const struct afp_options *options = &obj->options; + + maxstatuslen = sizeof(dsi->status); + + if (dsi->server.ss_family == AF_INET) { /* IPv4 */ + const struct sockaddr_in *sa4 = (struct sockaddr_in *)&dsi->server; + ipok = sa4->sin_addr.s_addr ? 1 : 0; + } else { /* IPv6 */ + const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&dsi->server; + for (int i=0; i<16; i++) { + if (sa6->sin6_addr.s6_addr[i]) { + ipok = 1; + break; + } + } + } + + /* + * These routines must be called in order -- earlier calls + * set the offsets for later calls. + * + * using structs is a bad idea, but that's what the original code + * does. solaris, in fact, will segfault with them. so, now + * we just use the powers of #defines and memcpy. + * + * reply block layout (offsets are 16-bit quantities): + * machine type offset -> AFP version count offset -> + * UAM count offset -> vol icon/mask offset -> flags -> + * + * server name [padded to even boundary] -> signature offset -> + * network address offset -> + * + * at the appropriate offsets: + * machine type, afp versions, uams, server signature + * (16-bytes), network addresses, volume icon/mask + */ + + status_flags(status, + options->flags & OPTION_SERVERNOTIF, + (options->fqdn || ipok), + options->passwdbits, + 1, + options->flags); + /* returns offset to signature offset */ + c = status_server(status, options->hostname, options); + status_machine(status); + status_versions(status, dsi); + status_uams(status, options->uamlist); + status_icon(status, icon, sizeof(icon), c); + + sigoff = status_signature(status, &c, options); + /* c now contains the offset where the netaddress offset lives */ + + status_netaddress(status, &c, dsi, options); + /* c now contains the offset where the Directory Names Count offset lives */ + + statuslen = status_directorynames(status, &c, dsi, options); + /* c now contains the offset where the UTF-8 ServerName offset lives */ + + if ( statuslen < maxstatuslen) + statuslen = status_utf8servername(status, &c, dsi, options); + + dsi->signature = status + sigoff; + dsi->statuslen = statuslen; +} + +/* set_signature() */ +/* */ +/* If found in conf file, use it. */ +/* If not found in conf file, genarate and append in conf file. */ +/* If conf file don't exist, create and genarate. */ +/* If cannot open conf file, use one-time signature. */ +/* If signature = xxxxx, use it. */ + +void set_signature(struct afp_options *options) { + int fd, i; + struct stat tmpstat; + char *servername_conf; + int header = 0; + char buf[1024], *p; + FILE *fp = NULL; + size_t len; + char *server_tmp; + + server_tmp = options->hostname; + len = strlen(options->signatureopt); + if (len == 0) { + goto server_signature_auto; /* default */ + } else if (len < 3) { + LOG(log_warning, logtype_afpd, "WARNING: signature string %s is very short !", options->signatureopt); + goto server_signature_user; + } else if (len > 16) { + LOG(log_warning, logtype_afpd, "WARNING: signature string %s is very long !", options->signatureopt); + len = 16; + goto server_signature_user; + } else { + LOG(log_info, logtype_afpd, "signature string is %s.", options->signatureopt); + goto server_signature_user; + } + +server_signature_user: + + /* Signature is defined in afp.conf */ + memset(options->signature, 0, 16); + memcpy(options->signature, options->signatureopt, len); + goto server_signature_done; + +server_signature_auto: + + /* Signature type is auto, using afp_signature.conf */ + if (!stat(options->sigconffile, &tmpstat)) { /* conf file exists? */ + if ((fp = fopen(options->sigconffile, "r")) != NULL) { /* read open? */ + /* scan in the conf file */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + p = buf; + while (p && isblank(*p)) + p++; + if (!p || (*p == '#') || (*p == '\n')) + continue; /* invalid line */ + if (*p == '"') { + p++; + if ((servername_conf = strtok( p, "\"" )) == NULL) + continue; /* syntax error: invalid quoted servername */ + } else { + if ((servername_conf = strtok( p, " \t" )) == NULL) + continue; /* syntax error: invalid servername */ + } + p = strchr(p, '\0'); + p++; + if (*p == '\0') + continue; /* syntax error: missing signature */ + + if (strcmp(server_tmp, servername_conf)) + continue; /* another servername */ + + while (p && isblank(*p)) + p++; + if ( 16 == sscanf(p, "%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX", + &options->signature[ 0], &options->signature[ 1], + &options->signature[ 2], &options->signature[ 3], + &options->signature[ 4], &options->signature[ 5], + &options->signature[ 6], &options->signature[ 7], + &options->signature[ 8], &options->signature[ 9], + &options->signature[10], &options->signature[11], + &options->signature[12], &options->signature[13], + &options->signature[14], &options->signature[15] + )) { + fclose(fp); + goto server_signature_done; /* found in conf file */ + } + } + if ((fp = freopen(options->sigconffile, "a+", fp)) != NULL) { /* append because not found */ + fseek(fp, 0L, SEEK_END); + if(ftell(fp) == 0) { /* size = 0 */ + header = 1; + goto server_signature_random; + } else { + fseek(fp, -1L, SEEK_END); + if(fgetc(fp) != '\n') fputc('\n', fp); /* last char is \n? */ + goto server_signature_random; + } + } else { + LOG(log_error, logtype_afpd, "ERROR: Cannot write in %s (%s). Using one-time signature.", + options->sigconffile, strerror(errno)); + goto server_signature_random; + } + } else { + LOG(log_error, logtype_afpd, "ERROR: Cannot read %s (%s). Using one-time signature.", + options->sigconffile, strerror(errno)); + goto server_signature_random; + } + } else { /* conf file don't exist */ + if (( fd = creat(options->sigconffile, 0644 )) < 0 ) { + LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s). Using one-time signature.", + options->sigconffile, strerror(errno)); + goto server_signature_random; + } + if (( fp = fdopen( fd, "w" )) == NULL ) { + LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s). Using one-time signature.", + options->sigconffile, strerror(errno)); + close(fd); + goto server_signature_random; + } + header = 1; + goto server_signature_random; + } + +server_signature_random: + + /* generate signature from random number */ + randombytes(options->signature, 16); + + if (fp && header) { /* conf file is created or size=0 */ + fprintf(fp, "# DON'T TOUCH NOR COPY THOUGHTLESSLY!\n"); + fprintf(fp, "# This file is auto-generated by afpd.\n"); + fprintf(fp, "# \n"); + fprintf(fp, "# ServerSignature is unique identifier used to prevent logging on to\n"); + fprintf(fp, "# the same server twice.\n"); + fprintf(fp, "# \n"); + fprintf(fp, "# If setting \"signature = xxxxx\" in afp.conf, this file is not used.\n\n"); + } + + if (fp) { + fprintf(fp, "\"%s\"\t", server_tmp); + for (i=0 ; i<16 ; i++) { + fprintf(fp, "%02X", (options->signature)[i]); + } + fprintf(fp, "%s", "\n"); + fclose(fp); + } + +server_signature_done: + + /* retrun */ + LOG(log_info, logtype_afpd, + "signature is %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + (options->signature)[ 0], (options->signature)[ 1], + (options->signature)[ 2], (options->signature)[ 3], + (options->signature)[ 4], (options->signature)[ 5], + (options->signature)[ 6], (options->signature)[ 7], + (options->signature)[ 8], (options->signature)[ 9], + (options->signature)[10], (options->signature)[11], + (options->signature)[12], (options->signature)[13], + (options->signature)[14], (options->signature)[15]); + + return; +} + +/* this is the same as asp/dsi_getstatus */ +int afp_getsrvrinfo(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + memcpy(rbuf, obj->dsi->status, obj->dsi->statuslen); + *rbuflen = obj->dsi->statuslen; + + return AFP_OK; +} diff --git a/etc/afpd/status.h b/etc/afpd/status.h new file mode 100644 index 0000000..343774a --- /dev/null +++ b/etc/afpd/status.h @@ -0,0 +1,44 @@ +#ifndef AFPD_STATUS_H +#define AFPD_STATUS_H 1 + +#include +#include + +#include "afp_config.h" + +/* we use these to prevent whacky alignment problems */ +#define AFPSTATUS_MACHOFF 0 +#define AFPSTATUS_VERSOFF 2 +#define AFPSTATUS_UAMSOFF 4 +#define AFPSTATUS_ICONOFF 6 +#define AFPSTATUS_FLAGOFF 8 + +/* AFPSTATUS_PRELEN is the number of bytes for status data prior to + * the ServerName field. + * + * This is two bytes of offset space for the MachineType, AFPVersionCount, + * UAMCount, VolumeIconAndMask, and the 16-bit "Fixed" status flags. + */ +#define AFPSTATUS_PRELEN 10 + +/* AFPSTATUS_POSTLEN is the number of bytes for offset records + * after the ServerName field. + * + * Right now, this is 2 bytes each for ServerSignature, networkAddressCount, + * DirectoryNameCount, and UTF-8 ServerName + */ +#define AFPSTATUS_POSTLEN 8 +#define AFPSTATUS_LEN (AFPSTATUS_PRELEN + AFPSTATUS_POSTLEN) + +/* AFPSTATUS_MACHLEN is the number of characters for the MachineType. */ +#define AFPSTATUS_MACHLEN 16 + +extern void status_versions (char * /*status*/, const DSI *); +extern void status_uams (char * /*status*/, const char * /*authlist*/); +extern void status_init (AFPObj *, DSI *dsi); +extern void set_signature(struct afp_options *); + +/* FP functions */ +int afp_getsrvrinfo (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +#endif diff --git a/etc/afpd/switch.c b/etc/afpd/switch.c new file mode 100644 index 0000000..5c98e8d --- /dev/null +++ b/etc/afpd/switch.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include /* to pick up NULL */ +#include /* works around a bug */ +#include + +#include +#include +#include + +/* grab the FP functions */ +#include "auth.h" +#include "desktop.h" +#include "switch.h" +#include "fork.h" +#include "file.h" +#include "directory.h" +#include "filedir.h" +#include "status.h" +#include "misc.h" +#ifdef HAVE_ACLS +#include "acls.h" +#endif + +static int afp_null(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + LOG(log_info, logtype_afpd, "afp_null handle %d", *ibuf ); + *rbuflen = 0; + return( AFPERR_NOOP ); +} + +/* + * Routines marked "NULL" are not AFP functions. + * Routines marked "afp_null" are AFP functions + * which are not yet implemented. A fine line... + */ +static AFPCmd preauth_switch[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 0 - 7 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 8 - 15 */ + NULL, NULL, afp_login, afp_logincont, + afp_logout, NULL, NULL, NULL, /* 16 - 23 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 24 - 31 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 32 - 39 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 40 - 47 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 48 - 55 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, afp_login_ext, /* 56 - 63 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 64 - 71 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 72 - 79 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 80 - 87 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 88 - 95 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 96 - 103 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 104 - 111 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 112 - 119 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 120 - 127 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 128 - 135 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 136 - 143 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 144 - 151 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 152 - 159 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 160 - 167 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 168 - 175 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 176 - 183 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 184 - 191 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 192 - 199 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 200 - 207 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 208 - 215 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 216 - 223 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 224 - 231 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 232 - 239 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 240 - 247 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 248 - 255 */ +}; + +AFPCmd *afp_switch = preauth_switch; + +AFPCmd postauth_switch[] = { + NULL, afp_bytelock, afp_closevol, afp_closedir, + afp_closefork, afp_copyfile, afp_createdir, afp_createfile, /* 0 - 7 */ + afp_delete, afp_enumerate, afp_flush, afp_flushfork, + afp_null, afp_null, afp_getforkparams, afp_getsrvrinfo, /* 8 - 15 */ + afp_getsrvrparms, afp_getvolparams, afp_login, afp_logincont, + afp_logout, afp_mapid, afp_mapname, afp_moveandrename, /* 16 - 23 */ + afp_openvol, afp_opendir, afp_openfork, afp_read, + afp_rename, afp_setdirparams, afp_setfilparams, afp_setforkparams, + /* 24 - 31 */ + afp_setvolparams, afp_write, afp_getfildirparams, afp_setfildirparams, + afp_changepw, afp_getuserinfo, afp_getsrvrmesg, afp_createid, /* 32 - 39 */ + afp_deleteid, afp_resolveid, afp_exchangefiles, afp_catsearch, + afp_null, afp_null, afp_null, afp_null, /* 40 - 47 */ + afp_opendt, afp_closedt, afp_null, afp_geticon, + afp_geticoninfo, afp_addappl, afp_rmvappl, afp_getappl, /* 48 - 55 */ + afp_addcomment, afp_rmvcomment, afp_getcomment, NULL, + NULL, NULL, NULL, NULL, /* 56 - 63 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 64 - 71 */ + NULL, NULL, NULL, NULL, + NULL, NULL, afp_syncdir, afp_syncfork, /* 72 - 79 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 80 - 87 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 88 - 95 */ + NULL, NULL, NULL, NULL, + afp_getdiracl, afp_setdiracl, afp_afschangepw, NULL, /* 96 - 103 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 104 - 111 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 112 - 119 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 120 - 127 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 128 - 135 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 136 - 143 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 144 - 151 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 152 - 159 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 160 - 167 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 168 - 175 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 176 - 183 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 184 - 191 */ + afp_addicon, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 192 - 199 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 200 - 207 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 208 - 215 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 216 - 223 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 224 - 231 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 232 - 239 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 240 - 247 */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, /* 248 - 255 */ +}; + + +/* add a new function if it's specified. return the old function in + * "old" if there's a pointer there. */ +int uam_afpserver_action(const int id, const int which, + AFPCmd new_table, AFPCmd *old) +{ + switch (which) { + case UAM_AFPSERVER_PREAUTH: + if (old) + *old = preauth_switch[id]; + if (new_table) + preauth_switch[id] = new_table; + break; + case UAM_AFPSERVER_POSTAUTH: + if (old) + *old = postauth_switch[id]; + if (new_table) + postauth_switch[id] = new_table; + break; + default: + LOG(log_debug, logtype_afpd, "uam_afpserver_action: unknown switch %d[%d]", + which, id); + return -1; + } + + return 0; +} diff --git a/etc/afpd/switch.h b/etc/afpd/switch.h new file mode 100644 index 0000000..1cc50d0 --- /dev/null +++ b/etc/afpd/switch.h @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifndef AFPD_SWITCH_H +#define AFPD_SWITCH_H 1 + +extern AFPCmd *afp_switch; +extern AFPCmd postauth_switch[]; + +/* switch.c */ +#define UAM_AFPSERVER_PREAUTH (0) +#define UAM_AFPSERVER_POSTAUTH (1 << 0) + +extern int uam_afpserver_action (const int /*id*/, const int /*switch*/, + AFPCmd new_table, AFPCmd *old); + + +#endif diff --git a/etc/afpd/uam.c b/etc/afpd/uam.c new file mode 100644 index 0000000..04e54cb --- /dev/null +++ b/etc/afpd/uam.c @@ -0,0 +1,534 @@ +/* + * + * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_DLFCN_H +#include +#endif /* HAVE_DLFCN_H */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "afp_config.h" +#include "auth.h" +#include "uam_auth.h" + +#ifdef TRU64 +#include +#include +#include +#include +#endif /* TRU64 */ + +/* --- server uam functions -- */ + +/* uam_load. uams must have a uam_setup function. */ +struct uam_mod *uam_load(AFPObj *obj, const char *path, const char *name) +{ + char buf[MAXPATHLEN + 1], *p; + struct uam_mod *mod; + void *module; + + if ((module = mod_open(path)) == NULL) { + LOG(log_error, logtype_afpd, "uam_load(%s): failed to load: %s", name, mod_error()); + return NULL; + } + + if ((mod = (struct uam_mod *) malloc(sizeof(struct uam_mod))) == NULL) { + LOG(log_error, logtype_afpd, "uam_load(%s): malloc failed", name); + goto uam_load_fail; + } + + strlcpy(buf, name, sizeof(buf)); + if ((p = strchr(buf, '.'))) + *p = '\0'; + + if ((mod->uam_fcn = mod_symbol(module, buf)) == NULL) { + LOG(log_error, logtype_afpd, "uam_load(%s): mod_symbol error for symbol %s", + name, + buf); + goto uam_load_err; + } + + if (mod->uam_fcn->uam_type != UAM_MODULE_SERVER) { + LOG(log_error, logtype_afpd, "uam_load(%s): attempted to load a non-server module", + name); + goto uam_load_err; + } + + /* version check would go here */ + + if (!mod->uam_fcn->uam_setup || + ((*mod->uam_fcn->uam_setup)(obj, name) < 0)) { + LOG(log_error, logtype_afpd, "uam_load(%s): uam_setup failed", name); + goto uam_load_err; + } + + mod->uam_module = module; + return mod; + +uam_load_err: + free(mod); +uam_load_fail: + mod_close(module); + return NULL; +} + +/* unload the module. we check for a cleanup function, but we don't + * die if one doesn't exist. however, things are likely to leak without one. + */ +void uam_unload(struct uam_mod *mod) +{ + if (mod->uam_fcn->uam_cleanup) + (*mod->uam_fcn->uam_cleanup)(); + + mod_close(mod->uam_module); + free(mod); +} + +/* -- client-side uam functions -- */ +/* set up stuff for this uam. */ +int uam_register(const int type, const char *path, const char *name, ...) +{ + va_list ap; + struct uam_obj *uam; + int ret; + + if (!name) + return -1; + + /* see if it already exists. */ + if ((uam = auth_uamfind(type, name, strlen(name)))) { + if (strcmp(uam->uam_path, path)) { + /* it exists, but it's not the same module. */ + LOG(log_error, logtype_afpd, "uam_register: \"%s\" already loaded by %s", + name, path); + return -1; + } + uam->uam_count++; + return 0; + } + + /* allocate space for uam */ + if ((uam = calloc(1, sizeof(struct uam_obj))) == NULL) + return -1; + + uam->uam_name = name; + uam->uam_path = strdup(path); + uam->uam_count++; + + va_start(ap, name); + switch (type) { + case UAM_SERVER_LOGIN_EXT: /* expect four arguments */ + uam->u.uam_login.login = va_arg(ap, void *); + uam->u.uam_login.logincont = va_arg(ap, void *); + uam->u.uam_login.logout = va_arg(ap, void *); + uam->u.uam_login.login_ext = va_arg(ap, void *); + break; + + case UAM_SERVER_LOGIN: /* expect three arguments */ + uam->u.uam_login.login_ext = NULL; + uam->u.uam_login.login = va_arg(ap, void *); + uam->u.uam_login.logincont = va_arg(ap, void *); + uam->u.uam_login.logout = va_arg(ap, void *); + break; + case UAM_SERVER_CHANGEPW: /* one argument */ + uam->u.uam_changepw = va_arg(ap, void *); + break; + case UAM_SERVER_PRINTAUTH: /* x arguments */ + default: + break; + } + va_end(ap); + + /* attach to other uams */ + ret = auth_register(type, uam); + if ( ret) { + free(uam->uam_path); + free(uam); + } + + return ret; +} + +void uam_unregister(const int type, const char *name) +{ + struct uam_obj *uam; + + if (!name) + return; + + uam = auth_uamfind(type, name, strlen(name)); + if (!uam || --uam->uam_count > 0) + return; + + auth_unregister(uam); + free(uam->uam_path); + free(uam); +} + +/* --- helper functions for plugin uams --- + * name: user name + * len: size of name buffer. +*/ + +struct passwd *uam_getname(void *private, char *name, const int len) +{ + AFPObj *obj = private; + struct passwd *pwent; + static char username[256]; + static char user[256]; + static char pwname[256]; + char *p; + size_t namelen, gecoslen = 0, pwnamelen = 0; + + if ((pwent = getpwnam(name))) + return pwent; + + /* if we have a NT domain name try with it */ + if (obj->options.addomain || (obj->options.ntdomain && obj->options.ntseparator)) { + /* FIXME What about charset ? */ + bstring princ; + if (obj->options.addomain) + princ = bformat("%s@%s", name, obj->options.addomain); + else + princ = bformat("%s%s%s", obj->options.ntdomain, obj->options.ntseparator, name); + pwent = getpwnam(bdata(princ)); + bdestroy(princ); + + if (pwent) { + int len = strlen(pwent->pw_name); + if (len < MAXUSERLEN) { + strncpy(name,pwent->pw_name, MAXUSERLEN); + } else { + LOG(log_error, logtype_uams, "The name '%s' is longer than %d", pwent->pw_name, MAXUSERLEN); + } + return pwent; + } + } +#ifndef NO_REAL_USER_NAME + + if ( (size_t) -1 == (namelen = convert_string((utf8_encoding(obj))?CH_UTF8_MAC:obj->options.maccharset, + CH_UCS2, name, -1, username, sizeof(username)))) + return NULL; + + setpwent(); + while ((pwent = getpwent())) { + if ((p = strchr(pwent->pw_gecos, ','))) + *p = '\0'; + + gecoslen = convert_string(obj->options.unixcharset, CH_UCS2, + pwent->pw_gecos, -1, user, sizeof(username)); + pwnamelen = convert_string(obj->options.unixcharset, CH_UCS2, + pwent->pw_name, -1, pwname, sizeof(username)); + if ((size_t)-1 == gecoslen && (size_t)-1 == pwnamelen) + continue; + + + /* check against both the gecos and the name fields. the user + * might have just used a different capitalization. */ + + if ( (namelen == gecoslen && strncasecmp_w((ucs2_t*)user, (ucs2_t*)username, len) == 0) || + ( namelen == pwnamelen && strncasecmp_w ( (ucs2_t*) pwname, (ucs2_t*) username, len) == 0)) { + strlcpy(name, pwent->pw_name, len); + break; + } + } + endpwent(); +#endif /* ! NO_REAL_USER_NAME */ + + /* os x server doesn't keep anything useful if we do getpwent */ + return pwent ? getpwnam(name) : NULL; +} + +int uam_checkuser(const struct passwd *pwd) +{ + const char *p; + + if (!pwd) + return -1; + +#ifndef DISABLE_SHELLCHECK + if (!pwd->pw_shell || (*pwd->pw_shell == '\0')) { + LOG(log_info, logtype_afpd, "uam_checkuser: User %s does not have a shell", pwd->pw_name); + return -1; + } + + while ((p = getusershell())) { + if ( strcmp( p, pwd->pw_shell ) == 0 ) + break; + } + endusershell(); + + if (!p) { + LOG(log_info, logtype_afpd, "illegal shell %s for %s", pwd->pw_shell, pwd->pw_name); + return -1; + } +#endif /* DISABLE_SHELLCHECK */ + + return 0; +} + +int uam_random_string (AFPObj *obj, char *buf, int len) +{ + uint32_t result; + int ret; + int fd; + + if ( (len <= 0) || (len % sizeof(result))) + return -1; + + /* construct a random number */ + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { + struct timeval tv; + struct timezone tz; + int i; + + if (gettimeofday(&tv, &tz) < 0) + return -1; + srandom(tv.tv_sec + (unsigned long) obj + (unsigned long) obj->dsi); + for (i = 0; i < len; i += sizeof(result)) { + result = random(); + memcpy(buf + i, &result, sizeof(result)); + } + } else { + ret = read(fd, buf, len); + close(fd); + if (ret <= 0) + return -1; + } + return 0; +} + +/* afp-specific functions */ +int uam_afpserver_option(void *private, const int what, void *option, + size_t *len) +{ + AFPObj *obj = private; + const char **buf = (const char **) option; /* most of the options are this */ + struct session_info **sinfo = (struct session_info **) option; + + if (!obj || !option) + return -1; + + switch (what) { + case UAM_OPTION_USERNAME: + *buf = &(obj->username[0]); + if (len) + *len = sizeof(obj->username) - 1; + break; + + case UAM_OPTION_GUEST: + *buf = obj->options.guest; + if (len) + *len = strlen(obj->options.guest); + break; + + case UAM_OPTION_PASSWDOPT: + if (!len) + return -1; + + switch (*len) { + case UAM_PASSWD_FILENAME: + *buf = obj->options.passwdfile; + *len = strlen(obj->options.passwdfile); + break; + + case UAM_PASSWD_MINLENGTH: + *((int *) option) = obj->options.passwdminlen; + *len = sizeof(obj->options.passwdminlen); + break; + + case UAM_PASSWD_EXPIRETIME: /* not implemented */ + default: + return -1; + break; + } + break; + + case UAM_OPTION_SIGNATURE: + *buf = (void *)obj->dsi->signature; + if (len) + *len = 16; + break; + + case UAM_OPTION_RANDNUM: /* returns a random number in 4-byte units. */ + if (!len) + return -1; + + return uam_random_string(obj, option, *len); + break; + + case UAM_OPTION_HOSTNAME: + *buf = obj->options.hostname; + if (len) + *len = strlen(obj->options.hostname); + break; + + case UAM_OPTION_CLIENTNAME: + { + struct DSI *dsi = obj->dsi; + const struct sockaddr *sa; + static char hbuf[NI_MAXHOST]; + + sa = (struct sockaddr *)&dsi->client; + if (getnameinfo(sa, sizeof(dsi->client), hbuf, sizeof(hbuf), NULL, 0, 0) == 0) + *buf = hbuf; + else + *buf = getip_string((struct sockaddr *)&dsi->client); + + break; + } + case UAM_OPTION_COOKIE: + /* it's up to the uam to actually store something useful here. + * this just passes back a handle to the cookie. the uam side + * needs to do something like **buf = (void *) cookie to store + * the cookie. */ + *buf = (void *) &obj->uam_cookie; + break; + case UAM_OPTION_KRB5SERVICE: + *buf = obj->options.k5service; + if (len) + *len = (*buf)?strlen(*buf):0; + break; + case UAM_OPTION_KRB5REALM: + *buf = obj->options.k5realm; + if (len) + *len = (*buf)?strlen(*buf):0; + break; + case UAM_OPTION_FQDN: + *buf = obj->options.fqdn; + if (len) + *len = (*buf)?strlen(*buf):0; + break; + case UAM_OPTION_MACCHARSET: + *((int *) option) = obj->options.maccharset; + *len = sizeof(obj->options.maccharset); + break; + case UAM_OPTION_UNIXCHARSET: + *((int *) option) = obj->options.unixcharset; + *len = sizeof(obj->options.unixcharset); + break; + case UAM_OPTION_SESSIONINFO: + *sinfo = &(obj->sinfo); + break; + default: + return -1; + break; + } + + return 0; +} + +/* if we need to maintain a connection, this is how we do it. + * because an action pointer gets passed in, we can stream + * DSI connections */ +int uam_afp_read(void *handle, char *buf, size_t *buflen, + int (*action)(void *, void *, const int)) +{ + AFPObj *obj = handle; + int len; + + if (!obj) + return AFPERR_PARAM; + + len = dsi_writeinit(obj->dsi, buf, *buflen); + if (!len || ((len = action(handle, buf, len)) < 0)) { + dsi_writeflush(obj->dsi); + goto uam_afp_read_err; + } + + while ((len = (dsi_write(obj->dsi, buf, *buflen)))) { + if ((len = action(handle, buf, len)) < 0) { + dsi_writeflush(obj->dsi); + goto uam_afp_read_err; + } + } + return 0; + +uam_afp_read_err: + *buflen = 0; + return len; +} + +#ifdef TRU64 +void uam_afp_getcmdline( int *ac, char ***av ) +{ + afp_get_cmdline( ac, av ); +} + +int uam_sia_validate_user(sia_collect_func_t * collect, int argc, char **argv, + char *hostname, char *username, char *tty, + int colinput, char *gssapi, char *passphrase) +/* A clone of the Tru64 system function sia_validate_user() that calls + * sia_ses_authent() rather than sia_ses_reauthent() + * Added extra code to take into account suspected SIA bug whereby it clobbers + * the signal handler on SIGALRM (tickle) installed by Netatalk/afpd + */ +{ + SIAENTITY *entity = NULL; + struct sigaction act; + int rc; + + if ((rc=sia_ses_init(&entity, argc, argv, hostname, username, tty, + colinput, gssapi)) != SIASUCCESS) { + LOG(log_error, logtype_afpd, "cannot initialise SIA"); + return SIAFAIL; + } + + /* save old action for restoration later */ + if (sigaction(SIGALRM, NULL, &act)) + LOG(log_error, logtype_afpd, "cannot save SIGALRM handler"); + + if ((rc=sia_ses_authent(collect, passphrase, entity)) != SIASUCCESS) { + /* restore old action after clobbering by sia_ses_authent() */ + if (sigaction(SIGALRM, &act, NULL)) + LOG(log_error, logtype_afpd, "cannot restore SIGALRM handler"); + + LOG(log_info, logtype_afpd, "unsuccessful login for %s", +(hostname?hostname:"(null)")); + return SIAFAIL; + } + LOG(log_info, logtype_afpd, "successful login for %s", +(hostname?hostname:"(null)")); + + /* restore old action after clobbering by sia_ses_authent() */ + if (sigaction(SIGALRM, &act, NULL)) + LOG(log_error, logtype_afpd, "cannot restore SIGALRM handler"); + + sia_ses_release(&entity); + + return SIASUCCESS; +} +#endif /* TRU64 */ + +/* --- papd-specific functions (just placeholders) --- */ +struct papfile; + +UAM_MODULE_EXPORT void append(struct papfile *pf _U_, const char *data _U_, int len _U_) +{ + return; +} diff --git a/etc/afpd/uam_auth.h b/etc/afpd/uam_auth.h new file mode 100644 index 0000000..4eb3bf0 --- /dev/null +++ b/etc/afpd/uam_auth.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + * interface between uam.c and auth.c + */ + +#ifndef AFPD_UAM_AUTH_H +#define AFPD_UAM_AUTH_H 1 + +#include + +#include +#include + +struct uam_mod { + void *uam_module; + struct uam_export *uam_fcn; + struct uam_mod *uam_prev, *uam_next; +}; + +struct uam_obj { + const char *uam_name; /* authentication method */ + char *uam_path; /* where it's located */ + int uam_count; + union { + struct { + int (*login) (void *, struct passwd **, + char *, int, char *, size_t *); + int (*logincont) (void *, struct passwd **, char *, + int, char *, size_t *); + void (*logout) (void); + int (*login_ext) (void *, char *, struct passwd **, + char *, int, char *, size_t *); + } uam_login; + int (*uam_changepw) (void *, char *, struct passwd *, char *, + int, char *, size_t *); + } u; + struct uam_obj *uam_prev, *uam_next; +}; + +#define uam_attach(a, b) do { \ + (a)->uam_prev->uam_next = (b); \ + (b)->uam_prev = (a)->uam_prev; \ + (b)->uam_next = (a); \ + (a)->uam_prev = (b); \ +} while (0) + +#define uam_detach(a) do { \ + (a)->uam_prev->uam_next = (a)->uam_next; \ + (a)->uam_next->uam_prev = (a)->uam_prev; \ +} while (0) + +extern struct uam_mod *uam_load (AFPObj *, const char *, const char *); +extern void uam_unload (struct uam_mod *); + +/* auth.c */ +int auth_load (AFPObj *, const char *, const char *); +int auth_register (const int, struct uam_obj *); +#define auth_unregister(a) uam_detach(a) +struct uam_obj *auth_uamfind (const int, const char *, const int); +void auth_unload (void); + +/* uam.c */ +int uam_random_string (AFPObj *,char *, int); + +#endif /* uam_auth.h */ diff --git a/etc/afpd/uid.c b/etc/afpd/uid.c new file mode 100644 index 0000000..a3e4d59 --- /dev/null +++ b/etc/afpd/uid.c @@ -0,0 +1,12 @@ +/* + * code: jeff@univrel.pr.uconn.edu + * + * These functions are abstracted here, so that all calls for resolving + * user/group names can be centrally changed (good for OS dependant calls + * across the package). + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + diff --git a/etc/afpd/uid.h b/etc/afpd/uid.h new file mode 100644 index 0000000..8774514 --- /dev/null +++ b/etc/afpd/uid.h @@ -0,0 +1,8 @@ +/* + * code: jeff@univrel.pr.uconn.edu + */ + +#ifndef AFPD_UID_H +#define AFPD_UID_H 1 + +#endif diff --git a/etc/afpd/unix.c b/etc/afpd/unix.c new file mode 100644 index 0000000..e928fda --- /dev/null +++ b/etc/afpd/unix.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "auth.h" +#include "directory.h" +#include "volume.h" +#include "unix.h" +#include "fork.h" +#ifdef HAVE_ACLS +#include "acls.h" +#endif + +/* + * Get the free space on a partition. + */ +int ustatfs_getvolspace(const struct vol *vol, VolSpace *bfree, VolSpace *btotal, uint32_t *bsize) +{ + VolSpace maxVolSpace = UINT64_MAX; + +#ifdef ultrix + struct fs_data sfs; +#else /*ultrix*/ + struct statfs sfs; +#endif /*ultrix*/ + + if ( statfs( vol->v_path, &sfs ) < 0 ) { + LOG(log_error, logtype_afpd, "ustatfs_getvolspace unable to stat %s", vol->v_path); + return( AFPERR_PARAM ); + } + +#ifdef ultrix + *bfree = (VolSpace) sfs.fd_req.bfreen; + *bsize = 1024; +#else /* !ultrix */ + *bfree = (VolSpace) sfs.f_bavail; + *bsize = sfs.f_frsize; +#endif /* ultrix */ + + if ( *bfree > maxVolSpace / *bsize ) { + *bfree = maxVolSpace; + } else { + *bfree *= *bsize; + } + +#ifdef ultrix + *btotal = (VolSpace) + ( sfs.fd_req.btot - ( sfs.fd_req.bfree - sfs.fd_req.bfreen )); +#else /* !ultrix */ + *btotal = (VolSpace) + ( sfs.f_blocks - ( sfs.f_bfree - sfs.f_bavail )); +#endif /* ultrix */ + + /* see similar block above comments */ + if ( *btotal > maxVolSpace / *bsize ) { + *btotal = maxVolSpace; + } else { + *btotal *= *bsize; + } + + return( AFP_OK ); +} + +static int utombits(mode_t bits) +{ + int mbits; + + mbits = 0; + + mbits |= ( bits & ( S_IREAD >> 6 )) ? AR_UREAD : 0; + mbits |= ( bits & ( S_IWRITE >> 6 )) ? AR_UWRITE : 0; + /* Do we really need this? */ + mbits |= ( bits & ( S_IEXEC >> 6) ) ? AR_USEARCH : 0; + + return( mbits ); +} + +/* -------------------------------- + cf AFP 3.0 page 63 +*/ +static void utommode(const AFPObj *obj, const struct stat *stat, struct maccess *ma) +{ + mode_t mode; + + mode = stat->st_mode; + ma->ma_world = utombits( mode ); + mode = mode >> 3; + + ma->ma_group = utombits( mode ); + mode = mode >> 3; + + ma->ma_owner = utombits( mode ); + + /* ma_user is a union of all permissions but we must follow + * unix perm + */ + if ( (obj->uid == stat->st_uid) || (obj->uid == 0)) { + ma->ma_user = ma->ma_owner | AR_UOWN; + } + else if (gmem(stat->st_gid, obj->ngroups, obj->groups)) { + ma->ma_user = ma->ma_group; + } + else { + ma->ma_user = ma->ma_world; + } + + /* + * There are certain things the mac won't try if you don't have + * the "owner" bit set, even tho you can do these things on unix wiht + * only write permission. What were the things? + * + * FIXME + * ditto seems to care if st_uid is 0 ? + * was ma->ma_user & AR_UWRITE + * but 0 as owner is a can of worms. + */ + if ( !stat->st_uid ) { + ma->ma_user |= AR_UOWN; + } +} + +#ifdef accessmode + +#undef accessmode +#endif +/* + * Calculate the mode for a directory using a stat() call to + * estimate permission. + * + * Note: the previous method, using access(), does not work correctly + * over NFS. + * + * dir parameter is used by AFS + */ +void accessmode(const AFPObj *obj, const struct vol *vol, char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st) +{ + struct stat sb; + + ma->ma_user = ma->ma_owner = ma->ma_world = ma->ma_group = 0; + if (!st) { + if (ostat(path, &sb, vol_syml_opt(vol)) != 0) + return; + st = &sb; + } + utommode(obj, st, ma ); +#ifdef HAVE_ACLS + acltoownermode(obj, vol, path, st, ma); +#endif +} + +static mode_t mtoubits(u_char bits) +{ + mode_t mode; + + mode = 0; + + mode |= ( bits & AR_UREAD ) ? ( (S_IREAD | S_IEXEC) >> 6 ) : 0; + mode |= ( bits & AR_UWRITE ) ? ( (S_IWRITE | S_IEXEC) >> 6 ) : 0; + /* I don't think there's a way to set the SEARCH bit by itself on a Mac + mode |= ( bits & AR_USEARCH ) ? ( S_IEXEC >> 6 ) : 0; */ + + return( mode ); +} + +/* ---------------------------------- + from the finder's share windows (menu--> File--> sharing...) + and from AFP 3.0 spec page 63 + the mac mode should be save somewhere +*/ +mode_t mtoumode(struct maccess *ma) +{ + mode_t mode; + + mode = 0; + mode |= mtoubits( ma->ma_owner |ma->ma_world); + mode = mode << 3; + + mode |= mtoubits( ma->ma_group |ma->ma_world); + mode = mode << 3; + + mode |= mtoubits( ma->ma_world ); + + return( mode ); +} + +/* --------------------- */ +int setfilunixmode (const struct vol *vol, struct path* path, mode_t mode) +{ + if (!path->st_valid) { + of_stat(vol, path); + } + + if (path->st_errno) { + return -1; + } + + mode |= vol->v_fperm; + + if (setfilmode(vol, path->u_name, mode, &path->st) < 0) + return -1; + /* we need to set write perm if read set for resource fork */ + return vol->vfs->vfs_setfilmode(vol, path->u_name, mode, &path->st); +} + + +/* --------------------- */ +int setdirunixmode(const struct vol *vol, char *name, mode_t mode) +{ + LOG(log_debug, logtype_afpd, "setdirunixmode('%s', mode:%04o) {v_dperm:%04o}", + fullpathname(name), mode, vol->v_dperm); + + mode |= vol->v_dperm | DIRBITS; + mode &= ~vol->v_umask; + + if (dir_rx_set(mode)) { + /* extending right? dir first then .AppleDouble in rf_setdirmode */ + if (ochmod(name, mode, NULL, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0) + return -1; + } + if (vol->vfs->vfs_setdirunixmode(vol, name, mode, NULL) < 0) { + return -1 ; + } + if (!dir_rx_set(mode)) { + if (ochmod(name, mode, NULL, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0) + return -1; + } + return 0; +} + +/* ----------------------------- */ +int setfilowner(const struct vol *vol, const uid_t uid, const gid_t gid, struct path* path) +{ + if (ochown( path->u_name, uid, gid, vol_syml_opt(vol)) < 0 && errno != EPERM ) { + LOG(log_debug, logtype_afpd, "setfilowner: chown %d/%d %s: %s", + uid, gid, path->u_name, strerror(errno)); + return -1; + } + + if (vol->vfs->vfs_chown(vol, path->u_name, uid, gid) < 0 && errno != EPERM) { + LOG(log_debug, logtype_afpd, "setfilowner: rf_chown %d/%d %s: %s", + uid, gid, path->u_name, strerror(errno) ); + return -1; + } + + return 0; +} + +/* --------------------------------- + * uid/gid == 0 need to be handled as special cases. they really mean + * that user/group should inherit from other, but that doesn't fit + * into the unix permission scheme. we can get around this by + * co-opting some bits. */ +int setdirowner(const struct vol *vol, const char *name, const uid_t uid, const gid_t gid) +{ + if (ochown(name, uid, gid, vol_syml_opt(vol)) < 0 && errno != EPERM ) { + LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s", + uid, gid, fullpathname(name), strerror(errno) ); + } + + if (vol->vfs->vfs_setdirowner(vol, name, uid, gid) < 0) + return -1; + + return( 0 ); +} diff --git a/etc/afpd/unix.h b/etc/afpd/unix.h new file mode 100644 index 0000000..3b3c281 --- /dev/null +++ b/etc/afpd/unix.h @@ -0,0 +1,227 @@ +#ifndef AFPD_UNIX_H +#define AFPD_UNIX_H + +#include + +#include "config.h" +#include "volume.h" + +#if defined( sun ) && !defined( __svr4__ ) +#ifdef i386 +typedef int mode_t; +#endif /*i386*/ +#endif /*sun __svr4__*/ + +#if defined(HAVE_SYS_VFS_H) || defined( sun ) || defined( ibm032 ) +#include +#endif /* HAVE_SYS_VFS_H || sun || ibm032 */ + +#if defined(_IBMR2) || defined(HAVE_STATFS_H) +#include +/* this might not be right. */ +#define f_mntfromname f_fname +#endif /* _IBMR2 || HAVE_STATFS_H */ + +#if defined(TRU64) +#define f_frsize f_fsize +#else /* TRU64 */ +/* temp fix, was: defined(HAVE_SYS_STATVFS) || defined(__svr4__) */ +#if defined(__svr4__) || (defined(__NetBSD__) && (__NetBSD_Version__ >= 200040000)) +#include +#define statfs statvfs +#else /* HAVE_SYS_STATVFS || __svr4__ */ +#define f_frsize f_bsize +#endif /* USE_STATVFS_H */ +#endif /* TRU64 */ + +#if defined(__svr4__) || defined(HAVE_SYS_MNTTAB_H) +#include +#endif /* __svr4__ || HAVE_SYS_MNTTAB_H */ + +#if defined(__DragonFly__) +#define dqblk ufs_dqblk +#endif + +#if defined(HAVE_SYS_MOUNT_H) || defined(BSD4_4) || \ + defined(linux) || defined(ultrix) +#include +#endif /* HAVE_SYS_MOUNT_H || BSD4_4 || linux || ultrix */ + +#if defined(linux) || defined(HAVE_MNTENT_H) +#include +#endif /* linux || HAVE_MNTENT_H */ + + +#ifndef NO_QUOTA_SUPPORT +#if !defined(HAVE_LIBQUOTA) + +#if !(defined(__svr4__) || defined(HAVE_DQB_BTIMELIMIT)) +#define dqb_btimelimit dqb_btime +#endif /* ! __svr4__ || HAVE_DQB_BTIMELIMIT */ + +#if defined(linux) || defined(ultrix) || defined(HAVE_QUOTA_H) +#ifndef NEED_QUOTACTL_WRAPPER +/*#include */ +/*long quotactl (int, const char *, unsigned int, caddr_t); */ +/* extern long quotactl (int, const char *, long, caddr_t); */ + +#else /* ! NEED_QUOTACTL_WRAPPER */ +#include +#include +#include +#endif /* ! NEED_QUOTACTL_WRAPPER */ +#endif /* linux || ultrix || HAVE_QUOTA_H */ + +#ifdef __svr4__ +#include +#endif /* __svr4__ */ + +#ifdef BSD4_4 +#include +#endif /* BSD4_4 */ + +#ifdef HAVE_UFS_QUOTA_H +#include +#endif /* HAVE_UFS_QUOTA_H */ + +#ifdef _IBMR2 +#include +#endif /* _IBMR2 */ + +#include +#include +#include +#include "directory.h" + + +#if defined (linux) + +#define MAXQUOTAS 2 + +/* definitions from sys/quota.h */ +#define USRQUOTA 0 /* element used for user quotas */ +#define GRPQUOTA 1 /* element used for group quotas */ + +/* + * Command definitions for the 'quotactl' system call. + * The commands are broken into a main command defined below + * and a subcommand that is used to convey the type of + * quota that is being manipulated (see above). + */ +#define SUBCMDMASK 0x00ff +#define SUBCMDSHIFT 8 +#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) + +/* declare an internal version of the quota block struct */ +typedef u_int64_t qsize_t; /* Type in which we store size limitations */ +typedef u_int32_t qid_t; /* Type in which we store ids in memory */ + +struct dqblk { + qsize_t bsize; + qsize_t dqb_ihardlimit; /* absolute limit on allocated inodes */ + qsize_t dqb_isoftlimit; /* preferred inode limit */ + qsize_t dqb_curinodes; /* current # allocated inodes */ + qsize_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + qsize_t dqb_bsoftlimit; /* preferred limit on disk blks */ + qsize_t dqb_curblocks; /* current block count */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive inode use */ +}; + +/* API v1 command definitions */ +#define Q_V1_GETQUOTA 0x0300 +#define Q_V1_SYNC 0x0600 +#define Q_V1_SETQLIM 0x0700 +#define Q_V1_GETSTATS 0x0800 +/* API v2 command definitions */ +#define Q_V2_SYNC 0x0600 +#define Q_V2_SETQLIM 0x0700 +#define Q_V2_GETQUOTA 0x0D00 +#define Q_V2_GETSTATS 0x1100 +/* proc API command definitions */ +#define Q_V3_SYNC 0x800001 +#define Q_V3_GETQUOTA 0x800007 +#define Q_V3_SETQUOTA 0x800008 + +/* Interface versions */ +#define IFACE_UNSET 0 +#define IFACE_VFSOLD 1 +#define IFACE_VFSV0 2 +#define IFACE_GENERIC 3 + +#define DEV_QBSIZE 1024 + +struct dqblk_v3 { + u_int64_t dqb_bhardlimit; + u_int64_t dqb_bsoftlimit; + u_int64_t dqb_curspace; + u_int64_t dqb_ihardlimit; + u_int64_t dqb_isoftlimit; + u_int64_t dqb_curinodes; + u_int64_t dqb_btime; + u_int64_t dqb_itime; + u_int32_t dqb_valid; +}; + +struct dqblk_v2 { + unsigned int dqb_ihardlimit; + unsigned int dqb_isoftlimit; + unsigned int dqb_curinodes; + unsigned int dqb_bhardlimit; + unsigned int dqb_bsoftlimit; + qsize_t dqb_curspace; + time_t dqb_btime; + time_t dqb_itime; +}; + +struct dqstats_v2 { + u_int32_t lookups; + u_int32_t drops; + u_int32_t reads; + u_int32_t writes; + u_int32_t cache_hits; + u_int32_t allocated_dquots; + u_int32_t free_dquots; + u_int32_t syncs; + u_int32_t version; +}; + +struct dqblk_v1 { + u_int32_t dqb_bhardlimit; + u_int32_t dqb_bsoftlimit; + u_int32_t dqb_curblocks; + u_int32_t dqb_ihardlimit; + u_int32_t dqb_isoftlimit; + u_int32_t dqb_curinodes; + time_t dqb_btime; + time_t dqb_itime; +}; + +extern long quotactl (unsigned int, const char *, int, caddr_t); + + + +#endif /* linux */ + +extern int getnfsquota (struct vol *, const int, const uint32_t, + struct dqblk *); + +#endif /* ! HAVE_LIBQUOTA */ +extern int uquota_getvolspace (const AFPObj *obj, struct vol *, VolSpace *, VolSpace *, + const uint32_t); +#endif /* NO_QUOTA_SUPPORT */ + +extern struct afp_options default_options; + +extern int setdirunixmode (const struct vol *, char *, mode_t); +extern int setdirmode (const struct vol *, const char *, mode_t); +extern int setdirowner (const struct vol *, const char *, const uid_t, const gid_t); +extern int setfilunixmode (const struct vol *, struct path*, const mode_t); +extern int setfilowner (const struct vol *, const uid_t, const gid_t, struct path*); +extern void accessmode (const AFPObj *obj, const struct vol *, char *, struct maccess *, struct dir *, struct stat *); + +#ifdef AFS + #define accessmode afsmode +#endif + +#endif /* UNIX_H */ diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c new file mode 100644 index 0000000..8fca000 --- /dev/null +++ b/etc/afpd/volume.c @@ -0,0 +1,1072 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CNID_DB +#include +#endif /* CNID_DB*/ + +#include "directory.h" +#include "file.h" +#include "volume.h" +#include "unix.h" +#include "mangle.h" +#include "fork.h" +#include "hash.h" +#include "acls.h" + +#define VOLPASSLEN 8 + +extern int afprun(int root, char *cmd, int *outfd); + +/*! + * Read band-size info from Info.plist XML file of an TM sparsebundle + * + * @param path (r) path to Info.plist file + * @return band-size in bytes, -1 on error + */ +static long long int get_tm_bandsize(const char *path) +{ + EC_INIT; + FILE *file = NULL; + char buf[512]; + long long int bandsize = -1; + + EC_NULL_LOGSTR( file = fopen(path, "r"), + "get_tm_bandsize(\"%s\"): %s", + path, strerror(errno) ); + + while (fgets(buf, sizeof(buf), file) != NULL) { + if (strstr(buf, "band-size") == NULL) + continue; + + if (fscanf(file, " %lld", &bandsize) != 1) { + LOG(log_error, logtype_afpd, "get_tm_bandsize(\"%s\"): can't parse band-size", path); + EC_FAIL; + } + break; + } + +EC_CLEANUP: + if (file) + fclose(file); + LOG(log_debug, logtype_afpd, "get_tm_bandsize(\"%s\"): bandsize: %lld", path, bandsize); + return bandsize; +} + +/*! + * Return number on entries in a directory + * + * @param path (r) path to dir + * @return number of entries, -1 on error + */ +static long long int get_tm_bands(const char *path) +{ + EC_INIT; + long long int count = 0; + DIR *dir = NULL; + const struct dirent *entry; + + EC_NULL( dir = opendir(path) ); + + while ((entry = readdir(dir)) != NULL) + count++; + count -= 2; /* All OSens I'm aware of return "." and "..", so just substract them, avoiding string comparison in loop */ + +EC_CLEANUP: + if (dir) + closedir(dir); + if (ret != 0) + return -1; + return count; +} + +/*! + * Calculate used size of a TimeMachine volume + * + * This assumes that the volume is used only for TimeMachine. + * + * 1) readdir(path of volume) + * 2) for every element that matches regex "\(.*\)\.sparsebundle$" : + * 3) parse "\1.sparsebundle/Info.plist" and read the band-size XML key integer value + * 4) readdir "\1.sparsebundle/bands/" counting files + * 5) calculate used size as: (file_count - 1) * band-size + * + * The result of the calculation is returned in "volume->v_tm_used". + * "volume->v_appended" gets reset to 0. + * "volume->v_tm_cachetime" is updated with the current time from time(NULL). + * + * "volume->v_tm_used" is cached for TM_USED_CACHETIME seconds and updated by + * "volume->v_appended". The latter is increased by X every time the client + * appends X bytes to a file (in fork.c). + * + * @param vol (rw) volume to calculate + * @return 0 on success, -1 on error + */ +#define TM_USED_CACHETIME 60 /* cache for 60 seconds */ +static int get_tm_used(struct vol * restrict vol) +{ + EC_INIT; + long long int bandsize; + VolSpace used = 0; + bstring infoplist = NULL; + bstring bandsdir = NULL; + DIR *dir = NULL; + const struct dirent *entry; + const char *p; + long int links; + time_t now = time(NULL); + + if (vol->v_tm_cachetime + && ((vol->v_tm_cachetime + TM_USED_CACHETIME) >= now)) { + if (vol->v_tm_used == -1) + EC_FAIL; + vol->v_tm_used += vol->v_appended; + vol->v_appended = 0; + LOG(log_debug, logtype_afpd, "getused(\"%s\"): cached: %" PRIu64 " bytes", + vol->v_path, vol->v_tm_used); + return 0; + } + + vol->v_tm_cachetime = now; + + EC_NULL( dir = opendir(vol->v_path) ); + + while ((entry = readdir(dir)) != NULL) { + if (((p = strstr(entry->d_name, "sparsebundle")) != NULL) + && (strlen(entry->d_name) == (p + strlen("sparsebundle") - entry->d_name))) { + + EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") ); + + if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1) { + bdestroy(infoplist); + continue; + } + + EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") ); + + if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1) { + bdestroy(infoplist); + bdestroy(bandsdir); + continue; + } + + used += (links - 1) * bandsize; + LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes", + cfrombstr(bandsdir), used); + } + } + + vol->v_tm_used = used; + +EC_CLEANUP: + if (infoplist) + bdestroy(infoplist); + if (bandsdir) + bdestroy(bandsdir); + if (dir) + closedir(dir); + + LOG(log_debug, logtype_afpd, "getused(\"%s\"): %" PRIu64 " bytes", vol->v_path, vol->v_tm_used); + + EC_EXIT; +} + +static int getvolspace(const AFPObj *obj, struct vol *vol, + uint32_t *bfree, uint32_t *btotal, + VolSpace *xbfree, VolSpace *xbtotal, uint32_t *bsize) +{ + int spaceflag, rc; + uint32_t maxsize; +#ifndef NO_QUOTA_SUPPORT + VolSpace qfree, qtotal; +#endif + + spaceflag = AFPVOL_GVSMASK & vol->v_flags; + /* report up to 2GB if afp version is < 2.2 (4GB if not) */ + maxsize = (obj->afp_version < 22) ? 0x7fffffffL : 0xffffffffL; + +#ifdef AFS + if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_AFSGVS ) { + if ( afs_getvolspace( vol, xbfree, xbtotal, bsize ) == AFP_OK ) { + vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_AFSGVS; + goto getvolspace_done; + } + } +#endif + + if (( rc = ustatfs_getvolspace( vol, xbfree, xbtotal, bsize)) != AFP_OK ) { + return( rc ); + } + +#ifndef NO_QUOTA_SUPPORT + if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_UQUOTA ) { + if ( uquota_getvolspace(obj, vol, &qfree, &qtotal, *bsize ) == AFP_OK ) { + vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_UQUOTA; + *xbfree = MIN(*xbfree, qfree); + *xbtotal = MIN(*xbtotal, qtotal); + goto getvolspace_done; + } + } +#endif + vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_USTATFS; + +getvolspace_done: + if (vol->v_limitsize) { + if (get_tm_used(vol) != 0) + return AFPERR_MISC; + + *xbtotal = MIN(*xbtotal, (vol->v_limitsize * 1024 * 1024)); + *xbfree = MIN(*xbfree, *xbtotal < vol->v_tm_used ? 0 : *xbtotal - vol->v_tm_used); + + LOG(log_debug, logtype_afpd, + "volparams: total: %" PRIu64 ", used: %" PRIu64 ", free: %" PRIu64 " bytes", + *xbtotal, vol->v_tm_used, *xbfree); + } + + *bfree = MIN(*xbfree, maxsize); + *btotal = MIN(*xbtotal, maxsize); + return( AFP_OK ); +} + +/* ----------------------- + * set volume creation date + * avoid duplicate, well at least it tries + */ +static void vol_setdate(uint16_t id, struct adouble *adp, time_t date) +{ + struct vol *volume; + struct vol *vol = getvolumes(); + + for ( volume = getvolumes(); volume; volume = volume->v_next ) { + if (volume->v_vid == id) { + vol = volume; + } + else if ((time_t)(AD_DATE_FROM_UNIX(date)) == volume->v_ctime) { + date = date+1; + volume = getvolumes(); /* restart */ + } + } + vol->v_ctime = AD_DATE_FROM_UNIX(date); + ad_setdate(adp, AD_DATE_CREATE | AD_DATE_UNIX, date); +} + +/* ----------------------- */ +static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen) +{ + struct adouble ad; + int bit = 0, isad = 1; + uint32_t aint; + u_short ashort; + uint32_t bfree, btotal, bsize; + VolSpace xbfree, xbtotal; /* extended bytes */ + char *data, *nameoff = NULL; + char *slash; + + LOG(log_debug, logtype_afpd, "getvolparams: Volume '%s'", vol->v_localname); + + /* courtesy of jallison@whistle.com: + * For MacOS8.x support we need to create the + * .Parent file here if it doesn't exist. */ + + /* Convert adouble:v2 to adouble:ea on the fly */ + (void)ad_convert(vol->v_path, st, vol, NULL); + + ad_init(&ad, vol); + if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0 ) { + isad = 0; + vol->v_ctime = AD_DATE_FROM_UNIX(st->st_mtime); + + } else if (ad_get_MD_flags( &ad ) & O_CREAT) { + slash = strrchr( vol->v_path, '/' ); + if(slash) + slash++; + else + slash = vol->v_path; + if (ad_getentryoff(&ad, ADEID_NAME)) { + ad_setentrylen( &ad, ADEID_NAME, strlen( slash )); + memcpy(ad_entry( &ad, ADEID_NAME ), slash, + ad_getentrylen( &ad, ADEID_NAME )); + } + vol_setdate(vol->v_vid, &ad, st->st_mtime); + ad_flush(&ad); + } + else { + if (ad_getdate(&ad, AD_DATE_CREATE, &aint) < 0) + vol->v_ctime = AD_DATE_FROM_UNIX(st->st_mtime); + else + vol->v_ctime = aint; + } + + if (( bitmap & ( (1<>1; + bit++; + } + + switch ( bit ) { + case VOLPBIT_ATTR : + ashort = 0; + /* check for read-only. + * NOTE: we don't actually set the read-only flag unless + * it's passed in that way as it's possible to mount + * a read-write filesystem under a read-only one. */ + if ((vol->v_flags & AFPVOL_RO) || + ((utime(vol->v_path, NULL) < 0) && (errno == EROFS))) { + ashort |= VOLPBIT_ATTR_RO; + } + /* prior 2.1 only VOLPBIT_ATTR_RO is defined */ + if (obj->afp_version > 20) { + if (vol->v_cdb != NULL && (vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) + ashort |= VOLPBIT_ATTR_FILEID; + ashort |= VOLPBIT_ATTR_CATSEARCH; + + if (obj->afp_version >= 30) { + ashort |= VOLPBIT_ATTR_UTF8; + if (vol->v_flags & AFPVOL_UNIX_PRIV) + ashort |= VOLPBIT_ATTR_UNIXPRIV; + if (vol->v_flags & AFPVOL_TM) + ashort |= VOLPBIT_ATTR_TM; + if (vol->v_flags & AFPVOL_NONETIDS) + ashort |= VOLPBIT_ATTR_NONETIDS; + if (obj->afp_version >= 32) { + if (vol->v_vfs_ea) + ashort |= VOLPBIT_ATTR_EXT_ATTRS; + if (vol->v_flags & AFPVOL_ACLS) + ashort |= VOLPBIT_ATTR_ACLS; + if (vol->v_casefold & AFPVOL_CASESENS) + ashort |= VOLPBIT_ATTR_CASESENS; + } + } + } + ashort = htons(ashort); + memcpy(data, &ashort, sizeof( ashort )); + data += sizeof( ashort ); + break; + + case VOLPBIT_SIG : + ashort = htons( AFPVOLSIG_DEFAULT ); + memcpy(data, &ashort, sizeof( ashort )); + data += sizeof( ashort ); + break; + + case VOLPBIT_CDATE : + aint = vol->v_ctime; + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case VOLPBIT_MDATE : + if ( st->st_mtime > vol->v_mtime ) { + vol->v_mtime = st->st_mtime; + } + aint = AD_DATE_FROM_UNIX(vol->v_mtime); + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case VOLPBIT_BDATE : + if (!isad || (ad_getdate(&ad, AD_DATE_BACKUP, &aint) < 0)) + aint = AD_DATE_START; + memcpy(data, &aint, sizeof( aint )); + data += sizeof( aint ); + break; + + case VOLPBIT_VID : + memcpy(data, &vol->v_vid, sizeof( vol->v_vid )); + data += sizeof( vol->v_vid ); + break; + + case VOLPBIT_BFREE : + bfree = htonl( bfree ); + memcpy(data, &bfree, sizeof( bfree )); + data += sizeof( bfree ); + break; + + case VOLPBIT_BTOTAL : + btotal = htonl( btotal ); + memcpy(data, &btotal, sizeof( btotal )); + data += sizeof( btotal ); + break; + +#ifndef NO_LARGE_VOL_SUPPORT + case VOLPBIT_XBFREE : + xbfree = hton64( xbfree ); + memcpy(data, &xbfree, sizeof( xbfree )); + data += sizeof( xbfree ); + break; + + case VOLPBIT_XBTOTAL : + xbtotal = hton64( xbtotal ); + memcpy(data, &xbtotal, sizeof( xbtotal )); + data += sizeof( xbfree ); + break; +#endif /* ! NO_LARGE_VOL_SUPPORT */ + + case VOLPBIT_NAME : + nameoff = data; + data += sizeof( uint16_t ); + break; + + case VOLPBIT_BSIZE: /* block size */ + bsize = htonl(bsize); + memcpy(data, &bsize, sizeof(bsize)); + data += sizeof(bsize); + break; + + default : + if ( isad ) { + ad_close( &ad, ADFLAGS_HF ); + } + return( AFPERR_BITMAP ); + } + bitmap = bitmap>>1; + bit++; + } + if ( nameoff ) { + ashort = htons( data - buf ); + memcpy(nameoff, &ashort, sizeof( ashort )); + /* name is always in mac charset */ + aint = ucs2_to_charset( vol->v_maccharset, vol->v_macname, data+1, AFPVOL_MACNAMELEN + 1); + if ( aint <= 0 ) { + *buflen = 0; + return AFPERR_MISC; + } + + *data++ = aint; + data += aint; + } + if ( isad ) { + ad_close(&ad, ADFLAGS_HF); + } + *buflen = data - buf; + return( AFP_OK ); +} + +/* ------------------------- */ +static int stat_vol(const AFPObj *obj, uint16_t bitmap, struct vol *vol, char *rbuf, size_t *rbuflen) +{ + struct stat st; + int ret; + size_t buflen; + + if ( stat( vol->v_path, &st ) < 0 ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + /* save the volume device number */ + vol->v_dev = st.st_dev; + + buflen = *rbuflen - sizeof( bitmap ); + if (( ret = getvolparams(obj, bitmap, vol, &st, + rbuf + sizeof( bitmap ), &buflen )) != AFP_OK ) { + *rbuflen = 0; + return( ret ); + } + *rbuflen = buflen + sizeof( bitmap ); + bitmap = htons( bitmap ); + memcpy(rbuf, &bitmap, sizeof( bitmap )); + return( AFP_OK ); + +} + +/* ------------------------------- */ +int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct timeval tv; + struct stat st; + struct vol *volume; + char *data; + char *namebuf; + int vcnt; + size_t len; + uint32_t aint; + + load_volumes(obj, lv_none); + + data = rbuf + 5; + for ( vcnt = 0, volume = getvolumes(); volume && vcnt < 255; volume = volume->v_next ) { + if (!(volume->v_flags & AFPVOL_NOSTAT)) { + struct maccess ma; + + if ( stat( volume->v_path, &st ) < 0 ) { + LOG(log_info, logtype_afpd, "afp_getsrvrparms(%s): stat: %s", + volume->v_path, strerror(errno) ); + continue; /* can't access directory */ + } + if (!S_ISDIR(st.st_mode)) { + continue; /* not a dir */ + } + accessmode(obj, volume, volume->v_path, &ma, NULL, &st); + if ((ma.ma_user & (AR_UREAD | AR_USEARCH)) != (AR_UREAD | AR_USEARCH)) { + continue; /* no r-x access */ + } + } + + if (utf8_encoding(obj)) { + len = ucs2_to_charset_allocate(CH_UTF8_MAC, &namebuf, volume->v_u8mname); + } else { + len = ucs2_to_charset_allocate(obj->options.maccharset, &namebuf, volume->v_macname); + } + + if (len == (size_t)-1) + continue; + + /* + * There seems to be an undocumented limit on how big our reply can get + * before the client chokes and closes the connection. + * Testing with 10.8.4 found the limit at ~4600 bytes. Go figure. + */ + if (((data + len + 3) - rbuf) > 4600) + break; + + /* set password bit if there's a volume password */ + *data = (volume->v_password) ? AFPSRVR_PASSWD : 0; + + *data++ |= 0; /* UNIX PRIVS BIT ..., OSX doesn't seem to use it, so we don't either */ + *data++ = len; + memcpy(data, namebuf, len ); + data += len; + free(namebuf); + vcnt++; + } + + *rbuflen = data - rbuf; + data = rbuf; + if ( gettimeofday( &tv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_getsrvrparms: gettimeofday: %s", strerror(errno) ); + *rbuflen = 0; + return AFPERR_PARAM; + } + + aint = AD_DATE_FROM_UNIX(tv.tv_sec); + memcpy(data, &aint, sizeof( uint32_t)); + data += sizeof( uint32_t); + *data = vcnt; + return( AFP_OK ); +} + +/* ------------------------- */ +static int volume_codepage(AFPObj *obj, struct vol *volume) +{ + struct charset_functions *charset; + /* Codepages */ + + if (!volume->v_volcodepage) + volume->v_volcodepage = strdup("UTF8"); + + if ( (charset_t) -1 == ( volume->v_volcharset = add_charset(volume->v_volcodepage)) ) { + LOG (log_error, logtype_afpd, "Setting codepage %s as volume codepage failed", volume->v_volcodepage); + return -1; + } + + if ( NULL == (charset = find_charset_functions(volume->v_volcodepage)) || charset->flags & CHARSET_ICONV ) { + LOG (log_warning, logtype_afpd, "WARNING: volume encoding %s is *not* supported by netatalk, expect problems !!!!", volume->v_volcodepage); + } + + if (!volume->v_maccodepage) + volume->v_maccodepage = strdup(obj->options.maccodepage); + + if ( (charset_t) -1 == ( volume->v_maccharset = add_charset(volume->v_maccodepage)) ) { + LOG (log_error, logtype_afpd, "Setting codepage %s as mac codepage failed", volume->v_maccodepage); + return -1; + } + + if ( NULL == ( charset = find_charset_functions(volume->v_maccodepage)) || ! (charset->flags & CHARSET_CLIENT) ) { + LOG (log_error, logtype_afpd, "Fatal error: mac charset %s not supported", volume->v_maccodepage); + return -1; + } + volume->v_kTextEncoding = htonl(charset->kTextEncoding); + return 0; +} + +/* ------------------------- */ +static int volume_openDB(const AFPObj *obj, struct vol *volume) +{ + int flags = 0; + + if ((volume->v_flags & AFPVOL_NODEV)) { + flags |= CNID_FLAG_NODEV; + } + + volume->v_cdb = cnid_open(volume, volume->v_cnidscheme, flags); + + if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) { + /* The first attempt failed and it wasn't yet an attempt to open in-memory */ + LOG(log_error, logtype_afpd, "Can't open volume \"%s\" CNID backend \"%s\" ", + volume->v_path, volume->v_cnidscheme); + LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", + volume->v_path); + flags |= CNID_FLAG_MEMORY; + volume->v_cdb = cnid_open(volume, "tdb", flags); +#ifdef SERVERTEXT + /* kill ourself with SIGUSR2 aka msg pending */ + if (volume->v_cdb) { + setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead." + "Check server messages for details!"); + kill(getpid(), SIGUSR2); + /* deactivate cnid caching/storing in AppleDouble files */ + } +#endif + } + + return (!volume->v_cdb)?-1:0; +} + +/* + * Send list of open volumes to afpd master via IPC + */ +static void server_ipc_volumes(AFPObj *obj) +{ + struct vol *volume, *vols; + volume = vols = getvolumes(); + bstring openvolnames = bfromcstr(""); + bool firstvol = true; + + while (volume) { + if (volume->v_flags & AFPVOL_OPEN) { + if (!firstvol) + bcatcstr(openvolnames, ", "); + else + firstvol = false; + bcatcstr(openvolnames, volume->v_localname); + } + volume = volume->v_next; + } + + ipc_child_write(obj->ipc_fd, IPC_VOLUMES, blength(openvolnames), bdata(openvolnames)); + bdestroy(openvolnames); +} + +/* ------------------------- + * we are the user here + */ +int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) +{ + struct stat st; + char *volname; + + struct vol *volume; + struct dir *dir; + int len, ret; + size_t namelen; + uint16_t bitmap; + char *vol_uname; + char *vol_mname = NULL; + char *volname_tmp; + + ibuf += 2; + memcpy(&bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof( bitmap ); + + *rbuflen = 0; + if (( bitmap & (1<oldtmp; + + if ((volname_tmp = strchr(volname,'+')) != NULL) + volname = volname_tmp+1; + + if (utf8_encoding(obj)) { + namelen = convert_string(CH_UTF8_MAC, CH_UCS2, ibuf, len, volname, sizeof(obj->oldtmp)); + } else { + namelen = convert_string(obj->options.maccharset, CH_UCS2, ibuf, len, volname, sizeof(obj->oldtmp)); + } + + if ( namelen <= 0) { + return AFPERR_PARAM; + } + + ibuf += len; + if ((len + 1) & 1) /* pad to an even boundary */ + ibuf++; + + load_volumes(obj, lv_none); + + for ( volume = getvolumes(); volume; volume = volume->v_next ) { + if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) { + break; + } + } + + if ( volume == NULL ) { + return AFPERR_NOOBJ; + } + + /* check for a volume password */ + if (volume->v_password && strncmp(ibuf, volume->v_password, VOLPASSLEN)) { + return AFPERR_ACCESS; + } + + if (( volume->v_flags & AFPVOL_OPEN ) ) { + /* the volume is already open */ + return stat_vol(obj, bitmap, volume, rbuf, rbuflen); + } + + if (volume->v_root_preexec) { + if ((ret = afprun(1, volume->v_root_preexec, NULL)) && volume->v_root_preexec_close) { + LOG(log_error, logtype_afpd, "afp_openvol(%s): root preexec : %d", volume->v_path, ret ); + return AFPERR_MISC; + } + } + + if (volume->v_preexec) { + if ((ret = afprun(0, volume->v_preexec, NULL)) && volume->v_preexec_close) { + LOG(log_error, logtype_afpd, "afp_openvol(%s): preexec : %d", volume->v_path, ret ); + return AFPERR_MISC; + } + } + + if ( stat( volume->v_path, &st ) < 0 ) { + return AFPERR_PARAM; + } + + if ( chdir( volume->v_path ) < 0 ) { + return AFPERR_PARAM; + } + + if (volume_codepage(obj, volume) < 0) { + ret = AFPERR_MISC; + goto openvol_err; + } + + /* initialize volume variables + * FIXME file size + */ + if (utf8_encoding(obj)) { + volume->max_filename = UTF8FILELEN_EARLY; + } + else { + volume->max_filename = MACFILELEN; + } + + volume->v_flags |= AFPVOL_OPEN; + volume->v_cdb = NULL; + + if (utf8_encoding(obj)) { + len = convert_string_allocate(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, namelen, &vol_mname); + } else { + len = convert_string_allocate(CH_UCS2, obj->options.maccharset, volume->v_macname, namelen, &vol_mname); + } + if ( !vol_mname || len <= 0) { + ret = AFPERR_MISC; + goto openvol_err; + } + + if ((vol_uname = strrchr(volume->v_path, '/')) == NULL) + vol_uname = volume->v_path; + else if (vol_uname[1] != '\0') + vol_uname++; + + if ((dir = dir_new(vol_mname, + vol_uname, + volume, + DIRDID_ROOT_PARENT, + DIRDID_ROOT, + bfromcstr(volume->v_path), + &st) + ) == NULL) { + free(vol_mname); + LOG(log_error, logtype_afpd, "afp_openvol(%s): malloc: %s", volume->v_path, strerror(errno) ); + ret = AFPERR_MISC; + goto openvol_err; + } + volume->v_root = dir; + curdir = dir; + + if (volume_openDB(obj, volume) < 0) { + LOG(log_error, logtype_afpd, "Fatal error: cannot open CNID or invalid CNID backend for %s: %s", + volume->v_path, volume->v_cnidscheme); + ret = AFPERR_MISC; + goto openvol_err; + } + + ret = stat_vol(obj, bitmap, volume, rbuf, rbuflen); + + if (ret == AFP_OK) { + /* + * If you mount a volume twice, the second time the trash appears on + * the desk-top. That's because the Mac remembers the DID for the + * trash (even for volumes in different zones, on different servers). + * Just so this works better, we prime the DID cache with the trash, + * fixing the trash at DID 17. + * FIXME (RL): should it be done inside a CNID backend ? (always returning Trash DID when asked) ? + */ + if ((volume->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { + + /* FIXME find db time stamp */ + if (cnid_getstamp(volume->v_cdb, volume->v_stamp, sizeof(volume->v_stamp)) < 0) { + LOG (log_error, logtype_afpd, + "afp_openvol(%s): Fatal error: Unable to get stamp value from CNID backend", + volume->v_path); + ret = AFPERR_MISC; + goto openvol_err; + } + } + + const char *msg; + if ((msg = atalk_iniparser_getstring(obj->iniconfig, volume->v_configname, "login message", NULL)) != NULL) + setmessage(msg); + + free(vol_mname); + server_ipc_volumes(obj); + return( AFP_OK ); + } + +openvol_err: + if (volume->v_root) { + dir_free( volume->v_root ); + volume->v_root = NULL; + } + + volume->v_flags &= ~AFPVOL_OPEN; + if (volume->v_cdb != NULL) { + cnid_close(volume->v_cdb); + volume->v_cdb = NULL; + } + free(vol_mname); + *rbuflen = 0; + return ret; +} + +void closevol(const AFPObj *obj, struct vol *vol) +{ + if (!vol) + return; + + vol->v_flags &= ~AFPVOL_OPEN; + + of_closevol(obj, vol); + + dir_free( vol->v_root ); + vol->v_root = NULL; + if (vol->v_cdb != NULL) { + cnid_close(vol->v_cdb); + vol->v_cdb = NULL; + } + + if (vol->v_postexec) { + afprun(0, vol->v_postexec, NULL); + } + if (vol->v_root_postexec) { + afprun(1, vol->v_root_postexec, NULL); + } +} + +/* ------------------------- */ +void close_all_vol(const AFPObj *obj) +{ + struct vol *ovol; + curdir = NULL; + for ( ovol = getvolumes(); ovol; ovol = ovol->v_next ) { + if ( (ovol->v_flags & AFPVOL_OPEN) ) { + ovol->v_flags &= ~AFPVOL_OPEN; + closevol(obj, ovol); + } + } +} + +/* ------------------------- */ +int afp_closevol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct vol *vol; + uint16_t vid; + + *rbuflen = 0; + ibuf += 2; + memcpy(&vid, ibuf, sizeof( vid )); + if (NULL == ( vol = getvolbyvid( vid )) ) { + return( AFPERR_PARAM ); + } + + (void)chdir("/"); + curdir = NULL; + closevol(obj, vol); + server_ipc_volumes(obj); + + return( AFP_OK ); +} + +/* -------------------------- + poll if a volume is changed by other processes. + return + 0 no attention msg sent + 1 attention msg sent + -1 error (socket closed) + + Note: if attention return -1 no packet has been + sent because the buffer is full, we don't care + either there's no reader or there's a lot of + traffic and another pollvoltime will follow +*/ +int pollvoltime(AFPObj *obj) + +{ + struct vol *vol; + struct timeval tv; + struct stat st; + + if (!(obj->afp_version > 21 && obj->options.flags & OPTION_SERVERNOTIF)) + return 0; + + if ( gettimeofday( &tv, NULL ) < 0 ) + return 0; + + for ( vol = getvolumes(); vol; vol = vol->v_next ) { + if ( (vol->v_flags & AFPVOL_OPEN) && vol->v_mtime + 30 < tv.tv_sec) { + if ( !stat( vol->v_path, &st ) && vol->v_mtime != st.st_mtime ) { + vol->v_mtime = st.st_mtime; + if (!obj->attention(obj->dsi, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED)) + return -1; + return 1; + } + } + } + return 0; +} + +/* ------------------------- */ +void setvoltime(AFPObj *obj, struct vol *vol) +{ + struct timeval tv; + + if ( gettimeofday( &tv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "setvoltime(%s): gettimeofday: %s", vol->v_path, strerror(errno) ); + return; + } + if( utime( vol->v_path, NULL ) < 0 ) { + /* write of time failed ... probably a read only filesys, + * where no other users can interfere, so there's no issue here + */ + } + + /* a little granularity */ + if (vol->v_mtime < tv.tv_sec) { + vol->v_mtime = tv.tv_sec; + /* or finder doesn't update free space + * AFP 3.2 and above clients seem to be ok without so many notification + */ + if (obj->afp_version < 32 && obj->options.flags & OPTION_SERVERNOTIF) { + obj->attention(obj->dsi, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED); + } + } +} + +/* ------------------------- */ +int afp_getvolparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_,char *rbuf, size_t *rbuflen) +{ + struct vol *vol; + uint16_t vid, bitmap; + + ibuf += 2; + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + memcpy(&bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + + if (NULL == ( vol = getvolbyvid( vid )) ) { + *rbuflen = 0; + return( AFPERR_PARAM ); + } + + return stat_vol(obj, bitmap, vol, rbuf, rbuflen); +} + +/* ------------------------- */ +int afp_setvolparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct adouble ad; + struct vol *vol; + uint16_t vid, bitmap; + uint32_t aint; + + ibuf += 2; + *rbuflen = 0; + + memcpy(&vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + memcpy(&bitmap, ibuf, sizeof( bitmap )); + bitmap = ntohs( bitmap ); + ibuf += sizeof(bitmap); + + if (( vol = getvolbyvid( vid )) == NULL ) { + return( AFPERR_PARAM ); + } + + if ((vol->v_flags & AFPVOL_RO)) + return AFPERR_VLOCK; + + /* we can only set the backup date. */ + if (bitmap != (1 << VOLPBIT_BDATE)) + return AFPERR_BITMAP; + + ad_init(&ad, vol); + if ( ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR) < 0 ) { + if (errno == EROFS) + return AFPERR_VLOCK; + + return AFPERR_ACCESS; + } + + memcpy(&aint, ibuf, sizeof(aint)); + ad_setdate(&ad, AD_DATE_BACKUP, aint); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + return( AFP_OK ); +} diff --git a/etc/afpd/volume.h b/etc/afpd/volume.h new file mode 100644 index 0000000..a8bd2b8 --- /dev/null +++ b/etc/afpd/volume.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1990,1994 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifndef AFPD_VOLUME_H +#define AFPD_VOLUME_H 1 + +#include +#include + +#include +#include +#include +#include + +extern int ustatfs_getvolspace (const struct vol *, + VolSpace *, VolSpace *, + uint32_t *); +extern void setvoltime (AFPObj *, struct vol *); +extern int pollvoltime (AFPObj *); + +/* FP functions */ +int afp_openvol (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getvolparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_setvolparams (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_getsrvrparms (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); +int afp_closevol (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +/* netatalk functions */ +extern void close_all_vol(const AFPObj *obj); +extern void closevol(const AFPObj *obj, struct vol *vol); +#endif diff --git a/etc/cnid_dbd/Makefile.am b/etc/cnid_dbd/Makefile.am new file mode 100644 index 0000000..a9133d9 --- /dev/null +++ b/etc/cnid_dbd/Makefile.am @@ -0,0 +1,33 @@ +# Makefile.am for etc/cnid_dbd/ + +if BUILD_DBD_DAEMON +sbin_PROGRAMS = cnid_dbd cnid_metad +bin_PROGRAMS = dbd +else +sbin_PROGRAMS = +endif + +cnid_dbd_SOURCES = dbif.c pack.c comm.c db_param.c main.c \ + dbd_add.c dbd_get.c dbd_resolve.c dbd_lookup.c \ + dbd_update.c dbd_delete.c dbd_getstamp.c \ + dbd_rebuild_add.c dbd_dbcheck.c dbd_search.c +cnid_dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@ @ACL_LIBS@ @MYSQL_LIBS@ + +cnid_metad_SOURCES = cnid_metad.c usockfd.c db_param.c +cnid_metad_LDADD = $(top_builddir)/libatalk/libatalk.la @ACL_LIBS@ @MYSQL_LIBS@ + +dbd_SOURCES = cmd_dbd.c \ + cmd_dbd_scanvol.c \ + dbif.c pack.c \ + dbd_add.c \ + dbd_delete.c \ + dbd_getstamp.c \ + dbd_lookup.c \ + dbd_rebuild_add.c \ + dbd_resolve.c \ + dbd_update.c +dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@ @ACL_LIBS@ @MYSQL_LIBS@ + +noinst_HEADERS = dbif.h pack.h db_param.h dbd.h usockfd.h comm.h cmd_dbd.h + +AM_CFLAGS = @BDB_CFLAGS@ -D_PATH_CNID_DBD=\"$(sbindir)/cnid_dbd\" diff --git a/etc/cnid_dbd/Makefile.in b/etc/cnid_dbd/Makefile.in new file mode 100644 index 0000000..b78c877 --- /dev/null +++ b/etc/cnid_dbd/Makefile.in @@ -0,0 +1,814 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for etc/cnid_dbd/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@BUILD_DBD_DAEMON_TRUE@sbin_PROGRAMS = cnid_dbd$(EXEEXT) \ +@BUILD_DBD_DAEMON_TRUE@ cnid_metad$(EXEEXT) +@BUILD_DBD_DAEMON_TRUE@bin_PROGRAMS = dbd$(EXEEXT) +subdir = etc/cnid_dbd +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" +PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) +am_cnid_dbd_OBJECTS = dbif.$(OBJEXT) pack.$(OBJEXT) comm.$(OBJEXT) \ + db_param.$(OBJEXT) main.$(OBJEXT) dbd_add.$(OBJEXT) \ + dbd_get.$(OBJEXT) dbd_resolve.$(OBJEXT) dbd_lookup.$(OBJEXT) \ + dbd_update.$(OBJEXT) dbd_delete.$(OBJEXT) \ + dbd_getstamp.$(OBJEXT) dbd_rebuild_add.$(OBJEXT) \ + dbd_dbcheck.$(OBJEXT) dbd_search.$(OBJEXT) +cnid_dbd_OBJECTS = $(am_cnid_dbd_OBJECTS) +cnid_dbd_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_cnid_metad_OBJECTS = cnid_metad.$(OBJEXT) usockfd.$(OBJEXT) \ + db_param.$(OBJEXT) +cnid_metad_OBJECTS = $(am_cnid_metad_OBJECTS) +cnid_metad_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +am_dbd_OBJECTS = cmd_dbd.$(OBJEXT) cmd_dbd_scanvol.$(OBJEXT) \ + dbif.$(OBJEXT) pack.$(OBJEXT) dbd_add.$(OBJEXT) \ + dbd_delete.$(OBJEXT) dbd_getstamp.$(OBJEXT) \ + dbd_lookup.$(OBJEXT) dbd_rebuild_add.$(OBJEXT) \ + dbd_resolve.$(OBJEXT) dbd_update.$(OBJEXT) +dbd_OBJECTS = $(am_dbd_OBJECTS) +dbd_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(cnid_dbd_SOURCES) $(cnid_metad_SOURCES) $(dbd_SOURCES) +DIST_SOURCES = $(cnid_dbd_SOURCES) $(cnid_metad_SOURCES) \ + $(dbd_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +cnid_dbd_SOURCES = dbif.c pack.c comm.c db_param.c main.c \ + dbd_add.c dbd_get.c dbd_resolve.c dbd_lookup.c \ + dbd_update.c dbd_delete.c dbd_getstamp.c \ + dbd_rebuild_add.c dbd_dbcheck.c dbd_search.c + +cnid_dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@ @ACL_LIBS@ @MYSQL_LIBS@ +cnid_metad_SOURCES = cnid_metad.c usockfd.c db_param.c +cnid_metad_LDADD = $(top_builddir)/libatalk/libatalk.la @ACL_LIBS@ @MYSQL_LIBS@ +dbd_SOURCES = cmd_dbd.c \ + cmd_dbd_scanvol.c \ + dbif.c pack.c \ + dbd_add.c \ + dbd_delete.c \ + dbd_getstamp.c \ + dbd_lookup.c \ + dbd_rebuild_add.c \ + dbd_resolve.c \ + dbd_update.c + +dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@ @ACL_LIBS@ @MYSQL_LIBS@ +noinst_HEADERS = dbif.h pack.h db_param.h dbd.h usockfd.h comm.h cmd_dbd.h +AM_CFLAGS = @BDB_CFLAGS@ -D_PATH_CNID_DBD=\"$(sbindir)/cnid_dbd\" +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign etc/cnid_dbd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign etc/cnid_dbd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +cnid_dbd$(EXEEXT): $(cnid_dbd_OBJECTS) $(cnid_dbd_DEPENDENCIES) $(EXTRA_cnid_dbd_DEPENDENCIES) + @rm -f cnid_dbd$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cnid_dbd_OBJECTS) $(cnid_dbd_LDADD) $(LIBS) +cnid_metad$(EXEEXT): $(cnid_metad_OBJECTS) $(cnid_metad_DEPENDENCIES) $(EXTRA_cnid_metad_DEPENDENCIES) + @rm -f cnid_metad$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cnid_metad_OBJECTS) $(cnid_metad_LDADD) $(LIBS) +dbd$(EXEEXT): $(dbd_OBJECTS) $(dbd_DEPENDENCIES) $(EXTRA_dbd_DEPENDENCIES) + @rm -f dbd$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dbd_OBJECTS) $(dbd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd_dbd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd_dbd_scanvol.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cnid_metad.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db_param.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_dbcheck.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_get.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_getstamp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_lookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_rebuild_add.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_resolve.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_search.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbd_update.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbif.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pack.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usockfd.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool clean-sbinPROGRAMS cscopelist \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-sbinPROGRAMS + + +# 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/etc/cnid_dbd/cmd_dbd.c b/etc/cnid_dbd/cmd_dbd.c new file mode 100644 index 0000000..9e8e008 --- /dev/null +++ b/etc/cnid_dbd/cmd_dbd.c @@ -0,0 +1,309 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "cmd_dbd.h" + +enum dbd_cmd {dbd_scan, dbd_rebuild}; + +/* Global variables */ +volatile sig_atomic_t alarmed; /* flags for signals */ + +/* Local variables */ +static dbd_flags_t flags; + +/*************************************************************************** + * Local functions + ***************************************************************************/ + +/* + * SIGNAL handling: + * catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. + */ +static void sig_handler(int signo) +{ + alarmed = 1; + return; +} + +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_handler; + sv.sa_flags = SA_RESTART; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGTERM, &sv, NULL) < 0) { + dbd_log( LOGSTD, "error in sigaction(SIGTERM): %s", strerror(errno)); + exit(EXIT_FAILURE); + } + if (sigaction(SIGINT, &sv, NULL) < 0) { + dbd_log( LOGSTD, "error in sigaction(SIGINT): %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + memset(&sv, 0, sizeof(struct sigaction)); + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + + if (sigaction(SIGABRT, &sv, NULL) < 0) { + dbd_log( LOGSTD, "error in sigaction(SIGABRT): %s", strerror(errno)); + exit(EXIT_FAILURE); + } + if (sigaction(SIGHUP, &sv, NULL) < 0) { + dbd_log( LOGSTD, "error in sigaction(SIGHUP): %s", strerror(errno)); + exit(EXIT_FAILURE); + } + if (sigaction(SIGQUIT, &sv, NULL) < 0) { + dbd_log( LOGSTD, "error in sigaction(SIGQUIT): %s", strerror(errno)); + exit(EXIT_FAILURE); + } +} + +static void usage (void) +{ + printf("Usage: dbd [-cfFstuvV] \n\n" + "dbd scans all file and directories of AFP volumes, updating the\n" + "CNID database of the volume. dbd must be run with appropiate\n" + "permissions i.e. as root.\n\n" + "Options:\n" + " -s scan volume: treat the volume as read only and don't\n" + " perform any filesystem modifications\n" + " -c convert from adouble:v2 to adouble:ea\n" + " -F location of the afp.conf config file\n" + " -f delete and recreate CNID database\n" + " -t show statistics while running\n" + " -u username for use with AFP volumes using user variable $u\n" + " -v verbose\n" + " -V show version info\n\n" + ); +} + +/*************************************************************************** + * Global functions + ***************************************************************************/ + +void dbd_log(enum logtype lt, char *fmt, ...) +{ + int len; + static char logbuffer[1024]; + va_list args; + + if ( (lt == LOGSTD) || (flags & DBD_FLAGS_VERBOSE)) { + va_start(args, fmt); + len = vsnprintf(logbuffer, 1023, fmt, args); + va_end(args); + logbuffer[1023] = 0; + + printf("%s\n", logbuffer); + } +} + +int main(int argc, char **argv) +{ + EC_INIT; + int dbd_cmd = dbd_rebuild; + int cdir = -1; + AFPObj obj = { 0 }; + struct vol *vol = NULL; + const char *volpath = NULL; + char *username = NULL; + int c; + while ((c = getopt(argc, argv, ":cfF:rstu:vV")) != -1) { + switch(c) { + case 'c': + flags |= DBD_FLAGS_V2TOEA; + break; + case 'f': + flags |= DBD_FLAGS_FORCE; + break; + case 'F': + obj.cmdlineconfigfile = strdup(optarg); + break; + case 'r': + /* the default */ + break; + case 's': + dbd_cmd = dbd_scan; + flags |= DBD_FLAGS_SCAN; + break; + case 't': + flags |= DBD_FLAGS_STATS; + break; + case 'u': + username = strdup(optarg); + break; + case 'v': + flags |= DBD_FLAGS_VERBOSE; + break; + case 'V': + printf("dbd %s\n", VERSION); + exit(0); + case ':': + case '?': + usage(); + exit(EXIT_FAILURE); + break; + } + } + + if ( (optind + 1) != argc ) { + usage(); + exit(EXIT_FAILURE); + } + volpath = argv[optind]; + + if (geteuid() != 0) { + usage(); + exit(EXIT_FAILURE); + } + /* Inhereting perms in ad_mkdir etc requires this */ + ad_setfuid(0); + + setvbuf(stdout, (char *) NULL, _IONBF, 0); + + /* Remember cwd */ + if ((cdir = open(".", O_RDONLY)) < 0) { + dbd_log( LOGSTD, "Can't open dir: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Setup signal handling */ + set_signal(); + + /* Load config */ + if (afp_config_parse(&obj, "dbd") != 0) { + dbd_log( LOGSTD, "Couldn't load afp.conf"); + exit(EXIT_FAILURE); + } + + + /* Initialize CNID subsystem */ + cnid_init(); + + /* Setup logging. Should be portable among *NIXes */ + if (flags & DBD_FLAGS_VERBOSE) + setuplog("default:note, cnid:debug", "/dev/tty"); + else + setuplog("default:note", "/dev/tty"); + + /* Set username */ + if (username) { + strncpy(obj.username, username, MAXUSERLEN); + struct passwd *pwd; + pwd = getpwnam(obj.username); + if (!pwd) { + dbd_log( LOGSTD, "unknown user"); + exit(EXIT_FAILURE); + } + obj.uid = pwd->pw_uid; + } + + if (load_volumes(&obj, lv_all) != 0) { + dbd_log( LOGSTD, "Couldn't load volumes"); + exit(EXIT_FAILURE); + } + + if ((vol = getvolbypath(&obj, volpath)) == NULL) { + dbd_log( LOGSTD, "Couldn't find volume for '%s'", volpath); + exit(EXIT_FAILURE); + } + + if (load_charset(vol) != 0) { + dbd_log( LOGSTD, "Couldn't load charsets for '%s'", volpath); + exit(EXIT_FAILURE); + } + + /* open volume */ + if (STRCMP(vol->v_cnidscheme, != , "dbd") && STRCMP(vol->v_cnidscheme, != , "mysql")) { + dbd_log(LOGSTD, "\"%s\" isn't a \"dbd\" CNID volume", vol->v_path); + exit(EXIT_FAILURE); + } + vol->v_cdb = cnid_open(vol, vol->v_cnidscheme, + vol->v_flags & AFPVOL_NODEV ? CNID_FLAG_NODEV : 0); + if (vol->v_cdb == NULL) { + dbd_log(LOGSTD, "Cant initialize CNID database connection for %s", vol->v_path); + exit(EXIT_FAILURE); + } + + if (vol->v_adouble == AD_VERSION_EA) + dbd_log( LOGDEBUG, "adouble:ea volume"); + else if (vol->v_adouble == AD_VERSION2) + dbd_log( LOGDEBUG, "adouble:v2 volume"); + else { + dbd_log( LOGSTD, "unknown adouble volume"); + exit(EXIT_FAILURE); + } + + /* -C v2 to ea conversion only on adouble:ea volumes */ + if ((flags & DBD_FLAGS_V2TOEA) && (vol->v_adouble!= AD_VERSION_EA)) { + dbd_log( LOGSTD, "Can't run adouble:v2 to adouble:ea conversion because not an adouble:ea volume"); + exit(EXIT_FAILURE); + } + + /* Sanity checks to ensure we can touch this volume */ + if (vol->v_vfs_ea != AFPVOL_EA_AD && vol->v_vfs_ea != AFPVOL_EA_SYS) { + dbd_log( LOGSTD, "Unknown Extended Attributes option: %u", vol->v_vfs_ea); + exit(EXIT_FAILURE); + } + + if (flags & DBD_FLAGS_FORCE) { + if (cnid_wipe(vol->v_cdb) != 0) { + dbd_log( LOGSTD, "Failed to wipe CNID db"); + EC_FAIL; + } + } + + /* Now execute given command scan|rebuild|dump */ + switch (dbd_cmd) { + case dbd_scan: + case dbd_rebuild: + if (cmd_dbd_scanvol(vol, flags) < 0) { + dbd_log( LOGSTD, "Error repairing database."); + } + break; + } + +EC_CLEANUP: + if (vol) + cnid_close(vol->v_cdb); + + if (cdir != -1 && (fchdir(cdir) < 0)) + dbd_log(LOGSTD, "fchdir: %s", strerror(errno)); + + if (ret == 0) + exit(EXIT_SUCCESS); + else + exit(EXIT_FAILURE); +} diff --git a/etc/cnid_dbd/cmd_dbd.h b/etc/cnid_dbd/cmd_dbd.h new file mode 100644 index 0000000..9fcb3f4 --- /dev/null +++ b/etc/cnid_dbd/cmd_dbd.h @@ -0,0 +1,29 @@ +#ifndef CMD_DBD_H +#define CMD_DBD_H + +#include +#include + +#include +#include "dbif.h" + +enum logtype {LOGSTD, LOGDEBUG}; +typedef unsigned int dbd_flags_t; + +#define DBD_FLAGS_SCAN (1 << 0) +#define DBD_FLAGS_FORCE (1 << 1) +#define DBD_FLAGS_STATS (1 << 2) +#define DBD_FLAGS_V2TOEA (1 << 3) /* Convert adouble:v2 to adouble:ea */ +#define DBD_FLAGS_VERBOSE (1 << 4) + +#define ADv2_DIRNAME ".AppleDouble" + +#define DIR_DOT_OR_DOTDOT(a) \ + ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0)) + +extern volatile sig_atomic_t alarmed; + +extern void dbd_log(enum logtype lt, char *fmt, ...); +extern int cmd_dbd_scanvol(struct vol *vol, dbd_flags_t flags); + +#endif /* CMD_DBD_H */ diff --git a/etc/cnid_dbd/cmd_dbd_scanvol.c b/etc/cnid_dbd/cmd_dbd_scanvol.c new file mode 100644 index 0000000..15b9723 --- /dev/null +++ b/etc/cnid_dbd/cmd_dbd_scanvol.c @@ -0,0 +1,867 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmd_dbd.h" +#include "dbif.h" +#include "db_param.h" +#include "dbd.h" + +/* Some defines to ease code parsing */ +#define ADDIR_OK (addir_ok == 0) +#define ADFILE_OK (adfile_ok == 0) + + +static char cwdbuf[MAXPATHLEN+1]; +static struct vol *vol; +static dbd_flags_t dbd_flags; +static char stamp[CNID_DEV_LEN]; +static char *netatalk_dirs[] = { + ".AppleDB", + ".AppleDesktop", + NULL +}; +static char *special_dirs[] = { + ".zfs", + NULL +}; +static struct cnid_dbd_rqst rqst; +static struct cnid_dbd_rply rply; +static jmp_buf jmp; +static char pname[MAXPATHLEN] = "../"; + +/* + Taken form afpd/desktop.c +*/ +static char *utompath(char *upath) +{ + static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */ + char *m, *u; + uint16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX; + size_t outlen; + + if (!upath) + return NULL; + + m = mpath; + u = upath; + outlen = strlen(upath); + + if ((vol->v_casefold & AFPVOL_UTOMUPPER)) + flags |= CONV_TOUPPER; + else if ((vol->v_casefold & AFPVOL_UTOMLOWER)) + flags |= CONV_TOLOWER; + + if ((vol->v_flags & AFPVOL_EILSEQ)) { + flags |= CONV__EILSEQ; + } + + /* convert charsets */ + if ((size_t)-1 == ( outlen = convert_charset(vol->v_volcharset, + CH_UTF8_MAC, + vol->v_maccharset, + u, outlen, mpath, MAXPATHLEN, &flags)) ) { + dbd_log( LOGSTD, "Conversion from %s to %s for %s failed.", + vol->v_volcodepage, vol->v_maccodepage, u); + return NULL; + } + + return(m); +} + +/* + Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" + Returns pointer to name or NULL. +*/ +static const char *check_netatalk_dirs(const char *name) +{ + int c; + + for (c=0; netatalk_dirs[c]; c++) { + if ((strcmp(name, netatalk_dirs[c])) == 0) + return netatalk_dirs[c]; + } + return NULL; +} + +/* + Check for special names + Returns pointer to name or NULL. +*/ +static const char *check_special_dirs(const char *name) +{ + int c; + + for (c=0; special_dirs[c]; c++) { + if ((strcmp(name, special_dirs[c])) == 0) + return special_dirs[c]; + } + return NULL; +} + +/* + * We unCAPed a name, update CNID db + */ +static int update_cnid(cnid_t did, const struct stat *sp, const char *oldname, const char *newname) +{ + cnid_t id; + + /* Query the database */ + if ((id = cnid_lookup(vol->v_cdb, sp, did, (char *)oldname, strlen(oldname))) == CNID_INVALID) + /* not in db, no need to update */ + return 0; + + /* Update the database */ + if (cnid_update(vol->v_cdb, id, sp, did, (char *)newname, strlen(newname)) < 0) + return -1; + + return 0; +} + +/* + Check for .AppleDouble file, create if missing +*/ +static int check_adfile(const char *fname, const struct stat *st, const char **newname) +{ + int ret; + int adflags = ADFLAGS_HF; + struct adouble ad; + const char *adname; + + *newname = NULL; + + if (vol->v_adouble == AD_VERSION_EA) { + if (!(dbd_flags & DBD_FLAGS_V2TOEA)) + return 0; + if (ad_convert(fname, st, vol, newname) != 0) { + switch (errno) { + case ENOENT: + break; + default: + dbd_log(LOGSTD, "Conversion error for \"%s/%s\": %s", cwdbuf, fname, strerror(errno)); + break; + } + } + return 0; + } + + if (S_ISDIR(st->st_mode)) + adflags |= ADFLAGS_DIR; + + adname = vol->ad_path(fname, adflags); + + if ((ret = access( adname, F_OK)) != 0) { + if (errno != ENOENT) { + dbd_log(LOGSTD, "Access error for ad-file '%s/%s': %s", + cwdbuf, adname, strerror(errno)); + return -1; + } + /* Missing. Log and create it */ + dbd_log(LOGSTD, "Missing AppleDouble file '%s/%s'", cwdbuf, adname); + + if (dbd_flags & DBD_FLAGS_SCAN) + /* Scan only requested, dont change anything */ + return -1; + + /* Create ad file */ + ad_init(&ad, vol); + + if ((ret = ad_open(&ad, fname, adflags | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666)) != 0) { + dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s", + cwdbuf, adname, strerror(errno)); + + return -1; + } + + /* Set name in ad-file */ + ad_setname(&ad, utompath((char *)fname)); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + + chown(adname, st->st_uid, st->st_gid); + /* FIXME: should we inherit mode too here ? */ +#if 0 + chmod(adname, st->st_mode); +#endif + } else { + ad_init(&ad, vol); + if (ad_open(&ad, fname, adflags | ADFLAGS_RDONLY) != 0) { + dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s'", cwdbuf, fname); + return -1; + } + ad_close(&ad, ADFLAGS_HF); + } + return 0; +} + +/* + Remove all files with file::EA* from adouble dir +*/ +static void remove_eafiles(const char *name, struct ea *ea) +{ + DIR *dp = NULL; + struct dirent *ep; + char eaname[MAXPATHLEN]; + + strlcpy(eaname, name, sizeof(eaname)); + if (strlcat(eaname, "::EA", sizeof(eaname)) >= sizeof(eaname)) { + dbd_log(LOGSTD, "name too long: '%s/%s/%s'", cwdbuf, ADv2_DIRNAME, name); + return; + } + + if ((chdir(ADv2_DIRNAME)) != 0) { + dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s", + cwdbuf, ADv2_DIRNAME, strerror(errno)); + return; + } + + if ((dp = opendir(".")) == NULL) { + dbd_log(LOGSTD, "Couldn't open the directory '%s/%s': %s", + cwdbuf, ADv2_DIRNAME, strerror(errno)); + goto exit; + } + + while ((ep = readdir(dp))) { + if (strstr(ep->d_name, eaname) != NULL) { + dbd_log(LOGSTD, "Removing EA file: '%s/%s/%s'", + cwdbuf, ADv2_DIRNAME, ep->d_name); + if ((unlink(ep->d_name)) != 0) { + dbd_log(LOGSTD, "Error unlinking EA file '%s/%s/%s': %s", + cwdbuf, ADv2_DIRNAME, ep->d_name, strerror(errno)); + } + } /* if */ + } /* while */ + +exit: + if (dp) + closedir(dp); + if ((chdir("..")) != 0) { + dbd_log(LOGSTD, "Couldn't chdir to '%s': %s", cwdbuf, strerror(errno)); + /* we can't proceed */ + longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */ + } +} + +/* + Check Extended Attributes files +*/ +static int check_eafiles(const char *fname) +{ + unsigned int count = 0; + int ret = 0, remove; + struct ea ea; + struct stat st; + char *eaname; + + if ((ret = ea_open(vol, fname, EA_RDWR, &ea)) != 0) { + if (errno == ENOENT) + return 0; + dbd_log(LOGSTD, "Error calling ea_open for file: %s/%s, removing EA files", cwdbuf, fname); + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) + remove_eafiles(fname, &ea); + return -1; + } + + /* Check all EAs */ + while (count < ea.ea_count) { + dbd_log(LOGDEBUG, "EA: %s", (*ea.ea_entries)[count].ea_name); + remove = 0; + + eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 0); + + if (lstat(eaname, &st) != 0) { + if (errno == ENOENT) + dbd_log(LOGSTD, "Missing EA: %s/%s", cwdbuf, eaname); + else + dbd_log(LOGSTD, "Bogus EA: %s/%s", cwdbuf, eaname); + remove = 1; + } else if (st.st_size != (*ea.ea_entries)[count].ea_size) { + dbd_log(LOGSTD, "Bogus EA: %s/%s, removing it...", cwdbuf, eaname); + remove = 1; + if ((unlink(eaname)) != 0) + dbd_log(LOGSTD, "Error removing EA file '%s/%s': %s", + cwdbuf, eaname, strerror(errno)); + } + + if (remove) { + /* Be CAREFUL here! This should do what ea_delentry does. ea_close relies on it !*/ + free((*ea.ea_entries)[count].ea_name); + (*ea.ea_entries)[count].ea_name = NULL; + } + + count++; + } /* while */ + + ea_close(&ea); + return ret; +} + +/* + Check for .AppleDouble folder and .Parent, create if missing +*/ +static int check_addir(int volroot) +{ + int addir_ok, adpar_ok; + struct stat st; + struct adouble ad; + char *mname = NULL; + + if (vol->v_adouble == AD_VERSION_EA) + return 0; + + /* Check for ad-dir */ + if ( (addir_ok = access(ADv2_DIRNAME, F_OK)) != 0) { + if (errno != ENOENT) { + dbd_log(LOGSTD, "Access error in directory %s: %s", cwdbuf, strerror(errno)); + return -1; + } + dbd_log(LOGSTD, "Missing %s for '%s'", ADv2_DIRNAME, cwdbuf); + } + + /* Check for ".Parent" */ + if ( (adpar_ok = access(vol->ad_path(".", ADFLAGS_DIR), F_OK)) != 0) { + if (errno != ENOENT) { + dbd_log(LOGSTD, "Access error on '%s/%s': %s", + cwdbuf, vol->ad_path(".", ADFLAGS_DIR), strerror(errno)); + return -1; + } + dbd_log(LOGSTD, "Missing .AppleDouble/.Parent for '%s'", cwdbuf); + } + + /* Is one missing ? */ + if ((addir_ok != 0) || (adpar_ok != 0)) { + /* Yes, but are we only scanning ? */ + if (dbd_flags & DBD_FLAGS_SCAN) { + /* Yes: missing .Parent is not a problem, but missing ad-dir + causes later checking of ad-files to fail. So we have to return appropiately */ + if (addir_ok != 0) + return -1; + else /* (adpar_ok != 0) */ + return 0; + } + + /* Create ad dir and set name */ + ad_init(&ad, vol); + + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_CREATE | ADFLAGS_RDWR, 0777) != 0) { + dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno)); + return -1; + } + + /* Get basename of cwd from cwdbuf */ + mname = utompath(strrchr(cwdbuf, '/') + 1); + + /* Update name in ad file */ + ad_setname(&ad, mname); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + + /* Inherit owner/group from "." to ".AppleDouble" and ".Parent" */ + if ((lstat(".", &st)) != 0) { + dbd_log( LOGSTD, "Couldnt stat %s: %s", cwdbuf, strerror(errno)); + return -1; + } + chown(ADv2_DIRNAME, st.st_uid, st.st_gid); + chown(vol->ad_path(".", ADFLAGS_DIR), st.st_uid, st.st_gid); + } + + return 0; +} + +/* + Check if file cotains "::EA" and if it does check if its correspondig data fork exists. + Returns: + 0 = name is not an EA file + 1 = name is an EA file and no problem was found + -1 = name is an EA file and data fork is gone + */ +static int check_eafile_in_adouble(const char *name) +{ + int ret = 0; + char *namep, *namedup = NULL; + + /* Check if this is an AFPVOL_EA_AD vol */ + if (vol->v_vfs_ea == AFPVOL_EA_AD) { + /* Does the filename contain "::EA" ? */ + namedup = strdup(name); + if ((namep = strstr(namedup, "::EA")) == NULL) { + ret = 0; + goto ea_check_done; + } else { + /* File contains "::EA" so it's an EA file. Check for data file */ + + /* Get string before "::EA" from EA filename */ + namep[0] = 0; + strlcpy(pname + 3, namedup, sizeof(pname)); /* Prepends "../" */ + + if ((access( pname, F_OK)) == 0) { + ret = 1; + goto ea_check_done; + } else { + ret = -1; + if (errno != ENOENT) { + dbd_log(LOGSTD, "Access error for file '%s/%s': %s", + cwdbuf, name, strerror(errno)); + goto ea_check_done; + } + + /* Orphaned EA file*/ + dbd_log(LOGSTD, "Orphaned Extended Attribute file '%s/%s/%s'", + cwdbuf, ADv2_DIRNAME, name); + + if (dbd_flags & DBD_FLAGS_SCAN) + /* Scan only requested, dont change anything */ + goto ea_check_done; + + if ((unlink(name)) != 0) { + dbd_log(LOGSTD, "Error unlinking orphaned Extended Attribute file '%s/%s/%s'", + cwdbuf, ADv2_DIRNAME, name); + } + } /* if (access) */ + } /* if strstr */ + } /* if AFPVOL_EA_AD */ + +ea_check_done: + if (namedup) + free(namedup); + + return ret; +} + +/* + Check files and dirs inside .AppleDouble folder: + - remove orphaned files + - bail on dirs +*/ +static int read_addir(void) +{ + DIR *dp; + struct dirent *ep; + struct stat st; + + if ((chdir(ADv2_DIRNAME)) != 0) { + if (vol->v_adouble == AD_VERSION_EA) { + return 0; + } + dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s", + cwdbuf, ADv2_DIRNAME, strerror(errno)); + return -1; + } + + if ((dp = opendir(".")) == NULL) { + dbd_log(LOGSTD, "Couldn't open the directory '%s/%s': %s", + cwdbuf, ADv2_DIRNAME, strerror(errno)); + return -1; + } + + while ((ep = readdir(dp))) { + /* Check if its "." or ".." */ + if (DIR_DOT_OR_DOTDOT(ep->d_name)) + continue; + + /* Skip ".Parent" */ + if (STRCMP(ep->d_name, ==, ".Parent")) + continue; + + if ((lstat(ep->d_name, &st)) < 0) { + dbd_log( LOGSTD, "Lost file or dir while enumeratin dir '%s/%s/%s', probably removed: %s", + cwdbuf, ADv2_DIRNAME, ep->d_name, strerror(errno)); + continue; + } + + /* Check for dirs */ + if (S_ISDIR(st.st_mode)) { + dbd_log( LOGSTD, "Unexpected directory '%s' in AppleDouble dir '%s/%s'", + ep->d_name, cwdbuf, ADv2_DIRNAME); + continue; + } + + /* Check if for orphaned and corrupt Extended Attributes file */ + if (check_eafile_in_adouble(ep->d_name) != 0) + continue; + + /* Check for data file */ + strcpy(pname + 3, ep->d_name); + if ((access( pname, F_OK)) != 0) { + if (errno != ENOENT) { + dbd_log(LOGSTD, "Access error for file '%s/%s': %s", + cwdbuf, pname, strerror(errno)); + continue; + } + /* Orphaned ad-file*/ + dbd_log(LOGSTD, "Orphaned AppleDoube file '%s/%s/%s'", + cwdbuf, ADv2_DIRNAME, ep->d_name); + + if (dbd_flags & DBD_FLAGS_SCAN) + /* Scan only requested, dont change anything */ + continue;; + + if ((unlink(ep->d_name)) != 0) { + dbd_log(LOGSTD, "Error unlinking orphaned AppleDoube file '%s/%s/%s'", + cwdbuf, ADv2_DIRNAME, ep->d_name); + + } + } + } + + if ((chdir("..")) != 0) { + dbd_log(LOGSTD, "Couldn't chdir back to '%s' from AppleDouble dir: %s", + cwdbuf, strerror(errno)); + /* This really is EOT! */ + longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */ + } + + closedir(dp); + + return 0; +} + +/* + Check CNID for a file/dir, both from db and from ad-file. + For detailed specs see intro. + + @return Correct CNID of object or CNID_INVALID (ie 0) on error +*/ +static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok) +{ + int adflags = ADFLAGS_HF; + cnid_t db_cnid, ad_cnid; + struct adouble ad; + + adflags = ADFLAGS_HF | (S_ISDIR(st->st_mode) ? ADFLAGS_DIR : 0); + + /* Get CNID from ad-file */ + ad_cnid = CNID_INVALID; + if (ADFILE_OK) { + ad_init(&ad, vol); + if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) { + + if (vol->v_adouble != AD_VERSION_EA) { + dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); + return CNID_INVALID; + } + dbd_log( LOGDEBUG, "File without meta EA: \"%s/%s\"", cwdbuf, name); + adfile_ok = 1; + } else { + ad_cnid = ad_getid(&ad, st->st_dev, st->st_ino, 0, stamp); + if (ad_cnid == CNID_INVALID) + dbd_log( LOGSTD, "Bad CNID in adouble file of '%s/%s'", cwdbuf, name); + else + dbd_log( LOGDEBUG, "CNID from .AppleDouble file for '%s/%s': %u", cwdbuf, name, ntohl(ad_cnid)); + ad_close(&ad, ADFLAGS_HF); + } + } + + /* Get CNID from database */ + if ((db_cnid = cnid_add(vol->v_cdb, st, did, (char *)name, strlen(name), ad_cnid)) == CNID_INVALID) + return CNID_INVALID; + + /* Compare CNID from db and adouble file */ + if (ad_cnid != db_cnid && adfile_ok == 0) { + /* Mismatch, overwrite ad file with value from db */ + dbd_log(LOGSTD, "CNID mismatch for '%s/%s', CNID db: %u, ad-file: %u", + cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid)); + ad_init(&ad, vol); + if (ad_open(&ad, name, adflags | ADFLAGS_HF | ADFLAGS_RDWR) != 0) { + dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", + cwdbuf, name, strerror(errno)); + return CNID_INVALID; + } + ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_HF); + } + + return db_cnid; +} + +static int check_orphaned(const char *name) +{ + int rc; + struct stat sb; + + if (strlen(name) < 3) + return 0; + + rc = lstat(&name[2], &sb); + + if (rc != 0 && errno == ENOENT) { + dbd_log(LOGSTD, "Removing orphaned AppleDouble \"%s/%s\"", cwdbuf, name); + unlink(name); + return 1; + } + return 0; +} + +/* + This is called recursively for all dirs. + volroot=1 means we're in the volume root dir, 0 means we aren't. + We use this when checking for netatalk private folders like .AppleDB. + did is our parents CNID. +*/ +static int dbd_readdir(int volroot, cnid_t did) +{ + int cwd, ret = 0, adfile_ok, addir_ok; + cnid_t cnid = 0; + const char *name; + DIR *dp; + struct dirent *ep; + static struct stat st; /* Save some stack space */ + + /* Check again for .AppleDouble folder, check_adfile also checks/creates it */ + if ((addir_ok = check_addir(volroot)) != 0) + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) + /* Fatal on rebuild run, continue if only scanning ! */ + return -1; + + /* Check AppleDouble files in AppleDouble folder, but only if it exists or could be created */ + if (ADDIR_OK) + if ((read_addir()) != 0) + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) + /* Fatal on rebuild run, continue if only scanning ! */ + return -1; + + if ((dp = opendir (".")) == NULL) { + dbd_log(LOGSTD, "Couldn't open the directory: %s",strerror(errno)); + return -1; + } + + while ((ep = readdir (dp))) { + /* Check if we got a termination signal */ + if (alarmed) + longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */ + + /* Check if its "." or ".." */ + if (DIR_DOT_OR_DOTDOT(ep->d_name)) + continue; + + /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */ + if ((name = check_netatalk_dirs(ep->d_name)) != NULL) { + if (! volroot) + dbd_log(LOGSTD, "Nested %s in %s", name, cwdbuf); + continue; + } + + /* Check for special folders in volume root e.g. ".zfs" */ + if (volroot) { + if ((name = check_special_dirs(ep->d_name)) != NULL) { + dbd_log(LOGSTD, "Ignoring special dir \"%s\"", name); + continue; + } + } + + /* Skip .AppleDouble dir in this loop */ + if (STRCMP(ep->d_name, == , ADv2_DIRNAME)) + continue; + + if (!vol->vfs->vfs_validupath(vol, ep->d_name)) { + dbd_log(LOGDEBUG, "Ignoring \"%s\"", ep->d_name); + continue; + } + + if ((ret = lstat(ep->d_name, &st)) < 0) { + dbd_log( LOGSTD, "Lost file while reading dir '%s/%s', probably removed: %s", + cwdbuf, ep->d_name, strerror(errno)); + continue; + } + + switch (st.st_mode & S_IFMT) { + case S_IFREG: + case S_IFDIR: + case S_IFLNK: + break; + default: + dbd_log(LOGSTD, "Bad filetype: %s/%s", cwdbuf, ep->d_name); + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) { + if ((unlink(ep->d_name)) != 0) { + dbd_log(LOGSTD, "Error removing: %s/%s: %s", cwdbuf, ep->d_name, strerror(errno)); + } + } + continue; + } + + /************************************************************************** + Statistics + **************************************************************************/ + static unsigned long long statcount = 0; + static time_t t = 0; + + if (t == 0) + t = time(NULL); + + statcount++; + if ((statcount % 10000) == 0) { + if (dbd_flags & DBD_FLAGS_STATS) + dbd_log(LOGSTD, "Scanned: %10llu, time: %10llu s", + statcount, (unsigned long long)(time(NULL) - t)); + } + + /************************************************************************** + Tests + **************************************************************************/ + + /* Check for invalid names and orphaned ._ files */ + if (S_ISREG(st.st_mode) && (strncmp(ep->d_name, "._", strlen("._")) == 0)) { + if (check_orphaned(ep->d_name)) + continue; + if (vol->vfs->vfs_validupath(vol, ep->d_name)) { + dbd_log(LOGSTD, "Bad AppleDouble \"%s/%s\"", cwdbuf, ep->d_name); + continue; + } + } + + /* Check for appledouble file, create if missing, but only if we have addir */ + const char *name = NULL; + adfile_ok = -1; + if (ADDIR_OK) + adfile_ok = check_adfile(ep->d_name, &st, &name); + + if (!S_ISLNK(st.st_mode)) { + if (name == NULL) { + name = ep->d_name; + } else { + update_cnid(did, &st, ep->d_name, name); + } + + /* Check CNIDs */ + cnid = check_cnid(name, did, &st, adfile_ok); + + /* Check EA files */ + if (vol->v_vfs_ea == AFPVOL_EA_AD) + check_eafiles(name); + } + + /************************************************************************** + Recursion + **************************************************************************/ + if (S_ISDIR(st.st_mode) && cnid) { /* If we have no cnid for it we cant enter recursion */ + strcat(cwdbuf, "/"); + strcat(cwdbuf, name); + dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf); + if (-1 == (cwd = open(".", O_RDONLY))) { + dbd_log( LOGSTD, "Cant open directory '%s': %s", cwdbuf, strerror(errno)); + continue; + } + if (0 != chdir(name)) { + dbd_log( LOGSTD, "Cant chdir to directory '%s': %s", cwdbuf, strerror(errno)); + close(cwd); + continue; + } + + ret = dbd_readdir(0, cnid); + + fchdir(cwd); + close(cwd); + *(strrchr(cwdbuf, '/')) = 0; + if (ret < 0) + return -1; + } + } + + /* + Use results of previous checks + */ + if ((vol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) { + if (rmdir(ADv2_DIRNAME) != 0) { + switch (errno) { + case ENOENT: + break; + default: + dbd_log(LOGSTD, "Error removing adouble dir \"%s/%s\": %s", cwdbuf, ADv2_DIRNAME, strerror(errno)); + break; + } + } + } + closedir(dp); + return ret; +} + +/* + Main func called from cmd_dbd.c +*/ +int cmd_dbd_scanvol(struct vol *vol_in, dbd_flags_t flags) +{ + EC_INIT; + struct stat st; + + /* Run with umask 0 */ + umask(0); + + /* Make vol accessible for all funcs */ + vol = vol_in; + dbd_flags = flags; + + /* We only support unicode volumes ! */ + if (vol->v_volcharset != CH_UTF8) { + dbd_log(LOGSTD, "Not a Unicode volume: %s, %u != %u", vol->v_volcodepage, vol->v_volcharset, CH_UTF8); + EC_FAIL; + } + + /* + * Get CNID database stamp, cnid_getstamp() passes the buffer, + * then cnid_resolve() actually gets the value from the db + */ + cnid_getstamp(vol->v_cdb, stamp, sizeof(stamp)); + + if (setjmp(jmp) != 0) { + EC_EXIT_STATUS(0); /* Got signal, jump from dbd_readdir */ + } + + strcpy(cwdbuf, vol->v_path); + chdir(vol->v_path); + + if ((vol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) { + if (lstat(".", &st) != 0) + EC_FAIL; + if (ad_convert(".", &st, vol, NULL) != 0) { + switch (errno) { + case ENOENT: + break; + default: + dbd_log(LOGSTD, "Conversion error for \"%s\": %s", vol->v_path, strerror(errno)); + break; + } + } + } + + /* Start recursion */ + EC_NEG1( dbd_readdir(1, htonl(2)) ); /* 2 = volumeroot CNID */ + +EC_CLEANUP: + EC_EXIT; +} diff --git a/etc/cnid_dbd/cnid_metad.c b/etc/cnid_dbd/cnid_metad.c new file mode 100644 index 0000000..b05d72d --- /dev/null +++ b/etc/cnid_dbd/cnid_metad.c @@ -0,0 +1,650 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2009, 2010 + * + * All Rights Reserved. See COPYING. + */ + +/* + cnid_dbd metadaemon to start up cnid_dbd upon request from afpd. + Here is how it works: + + via TCP socket + 1. afpd -------> cnid_metad + + via UNIX domain socket + 2. cnid_metad -------> cnid_dbd + + passes afpd client fd + 3. cnid_metad -------> cnid_dbd + + Result: + via TCP socket + 4. afpd -------> cnid_dbd + + cnid_metad and cnid_dbd have been converted to non-blocking IO in 2010. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#undef __USE_GNU + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #define _XPG4_2 1 +#include +#include +#include + +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif /* ! WEXITSTATUS */ +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif /* ! WIFEXITED */ +#ifndef WIFSTOPPED +#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) +#endif + +#ifndef WIFSIGNALED +#define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status)) +#endif +#ifndef WTERMSIG +#define WTERMSIG(status) ((status) & 0x7f) +#endif + +/* functions for username and group */ +#include +#include + +/* FIXME */ +#ifdef linux +#ifndef USE_SETRESUID +#define USE_SETRESUID 1 +#define SWITCH_TO_GID(gid) ((setresgid(gid,gid,gid) < 0 || setgid(gid) < 0) ? -1 : 0) +#define SWITCH_TO_UID(uid) ((setresuid(uid,uid,uid) < 0 || setuid(uid) < 0) ? -1 : 0) +#endif /* USE_SETRESUID */ +#else /* ! linux */ +#ifndef USE_SETEUID +#define USE_SETEUID 1 +#define SWITCH_TO_GID(gid) ((setegid(gid) < 0 || setgid(gid) < 0) ? -1 : 0) +#define SWITCH_TO_UID(uid) ((setuid(uid) < 0 || seteuid(uid) < 0 || setuid(uid) < 0) ? -1 : 0) +#endif /* USE_SETEUID */ +#endif /* linux */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usockfd.h" + +#define DBHOME ".AppleDB" +#define DBHOMELEN 8 + +static int srvfd; +static int rqstfd; +static volatile sig_atomic_t sigchild = 0; +static uint maxvol; + +#define MAXSPAWN 3 /* Max times respawned in.. */ +#define TESTTIME 10 /* this much seconds apfd client tries to * + * to reconnect every 5 secondes, catch it */ +#define MAXVOLS 4096 +#define DEFAULTHOST "localhost" +#define DEFAULTPORT "4700" + +struct server { + char *v_path; + pid_t pid; + time_t tm; /* When respawned last */ + unsigned int count; /* Times respawned in the last TESTTIME secondes */ + int control_fd; /* file descriptor to child cnid_dbd process */ +}; + +static struct server srv[MAXVOLS]; + +static void daemon_exit(int i) +{ + exit(i); +} + +/* ------------------ */ +static void sig_handler(int sig) +{ + switch( sig ) { + case SIGTERM: + case SIGQUIT: + LOG(log_note, logtype_afpd, "shutting down on %s", + sig == SIGTERM ? "SIGTERM" : "SIGQUIT"); + break; + default : + LOG(log_error, logtype_afpd, "unexpected signal: %d", sig); + } + daemon_exit(0); +} + +static struct server *test_usockfn(const char *path) +{ + int i; + + for (i = 0; i < maxvol; i++) { + if (srv[i].v_path && STRCMP(path, ==, srv[i].v_path)) + return &srv[i]; + } + + return NULL; +} + +/** + * Pass connection request to existing cnid_dbd process or start a new one + * + * @param[in] obj handle + * @param[in] dbdpn Path to cnid_dbd binary + * @param[in] volpath Path of AFP volume + * @param[in] username Optional username, may be NULL + * + * @return 0 on success, -1 on error + **/ + int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath, const char *username) +{ + pid_t pid; + struct server *up; + int sv[2]; + int i; + time_t t; + char buf1[8]; + char buf2[8]; + + LOG(log_debug, logtype_cnid, "maybe_start_dbd(\"%s\"): BEGIN", volpath); + + up = test_usockfn(volpath); + if (up && up->pid) { + /* we already have a process, send our fd */ + LOG(log_debug, logtype_cnid, "maybe_start_dbd: cnid_dbd[%d] already serving", up->pid); + if (send_fd(up->control_fd, rqstfd) < 0) { + /* FIXME */ + return -1; + } + return 0; + } + + LOG(log_debug, logtype_cnid, "maybe_start_dbd: no cnid_dbd serving yet"); + + time(&t); + if (!up) { + /* find an empty slot (i < maxvol) or the first free slot (i == maxvol)*/ + for (i = 0; i <= maxvol && i < MAXVOLS; i++) { + if (srv[i].v_path == NULL) { + up = &srv[i]; + if ((up->v_path = strdup(volpath)) == NULL) + return -1; + up->tm = t; + up->count = 0; + if (i == maxvol) + maxvol++; + break; + } + } + if (!up) { + LOG(log_error, logtype_cnid, "no free slot for cnid_dbd child. Configured maximum: %d. Do you have so many volumes?", MAXVOLS); + return -1; + } + } else { + /* we have a slot but no process */ + if (up->count > 0) { + /* check for respawn too fast */ + if (t < (up->tm + TESTTIME)) { + /* We're in the respawn time window */ + if (up->count > MAXSPAWN) { + /* ...and already tried to fork too often */ + LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawning too fast"); + return -1; /* just exit, dont sleep, because we might have work to do for another client */ + } + } else { + /* out of respawn too fast windows reset the count */ + LOG(log_info, logtype_cnid, "maybe_start_dbd: respawn window ended"); + up->count = 0; + } + } + up->count++; + up->tm = t; + LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: respawn count: %u", up->count); + if (up->count > MAXSPAWN) { + /* We spawned too fast. From now until the first time we tried + TESTTIME seconds + we will just return -1 above */ + LOG(log_info, logtype_cnid, "maybe_start_dbd: reached MAXSPAWN threshhold"); + } + } + + /* + Create socketpair for comm between parent and child. + We use it to pass fds from connecting afpd processes to our + cnid_dbd child via fd passing. + */ + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) { + LOG(log_error, logtype_cnid, "error in socketpair: %s", strerror(errno)); + return -1; + } + + if ((pid = fork()) < 0) { + LOG(log_error, logtype_cnid, "error in fork: %s", strerror(errno)); + return -1; + } + if (pid == 0) { + int ret; + /* + * Child. Close descriptors and start the daemon. If it fails + * just log it. The client process will fail connecting + * afterwards anyway. + */ + + close(srvfd); + close(sv[0]); + + for (i = 0; i < MAXVOLS; i++) { + if (srv[i].pid && up != &srv[i]) { + close(srv[i].control_fd); + } + } + + sprintf(buf1, "%i", sv[1]); + sprintf(buf2, "%i", rqstfd); + + if (up->count == MAXSPAWN) { + /* there's a pb with the db inform child, it will delete the db */ + LOG(log_warning, logtype_cnid, + "Multiple attempts to start CNID db daemon for \"%s\" failed, wiping the slate clean...", + up->v_path); + ret = execlp(dbdpn, dbdpn, + "-F", obj->options.configfile, + "-p", volpath, + "-t", buf1, + "-l", buf2, + "-u", username, + NULL); + } else { + ret = execlp(dbdpn, dbdpn, + "-F", obj->options.configfile, + "-p", volpath, + "-t", buf1, + "-l", buf2, + "-u", username, + NULL); + } + /* Yikes! We're still here, so exec failed... */ + LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno)); + daemon_exit(0); + } + /* + * Parent. + */ + up->pid = pid; + close(sv[1]); + up->control_fd = sv[0]; + return 0; +} + +/* ------------------ */ +static int set_dbdir(const char *dbdir, const char *vpath) +{ + EC_INIT; + struct stat st; + bstring oldpath, newpath; + char *cmd_argv[4]; + + LOG(log_debug, logtype_cnid, "set_dbdir: volume: %s, db path: %s", vpath, dbdir); + + EC_NULL_LOG( oldpath = bformat("%s/%s/", vpath, DBHOME) ); + EC_NULL_LOG( newpath = bformat("%s/%s/", dbdir, DBHOME) ); + + if (lstat(dbdir, &st) < 0 && mkdir(dbdir, 0755) < 0) { + LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", dbdir); + EC_FAIL; + } + + if (lstat(cfrombstr(oldpath), &st) == 0 && lstat(cfrombstr(newpath), &st) != 0 && errno == ENOENT) { + /* There's an .AppleDB in the volume root, we move it */ + cmd_argv[0] = "mv"; + cmd_argv[1] = bdata(oldpath); + cmd_argv[2] = (char *)dbdir; + cmd_argv[3] = NULL; + if (run_cmd("mv", cmd_argv) != 0) { + LOG(log_error, logtype_cnid, "set_dbdir: moving CNID db from \"%s\" to \"%s\" failed", + bdata(oldpath), dbdir); + EC_FAIL; + } + + } + + if (lstat(cfrombstr(newpath), &st) < 0 && mkdir(cfrombstr(newpath), 0755 ) < 0) { + LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", bdata(newpath)); + EC_FAIL; + } + +EC_CLEANUP: + bdestroy(oldpath); + bdestroy(newpath); + EC_EXIT; +} + +/* ------------------ */ +static void catch_child(int sig _U_) +{ + sigchild = 1; +} + +/* ----------------------- */ +static void set_signal(void) +{ + struct sigaction sv; + sigset_t set; + + memset(&sv, 0, sizeof(sv)); + + /* Catch SIGCHLD */ + sv.sa_handler = catch_child; + sv.sa_flags = SA_NOCLDSTOP; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGCHLD, &sv, NULL) < 0) { + LOG(log_error, logtype_cnid, "cnid_metad: sigaction: %s", strerror(errno)); + daemon_exit(EXITERR_SYS); + } + + /* Catch SIGTERM and SIGQUIT */ + sv.sa_handler = sig_handler; + sigfillset(&sv.sa_mask ); + if (sigaction(SIGTERM, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } + if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } + + /* Ignore the rest */ + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask ); + if (sigaction(SIGALRM, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask ); + if (sigaction(SIGHUP, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask ); + if (sigaction(SIGUSR1, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask ); + if (sigaction(SIGUSR2, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask ); + if (sigaction(SIGPIPE, &sv, NULL ) < 0 ) { + LOG(log_error, logtype_afpd, "sigaction: %s", strerror(errno) ); + daemon_exit(EXITERR_SYS); + } + + /* block everywhere but in pselect */ + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_SETMASK, &set, NULL); +} + +static int setlimits(void) +{ + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { + LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno)); + exit(1); + } + if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < 65535) { + rlim.rlim_cur = 65535; + if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < 65535) + rlim.rlim_max = 65535; + if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { + LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno)); + exit(1); + } + } + return 0; +} + +static uid_t uid_from_name(const char *name) +{ + struct passwd *pwd; + + pwd = getpwnam(name); + if (pwd == NULL) + return 0; + return pwd->pw_uid; +} + +/* ------------------ */ +int main(int argc, char *argv[]) +{ + char *volname = NULL; + char *volpath = NULL; + char *username = NULL; + int len[DBD_NUM_OPEN_ARGS], actual_len; + pid_t pid; + int status; + char *dbdpn = _PATH_CNID_DBD; + char *host; + char *port; + int i; + int cc; + uid_t uid = 0; + gid_t gid = 0; + int debug = 0; + int ret; + sigset_t set; + AFPObj obj = { 0 }; + struct vol *vol; + + while (( cc = getopt( argc, argv, "dF:vV")) != -1 ) { + switch (cc) { + case 'd': + debug = 1; + break; + case 'F': + obj.cmdlineconfigfile = strdup(optarg); + break; + case 'v': + case 'V': + printf("cnid_metad (Netatalk %s)\n", VERSION); + return -1; + default: + printf("cnid_metad [-dvV] [-F alternate configfile ]\n"); + return -1; + } + } + + if (!debug && daemonize(0, 0) != 0) + exit(EXITERR_SYS); + + if (afp_config_parse(&obj, "cnid_metad") != 0) + daemon_exit(1); + + (void)setlimits(); + + host = atalk_iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700"); + if ((port = strrchr(host, ':'))) + *port++ = 0; + else + port = DEFAULTPORT; + if ((srvfd = tsockfd_create(host, port, 10)) < 0) + daemon_exit(1); + + LOG(log_note, logtype_afpd, "CNID Server listening on %s:%s", host, port); + + /* switch uid/gid */ + if (uid || gid) { + LOG(log_debug, logtype_cnid, "Setting uid/gid to %i/%i", uid, gid); + if (gid) { + if (SWITCH_TO_GID(gid) < 0) { + LOG(log_info, logtype_cnid, "unable to switch to group %d", gid); + daemon_exit(1); + } + } + if (uid) { + if (SWITCH_TO_UID(uid) < 0) { + LOG(log_info, logtype_cnid, "unable to switch to user %d", uid); + daemon_exit(1); + } + } + } + + set_signal(); + + sigemptyset(&set); + sigprocmask(SIG_SETMASK, NULL, &set); + sigdelset(&set, SIGCHLD); + + while (1) { + rqstfd = usockfd_check(srvfd, &set); + /* Collect zombie processes and log what happened to them */ + if (sigchild) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + for (i = 0; i < maxvol; i++) { + if (srv[i].pid == pid) { + srv[i].pid = 0; + close(srv[i].control_fd); + break; + } + } + if (WIFEXITED(status)) { + LOG(log_info, logtype_cnid, "cnid_dbd[%i] exited with exit code %i", + pid, WEXITSTATUS(status)); + } else { + /* cnid_dbd did a clean exit probably on idle timeout, reset bookkeeping */ + srv[i].tm = 0; + srv[i].count = 0; + } + if (WIFSIGNALED(status)) { + LOG(log_info, logtype_cnid, "cnid_dbd[%i] got signal %i", + pid, WTERMSIG(status)); + } + sigchild = 0; + } + if (rqstfd <= 0) + continue; + + ret = readt(rqstfd, &len[0], sizeof(int) * DBD_NUM_OPEN_ARGS, 1, 4); + + if (!ret) { + /* already close */ + goto loop_end; + } + else if (ret < 0) { + LOG(log_severe, logtype_cnid, "error read: %s", strerror(errno)); + goto loop_end; + } + else if (ret != DBD_NUM_OPEN_ARGS * sizeof(int)) { + LOG(log_error, logtype_cnid, "short read: got %d", ret); + goto loop_end; + } + + /* + * checks for buffer overruns. The client libatalk side does it too + * before handing the dir path over but who trusts clients? + */ + if (!len[0] || !len[1]) { + LOG(log_error, logtype_cnid, "wrong len parameter: len[0]: %d, len[1]: %d", len[0], len[1]); + goto loop_end; + } + + volname = malloc(len[0]); + volpath = malloc(len[1]); + if (len[2]) { + username = malloc(len[2]); + } + if (!volname || !volpath || (len[2] && !username)) { + LOG(log_severe, logtype_cnid, "malloc: %s", strerror(errno)); + goto loop_end; + } + + actual_len = readt(rqstfd, volname, len[0], 1, 5); + if (actual_len != len[0]) { + LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno)); + goto loop_end; + } + + actual_len = readt(rqstfd, volpath, len[1], 1, 5); + if (actual_len != len[1]) { + LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno)); + goto loop_end; + } + + if (len[2]) { + actual_len = readt(rqstfd, username, len[2], 1, 5); + if (actual_len != len[2]) { + LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno)); + goto loop_end; + } + strlcpy(obj.username, username, MAXUSERLEN); + obj.uid = uid_from_name(username); + if (!obj.uid) + goto loop_end; + } else { + obj.username[0] = 0; + } + + LOG(log_debug, logtype_cnid, "user: %s, volume %s, path %s", + username ? username : "-", volname, volpath); + + if (load_volumes(&obj, lv_all) != 0) { + LOG(log_severe, logtype_cnid, "main: error reloading config"); + goto loop_end; + } + + if ((vol = getvolbypath(&obj, volpath)) == NULL) { + LOG(log_severe, logtype_cnid, "main: no volume for path \"%s\"", volpath); + goto loop_end; + } + + LOG(log_maxdebug, logtype_cnid, "main: dbpath: %s", vol->v_dbpath); + + if (set_dbdir(vol->v_dbpath, vol->v_path) < 0) { + goto loop_end; + } + + maybe_start_dbd(&obj, dbdpn, vol->v_path, username); + + loop_end: + close(rqstfd); + unload_volumes(&obj); + SAFE_FREE(volname); + SAFE_FREE(volpath); + SAFE_FREE(username); + } +} diff --git a/etc/cnid_dbd/comm.c b/etc/cnid_dbd/comm.c new file mode 100644 index 0000000..28fab0e --- /dev/null +++ b/etc/cnid_dbd/comm.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 + * + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "db_param.h" +#include "usockfd.h" +#include "comm.h" + +/* Length of the space taken up by a padded control message of length len */ +#ifndef CMSG_SPACE +#define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len)) +#endif + + +struct connection { + time_t tm; /* When respawned last */ + int fd; +}; + +static int control_fd; +static int cur_fd; +static struct connection *fd_table; +static int fd_table_size; +static int fds_in_use = 0; + + +static void invalidate_fd(int fd) +{ + int i; + + if (fd == control_fd) + return; + for (i = 0; i != fds_in_use; i++) + if (fd_table[i].fd == fd) + break; + + assert(i < fds_in_use); + + fds_in_use--; + fd_table[i] = fd_table[fds_in_use]; + fd_table[fds_in_use].fd = -1; + close(fd); + return; +} + + +/* + * Check for client requests. We keep up to fd_table_size open descriptors in + * fd_table. If the table is full and we get a new descriptor via + * control_fd, we close a random decriptor in the table to make space. The + * affected client will automatically reconnect. For an EOF (descriptor is + * closed by the client, so a read here returns 0) comm_rcv will take care of + * things and clean up fd_table. The same happens for any read/write errors. + */ + +static int check_fd(time_t timeout, const sigset_t *sigmask, time_t *now) +{ + int fd; + fd_set readfds; + struct timespec tv; + int ret; + int i; + int maxfd = control_fd; + time_t t; + + FD_ZERO(&readfds); + FD_SET(control_fd, &readfds); + + for (i = 0; i != fds_in_use; i++) { + FD_SET(fd_table[i].fd, &readfds); + if (maxfd < fd_table[i].fd) + maxfd = fd_table[i].fd; + } + + tv.tv_nsec = 0; + tv.tv_sec = timeout; + if ((ret = pselect(maxfd + 1, &readfds, NULL, NULL, &tv, sigmask)) < 0) { + if (errno == EINTR) + return 0; + LOG(log_error, logtype_cnid, "error in select: %s",strerror(errno)); + return -1; + } + + time(&t); + if (now) + *now = t; + + if (!ret) + return 0; + + + if (FD_ISSET(control_fd, &readfds)) { + int l = 0; + + fd = recv_fd(control_fd, 0); + if (fd < 0) { + return -1; + } + if (fds_in_use < fd_table_size) { + fd_table[fds_in_use].fd = fd; + fd_table[fds_in_use].tm = t; + fds_in_use++; + } else { + time_t older = t; + + for (i = 0; i != fds_in_use; i++) { + if (older <= fd_table[i].tm) { + older = fd_table[i].tm; + l = i; + } + } + close(fd_table[l].fd); + fd_table[l].fd = fd; + fd_table[l].tm = t; + } + return 0; + } + + for (i = 0; i != fds_in_use; i++) { + if (FD_ISSET(fd_table[i].fd, &readfds)) { + fd_table[i].tm = t; + return fd_table[i].fd; + } + } + /* We should never get here */ + return 0; +} + +int comm_init(struct db_param *dbp, int ctrlfd, int clntfd) +{ + int i; + + fds_in_use = 0; + fd_table_size = dbp->fd_table_size; + + if ((fd_table = malloc(fd_table_size * sizeof(struct connection))) == NULL) { + LOG(log_error, logtype_cnid, "Out of memory"); + return -1; + } + for (i = 0; i != fd_table_size; i++) + fd_table[i].fd = -1; + /* from dup2 */ + control_fd = ctrlfd; +#if 0 + int b = 1; + /* this one dump core in recvmsg, great */ + if ( setsockopt(control_fd, SOL_SOCKET, SO_PASSCRED, &b, sizeof (b)) < 0) { + LOG(log_error, logtype_cnid, "setsockopt SO_PASSCRED %s", strerror(errno)); + return -1; + } +#endif + /* push the first client fd */ + fd_table[fds_in_use].fd = clntfd; + fds_in_use++; + + return 0; +} + +/* ------------ + nbe of clients +*/ +int comm_nbe(void) +{ + return fds_in_use; +} + +/* ------------ */ +int comm_rcv(struct cnid_dbd_rqst *rqst, time_t timeout, const sigset_t *sigmask, time_t *now) +{ + char *nametmp; + int b; + + if ((cur_fd = check_fd(timeout, sigmask, now)) < 0) + return -1; + + if (!cur_fd) + return 0; + + LOG(log_maxdebug, logtype_cnid, "comm_rcv: got data on fd %u", cur_fd); + + if (setnonblock(cur_fd, 1) != 0) { + LOG(log_error, logtype_cnid, "comm_rcv: setnonblock: %s", strerror(errno)); + return -1; + } + + nametmp = (char *)rqst->name; + if ((b = readt(cur_fd, rqst, sizeof(struct cnid_dbd_rqst), 1, CNID_DBD_TIMEOUT)) + != sizeof(struct cnid_dbd_rqst)) { + if (b) + LOG(log_error, logtype_cnid, "error reading message header: %s", strerror(errno)); + invalidate_fd(cur_fd); + rqst->name = nametmp; + return 0; + } + rqst->name = nametmp; + if (rqst->namelen && readt(cur_fd, (char *)rqst->name, rqst->namelen, 1, CNID_DBD_TIMEOUT) + != rqst->namelen) { + LOG(log_error, logtype_cnid, "error reading message name: %s", strerror(errno)); + invalidate_fd(cur_fd); + return 0; + } + /* We set this to make life easier for logging. None of the other stuff + needs zero terminated strings. */ + ((char *)(rqst->name))[rqst->namelen] = '\0'; + + LOG(log_maxdebug, logtype_cnid, "comm_rcv: got %u bytes", b + rqst->namelen); + + return 1; +} + +/* ------------ */ +#define USE_WRITEV +int comm_snd(struct cnid_dbd_rply *rply) +{ +#ifdef USE_WRITEV + struct iovec iov[2]; + size_t towrite; +#endif + + if (!rply->namelen) { + if (write(cur_fd, rply, sizeof(struct cnid_dbd_rply)) != sizeof(struct cnid_dbd_rply)) { + LOG(log_error, logtype_cnid, "error writing message header: %s", strerror(errno)); + invalidate_fd(cur_fd); + return 0; + } + return 1; + } +#ifdef USE_WRITEV + + iov[0].iov_base = rply; + iov[0].iov_len = sizeof(struct cnid_dbd_rply); + iov[1].iov_base = rply->name; + iov[1].iov_len = rply->namelen; + towrite = sizeof(struct cnid_dbd_rply) +rply->namelen; + + if (writev(cur_fd, iov, 2) != towrite) { + LOG(log_error, logtype_cnid, "error writing message : %s", strerror(errno)); + invalidate_fd(cur_fd); + return 0; + } +#else + if (write(cur_fd, rply, sizeof(struct cnid_dbd_rply)) != sizeof(struct cnid_dbd_rply)) { + LOG(log_error, logtype_cnid, "error writing message header: %s", strerror(errno)); + invalidate_fd(cur_fd); + return 0; + } + if (write(cur_fd, rply->name, rply->namelen) != rply->namelen) { + LOG(log_error, logtype_cnid, "error writing message name: %s", strerror(errno)); + invalidate_fd(cur_fd); + return 0; + } +#endif + return 1; +} + + diff --git a/etc/cnid_dbd/comm.h b/etc/cnid_dbd/comm.h new file mode 100644 index 0000000..2261777 --- /dev/null +++ b/etc/cnid_dbd/comm.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifndef CNID_DBD_COMM_H +#define CNID_DBD_COMM_H 1 + +/* number of seconds to try reading in readt */ +#define CNID_DBD_TIMEOUT 1 + +#include + + +extern int comm_init (struct db_param *, int, int); +extern int comm_rcv (struct cnid_dbd_rqst *, time_t, const sigset_t *, time_t *); +extern int comm_snd (struct cnid_dbd_rply *); +extern int comm_nbe (void); + +#endif /* CNID_DBD_COMM_H */ + diff --git a/etc/cnid_dbd/db_param.c b/etc/cnid_dbd/db_param.c new file mode 100644 index 0000000..3c8c102 --- /dev/null +++ b/etc/cnid_dbd/db_param.c @@ -0,0 +1,198 @@ +/* + * + * Copyright (C) Joerg Lenneis 2003 + * Copyright (c) Frank Lahm 2009 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "db_param.h" + +#define DB_PARAM_FN "db_param" +#define MAXKEYLEN 64 + +static struct db_param params; +static int parse_err; + +static size_t usock_maxlen(void) +{ + struct sockaddr_un addr; + return sizeof(addr.sun_path) - 1; +} + +static int make_pathname(char *path, char *dir, char *fn, size_t maxlen) +{ + size_t len; + + if (fn[0] != '/') { + len = strlen(dir); + if (len + 1 + strlen(fn) > maxlen) + return -1; + strcpy(path, dir); + if (path[len - 1] != '/') + strcat(path, "/"); + strcat(path, fn); + } else { + if (strlen(fn) > maxlen) + return -1; + strcpy(path, fn); + } + return 0; +} + +static void default_params(struct db_param *dbp, char *dir) +{ + dbp->logfile_autoremove = DEFAULT_LOGFILE_AUTOREMOVE; + dbp->cachesize = DEFAULT_CACHESIZE; + dbp->maxlocks = DEFAULT_MAXLOCKS; + dbp->maxlockobjs = DEFAULT_MAXLOCKOBJS; + dbp->flush_frequency = DEFAULT_FLUSH_FREQUENCY; + dbp->flush_interval = DEFAULT_FLUSH_INTERVAL; + if (make_pathname(dbp->usock_file, dir, DEFAULT_USOCK_FILE, usock_maxlen()) < 0) { + /* Not an error yet, it might be set in the config file */ + dbp->usock_file[0] = '\0'; + } + dbp->fd_table_size = DEFAULT_FD_TABLE_SIZE; + if ( dbp->fd_table_size > FD_SETSIZE -1) + dbp->fd_table_size = FD_SETSIZE -1; + dbp->idle_timeout = DEFAULT_IDLE_TIMEOUT; + + return; +} + +static int parse_int(char *val) +{ + char *tmp; + int result = 0; + + result = strtol(val, &tmp, 10); + if (tmp[0] != '\0') { + LOG(log_error, logtype_cnid, "invalid characters in token %s", val); + parse_err++; + } + return result; +} + + +/* TODO: This configuration file reading routine is neither very robust (%s + buffer overflow) nor elegant, we need to add support for whitespace in + filenames as well. */ + +struct db_param *db_param_read(char *dir) +{ + FILE *fp; + static char key[MAXKEYLEN + 1]; + static char val[MAXPATHLEN + 1]; + static char pfn[MAXPATHLEN + 1]; + int items; + + default_params(¶ms, dir); + params.dir = dir; + + if (make_pathname(pfn, dir, DB_PARAM_FN, MAXPATHLEN) < 0) { + LOG(log_error, logtype_cnid, "Parameter filename too long"); + return NULL; + } + + if ((fp = fopen(pfn, "r")) == NULL) { + if (errno == ENOENT) { + if (strlen(params.usock_file) == 0) { + LOG(log_error, logtype_cnid, "default usock filename too long"); + return NULL; + } else { + return ¶ms; + } + } else { + LOG(log_error, logtype_cnid, "error opening %s: %s", pfn, strerror(errno)); + return NULL; + } + } + parse_err = 0; + + while ((items = fscanf(fp, " %s %s", key, val)) != EOF) { + if (items != 2) { + LOG(log_error, logtype_cnid, "error parsing config file"); + parse_err++; + break; + } + + /* Config for both cnid_meta and dbd */ + if (! strcmp(key, "usock_file")) { + if (make_pathname(params.usock_file, dir, val, usock_maxlen()) < 0) { + LOG(log_error, logtype_cnid, "usock filename %s too long", val); + parse_err++; + } else + LOG(log_info, logtype_cnid, "db_param: setting UNIX domain socket filename to %s", params.usock_file); + } + + if (! strcmp(key, "fd_table_size")) { + params.fd_table_size = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting max number of concurrent afpd connections per volume (fd_table_size) to %d", params.fd_table_size); + } else if (! strcmp(key, "logfile_autoremove")) { + params.logfile_autoremove = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting logfile_autoremove to %d", params.logfile_autoremove); + } else if (! strcmp(key, "cachesize")) { + params.cachesize = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting cachesize to %d", params.cachesize); + } else if (! strcmp(key, "maxlocks")) { + params.maxlocks = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting maxlocks to %d", params.maxlocks); + } else if (! strcmp(key, "maxlockobjs")) { + params.maxlockobjs = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting maxlockobjs to %d", params.maxlockobjs); + } else if (! strcmp(key, "flush_frequency")) { + params.flush_frequency = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting flush_frequency to %d", params.flush_frequency); + } else if (! strcmp(key, "flush_interval")) { + params.flush_interval = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting flush_interval to %d", params.flush_interval); + } else if (! strcmp(key, "idle_timeout")) { + params.idle_timeout = parse_int(val); + LOG(log_info, logtype_cnid, "db_param: setting idle timeout to %d", params.idle_timeout); + } + + if (parse_err) + break; + } + + if (strlen(params.usock_file) == 0) { + LOG(log_error, logtype_cnid, "default usock filename too long"); + parse_err++; + } + + fclose(fp); + if (! parse_err) { + /* sanity checks */ + if (params.flush_frequency <= 0) + params.flush_frequency = 86400; + + if (params.flush_interval <= 0) + params.flush_interval = 1000000; + + if (params.fd_table_size <= 2) + params.fd_table_size = 32; + + if (params.idle_timeout <= 0) + params.idle_timeout = 86400; + + return ¶ms; + } + else + return NULL; +} + + + diff --git a/etc/cnid_dbd/db_param.h b/etc/cnid_dbd/db_param.h new file mode 100644 index 0000000..0d6e9b9 --- /dev/null +++ b/etc/cnid_dbd/db_param.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 + * All Rights Reserved. See COPYING. + */ + +#ifndef CNID_DBD_DB_PARAM_H +#define CNID_DBD_DB_PARAM_H 1 + +#include + +#define DEFAULT_LOGFILE_AUTOREMOVE 1 +#define DEFAULT_CACHESIZE (8 * 1024) /* KB, so 8 MB */ +#define DEFAULT_MAXLOCKS 20000 +#define DEFAULT_MAXLOCKOBJS 20000 +#define DEFAULT_FLUSH_FREQUENCY 1000 +#define DEFAULT_FLUSH_INTERVAL 1800 +#define DEFAULT_USOCK_FILE "usock" +#define DEFAULT_FD_TABLE_SIZE 512 +#define DEFAULT_IDLE_TIMEOUT (10 * 60) + +struct db_param { + char *dir; + int logfile_autoremove; + int cachesize; /* in KB */ + int maxlocks; + int maxlockobjs; + int flush_interval; + int flush_frequency; + char usock_file[MAXPATHLEN + 1]; + int fd_table_size; + int idle_timeout; + int max_vols; +}; + +extern struct db_param *db_param_read (char *); + +#endif /* CNID_DBD_DB_PARAM_H */ + diff --git a/etc/cnid_dbd/dbd.h b/etc/cnid_dbd/dbd.h new file mode 100644 index 0000000..ab532d8 --- /dev/null +++ b/etc/cnid_dbd/dbd.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2009, 2010 + * All Rights Reserved. See COPYING. + */ + +#ifndef CNID_DBD_DBD_H +#define CNID_DBD_DBD_H 1 + +#include + +#include + +extern int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply); +extern int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply); + +extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_get(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_resolve(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_update(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int idx); +extern int dbd_getstamp(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_rebuild_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_search(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *); +extern int dbd_check_indexes(DBD *dbd, char *); + +#endif /* CNID_DBD_DBD_H */ diff --git a/etc/cnid_dbd/dbd_add.c b/etc/cnid_dbd/dbd_add.c new file mode 100644 index 0000000..3af72fa --- /dev/null +++ b/etc/cnid_dbd/dbd_add.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dbif.h" +#include "pack.h" +#include "dbd.h" + +int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + DBT key, data; + int rc; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = &rply->cnid; + key.size = sizeof(rply->cnid); + + data.data = pack_cnid_data(rqst); + data.size = CNID_HEADER_LEN + rqst->namelen + 1; + memcpy(data.data, &rply->cnid, sizeof(rply->cnid)); + + /* main database */ + if ((rc = dbif_put(dbd, DBIF_CNID, &key, &data, DB_NOOVERWRITE))) { + /* This could indicate a database error or that the key already exists + (because of DB_NOOVERWRITE). In that case we still look at some sort of + database corruption since that is not supposed to happen. */ + + switch (rc) { + case 1: + rply->result = CNID_DBD_RES_ERR_DUPLCNID; + break; + case -1: + /* FIXME: Should that not be logged for case 1:? */ + LOG(log_error, logtype_cnid, "add_cnid: duplicate %x %s", rply->cnid + , (char *)data.data + CNID_NAME_OFS); + + rqst->cnid = rply->cnid; + rc = dbd_update(dbd, rqst, rply); + if (rc < 0) { + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + else + return 0; + break; + } + return -1; + } + + return 0; +} + +/* ---------------------- */ +int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply) +{ + static cnid_t id; + static char buf[ROOTINFO_DATALEN]; + DBT rootinfo_key, rootinfo_data, key, data; + int rc; + cnid_t hint; + + memset(&rootinfo_key, 0, sizeof(rootinfo_key)); + memset(&rootinfo_data, 0, sizeof(rootinfo_data)); + rootinfo_key.data = ROOTINFO_KEY; + rootinfo_key.size = ROOTINFO_KEYLEN; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + if (id == 0) { + if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) != 1) { + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN); + memcpy(&hint, buf + CNID_TYPE_OFS, sizeof(hint)); + id = ntohl(hint); + if (id < CNID_START - 1) + id = CNID_START - 1; + } + + cnid_t trycnid, tmp; + + while (true) { + if (rply->cnid != CNID_INVALID) { + trycnid = ntohl(rply->cnid); + rply->cnid = CNID_INVALID; + } else { + if (++id == CNID_INVALID) + id = CNID_START; + trycnid = id; + } + tmp = htonl(trycnid); + key.data = &tmp; + key.size = sizeof(cnid_t); + rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0); + if (rc == 0) { + break; + } else if (rc == -1) { + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + } + + if (trycnid == id) { + rootinfo_data.data = buf; + rootinfo_data.size = ROOTINFO_DATALEN; + hint = htonl(id); + memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint)); + + if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) { + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + } + + rply->cnid = htonl(trycnid); + return 0; +} + +/* ------------------------ */ +/* We need a nolookup version for `dbd` */ +int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + rply->namelen = 0; + + LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx) {start}", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + + /* See if we have an entry already and return it if yes */ + if (dbd_lookup(dbd, rqst, rply) < 0) { + LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): error in dbd_lookup", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + return -1; + } + + if (rply->result == CNID_DBD_RES_OK) { + /* Found it. rply->cnid is the correct CNID now. */ + LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success --> CNID: %u", ntohl(rply->cnid)); + return 1; + } + + LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): {adding to database ...}", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + + if (rqst->cnid) { + /* rqst->cnid is the cnid "hint"/backup from the adouble file */ + rply->cnid = rqst->cnid; + } + if (get_cnid(dbd, rply) < 0) { + if (rply->result == CNID_DBD_RES_ERR_MAX) { + LOG(log_error, logtype_cnid, "dbd_add: FATAL: CNID database has reached its limit."); + /* This will cause an abort/rollback if transactions are used */ + return 0; + } else { + LOG(log_error, logtype_cnid, "dbd_add: Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name); + return -1; + } + } + + if (add_cnid(dbd, rqst, rply) < 0) { + if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) { + LOG(log_error, logtype_cnid, "dbd_add(DID: %u/\"%s\", dev/ino 0x%llx/0x%llx): Cannot add CNID: %u", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid)); + /* abort/rollback, see above */ + return 0; + } else { + LOG(log_error, logtype_cnid, "dbd_add: Failed to add CNID for %s to database", rqst->name); + return -1; + } + } + LOG(log_debug, logtype_cnid, "dbd_add(did:%u, '%s', dev/ino:0x%llx/0x%llx): Added with CNID: %u", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid)); + + rply->result = CNID_DBD_RES_OK; + return 1; +} diff --git a/etc/cnid_dbd/dbd_dbcheck.c b/etc/cnid_dbd/dbd_dbcheck.c new file mode 100644 index 0000000..27f9021 --- /dev/null +++ b/etc/cnid_dbd/dbd_dbcheck.c @@ -0,0 +1,54 @@ +/* + * + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "pack.h" +#include "dbif.h" +#include "dbd.h" + +int dbd_check_indexes(DBD *dbd, char *dbdir) +{ + u_int32_t c_didname = 0, c_devino = 0, c_cnid = 0; + + LOG(log_note, logtype_cnid, "CNID database at `%s' is being checked (quick)", dbdir); + + if (dbif_count(dbd, DBIF_CNID, &c_cnid)) + return -1; + + if (dbif_count(dbd, DBIF_IDX_DEVINO, &c_devino)) + return -1; + + /* bailout after the first error */ + if ( c_cnid != c_devino) { + LOG(log_error, logtype_cnid, "CNID database at `%s' corrupted (%u/%u)", dbdir, c_cnid, c_devino); + return 1; + } + + if (dbif_count(dbd, DBIF_IDX_DIDNAME, &c_didname)) + return -1; + + if ( c_cnid != c_didname) { + LOG(log_error, logtype_cnid, "CNID database at `%s' corrupted (%u/%u)", dbdir, c_cnid, c_didname); + return 1; + } + + LOG(log_note, logtype_cnid, "CNID database at `%s' seems ok, %u entries.", dbdir, c_cnid); + return 0; +} + + diff --git a/etc/cnid_dbd/dbd_delete.c b/etc/cnid_dbd/dbd_delete.c new file mode 100644 index 0000000..5910942 --- /dev/null +++ b/etc/cnid_dbd/dbd_delete.c @@ -0,0 +1,91 @@ +/* + * + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include +#include + +#include "dbif.h" +#include "dbd.h" +#include "pack.h" + +int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int idx) +{ + DBT key; + int rc; + unsigned char *buf; + + memset(&key, 0, sizeof(key)); + rply->namelen = 0; + + switch (idx) { + case DBIF_IDX_DEVINO: + buf = pack_cnid_data(rqst); + key.data = buf + CNID_DEVINO_OFS; + key.size = CNID_DEVINO_LEN; + if ((rc = dbif_del(dbd, DBIF_IDX_DEVINO, &key, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for dev/ino: 0x%llx/0x%llx", + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (rc) { + LOG(log_debug, logtype_cnid, "cnid_delete: deleted dev/ino: 0x%llx/0x%llx", + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + rply->result = CNID_DBD_RES_OK; + } else { + LOG(log_debug, logtype_cnid, "cnid_delete: dev/ino: 0x%llx/0x%llx not in database", + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + rply->result = CNID_DBD_RES_NOTFOUND; + } + break; + case DBIF_IDX_DIDNAME: + buf = pack_cnid_data(rqst); + key.data = buf + CNID_DID_OFS; + key.size = CNID_DID_LEN + rqst->namelen + 1; + if ((rc = dbif_del(dbd, DBIF_IDX_DIDNAME, &key, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for DID: %lu, name: %s", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (rc) { + LOG(log_debug, logtype_cnid, "cnid_delete: deleted DID: %lu, name: %s", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_OK; + } else { + LOG(log_debug, logtype_cnid, "cnid_delete: DID: %lu, name: %s not in database", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_NOTFOUND; + } + break; + default: + key.data = (void *) &rqst->cnid; + key.size = sizeof(rqst->cnid); + + if ((rc = dbif_del(dbd, DBIF_CNID, &key, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for CNID %u", ntohl(rqst->cnid)); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (rc) { + LOG(log_debug, logtype_cnid, "cnid_delete: CNID %u deleted", ntohl(rqst->cnid)); + rply->result = CNID_DBD_RES_OK; + } else { + LOG(log_debug, logtype_cnid, "cnid_delete: CNID %u not in database", ntohl(rqst->cnid)); + rply->result = CNID_DBD_RES_NOTFOUND; + } + } + + return 1; +} diff --git a/etc/cnid_dbd/dbd_get.c b/etc/cnid_dbd/dbd_get.c new file mode 100644 index 0000000..07d82da --- /dev/null +++ b/etc/cnid_dbd/dbd_get.c @@ -0,0 +1,66 @@ +/* + * + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include + + +#include "dbif.h" +#include "dbd.h" +#include "pack.h" + + +/* Return CNID for a given did/name. */ + +int dbd_get(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + char start[CNID_DID_LEN + MAXPATHLEN + 1], *buf; + DBT key, data; + int rc; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + rply->namelen = 0; + + buf = start; + memcpy(buf, &rqst->did, sizeof(rqst->did)); + buf += sizeof(rqst->did); + memcpy(buf, rqst->name, rqst->namelen); + *(buf + rqst->namelen) = '\0'; /* Make it a C-string. */ + key.data = start; + key.size = CNID_DID_LEN + rqst->namelen + 1; + + if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &data, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_get: Unable to get CNID %u, name %s", ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + + if (rc == 0) { + LOG(log_debug, logtype_cnid, "cnid_get: CNID not found for did %u name %s", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + memcpy(&rply->cnid, data.data, sizeof(rply->cnid)); + + LOG(log_debug, logtype_cnid, "cnid_get: Returning CNID did %u name %s as %u", + ntohl(rqst->did), rqst->name, ntohl(rply->cnid)); + + rply->result = CNID_DBD_RES_OK; + return 1; +} diff --git a/etc/cnid_dbd/dbd_getstamp.c b/etc/cnid_dbd/dbd_getstamp.c new file mode 100644 index 0000000..27270c7 --- /dev/null +++ b/etc/cnid_dbd/dbd_getstamp.c @@ -0,0 +1,55 @@ + +/* + * + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include + +#include "dbif.h" +#include "dbd.h" +#include "pack.h" + +/* Return the unique stamp associated with this database */ + +int dbd_getstamp(DBD *dbd, struct cnid_dbd_rqst *rqst _U_, struct cnid_dbd_rply *rply) +{ + DBT key, data; + int rc; + + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + rply->namelen = 0; + + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if ((rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_getstamp: Error getting rootinfo record"); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + + if (rc == 0) { + LOG(log_error, logtype_cnid, "dbd_getstamp: No rootinfo record found"); + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + rply->namelen = CNID_DEV_LEN; + rply->name = (char *)data.data + CNID_DEV_OFS; + rply->result = CNID_DBD_RES_OK; + return 1; +} diff --git a/etc/cnid_dbd/dbd_lookup.c b/etc/cnid_dbd/dbd_lookup.c new file mode 100644 index 0000000..9ff4e41 --- /dev/null +++ b/etc/cnid_dbd/dbd_lookup.c @@ -0,0 +1,316 @@ +/* + * + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2009 + * All Rights Reserved. See COPYING. + */ + +/* +CNID salvation spec: +general rule: better safe then sorry, so we always delete CNIDs and assign +new ones in case of a lookup mismatch. afpd also sends us the CNID found +in the adouble file. In certain cases we can use this hint to determince +the right CNID. + + +The lines... + +Id Did T Dev Inode Name +============================ +a b c d e name1 +--> +f g h i h name2 + +...are the expected results of certain operations. (f) is the speced CNID, in some +cases it's only intermediate as described in the text and is overridden by another +spec. + +1) UNIX rename (via mv) or inode reusage(!) +------------------------------------------- +Name is possibly changed (rename case) but inode is the same. +We should try to keep the CNID, but we cant, because inode reusage is probably +much to frequent. + +rename: +15 2 f 1 1 file +--> +15 x f 1 1 renamedfile + +inode reusage: +15 2 f 1 1 file +--> +16 y f 1 1 inodereusagefile + +Result in dbd_lookup (-: not found, +: found): ++ devino +- didname + +Possible solution: +None. Delete old data, file gets new CNID in both cases (rename and inode). +If we got a hint and hint matches the CNID from devino we keep it and update +the record. + +2) UNIX mv from one folder to another +---------------------------------------- +Name is unchanged and inode stays the same, but DID is different. +We should try to keep the CNID. + +15 2 f 1 1 file +--> +15 x f 1 1 file + +Result in dbd_lookup: ++ devino +- didname + +Possible solution: +strcmp names, if they match keep CNID. Unfortunately this also can't be +distinguished from a new file with a reused inode. So me must assign +a new CNID. +If we got a hint and hint matches the CNID from devino we keep it and update +the record. + +3) Restore from backup ie change of inode number -- or emacs +------------------------------------------------------------ + +15 2 f 1 1 file +--> +15 2 f 1 2 file + +Result in dbd_lookup: +- devino ++ didname + +Possible fixup solution: +test-suite test235 tests and ensures that the CNID is _changed_. The reason for +this is somewhat lost in time, but nevertheless we believe our test suite. + +Similar things happen with emas: emacs uses a backup file (file~). When saving +because of inode reusage of the fs, both files most likely exchange inodes. + +15 2 f 1 1 file +16 2 f 1 2 file~ +--> this would be nice: +15 2 f 1 2 file +16 2 f 1 1 file~ +--> but for the reasons described above we must implement +17 2 f 1 2 file +18 2 f 1 1 file~ + +Result in dbd_lookup for the emacs case: ++ devino --> CNID: 16 ++ didname -> CNID: 15 +devino search and didname search result in different CNIDs !! + +Possible fixup solution: +to be safe we must assign new CNIDs to both files. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pack.h" +#include "dbif.h" +#include "dbd.h" + +/* + * This returns the CNID corresponding to a particular file. It will also fix + * up the database if there's a problem. + */ + +int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + unsigned char *buf; + DBT key, devdata, diddata; + int devino = 1, didname = 1; + int rc; + cnid_t id_devino, id_didname; + u_int32_t type_devino = (unsigned)-1; + u_int32_t type_didname = (unsigned)-1; + int update = 0; + + memset(&key, 0, sizeof(key)); + memset(&diddata, 0, sizeof(diddata)); + memset(&devdata, 0, sizeof(devdata)); + + rply->namelen = 0; + rply->cnid = 0; + + LOG(log_maxdebug, logtype_cnid, "dbd_lookup(): START"); + + buf = pack_cnid_data(rqst); + + /* Look for a CNID. We have two options: dev/ino or did/name. If we + only get a match in one of them, that means a file has moved. */ + key.data = buf + CNID_DEVINO_OFS; + key.size = CNID_DEVINO_LEN; + + if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (rc == 0) { + devino = 0; + } + else { + memcpy(&id_devino, devdata.data, sizeof(rply->cnid)); + memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino)); + type_devino = ntohl(type_devino); + } + + key.data = buf + CNID_DID_OFS; + key.size = CNID_DID_LEN + rqst->namelen + 1; + + if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (rc == 0) { + didname = 0; + } + else { + memcpy(&id_didname, diddata.data, sizeof(rply->cnid)); + memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname)); + type_didname = ntohl(type_didname); + } + + LOG(log_maxdebug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx) {devino: %u, didname: %u}", + rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, devino, didname); + + /* Have we found anything at all ? */ + if (!devino && !didname) { + /* nothing found */ + LOG(log_debug, logtype_cnid, "dbd_lookup: name: '%s', did: %u, dev/ino: 0x%llx/0x%llx is not in the CNID database", + rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + /* Check for type (file/dir) mismatch */ + if ((devino && (type_devino != rqst->type)) || (didname && (type_didname != rqst->type))) { + + if (devino && (type_devino != rqst->type)) { + /* one is a dir one is a file, remove from db */ + + LOG(log_debug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): type mismatch for devino", + rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + + rqst->cnid = id_devino; + rc = dbd_delete(dbd, rqst, rply, DBIF_CNID); + rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO); + rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME); + if (rc < 0) { + LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for devino", + rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + return -1; + } + } + + if (didname && (type_didname != rqst->type)) { + /* same: one is a dir one is a file, remove from db */ + + LOG(log_debug, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): type mismatch for didname", + rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + + rqst->cnid = id_didname; + rc = dbd_delete(dbd, rqst, rply, DBIF_CNID); + rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO); + rc += dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME); + if (rc < 0) { + LOG(log_error, logtype_cnid, "dbd_lookup(name:'%s', did:%u, dev/ino:0x%llx/0x%llx): error deleting type mismatch for didname", + rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + return -1; + } + } + + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + if (devino && didname && id_devino == id_didname) { + /* everything is fine */ + LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): Got CNID: %u", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, htonl(id_didname)); + rply->cnid = id_didname; + rply->result = CNID_DBD_RES_OK; + return 1; + } + + if (devino && didname && id_devino != id_didname) { + /* CNIDs don't match, something of a worst case, or possibly 3) emacs! */ + LOG(log_debug, logtype_cnid, "dbd_lookup: CNID mismatch: (DID:%u/'%s') --> %u , (0x%llx/0x%llx) --> %u", + ntohl(rqst->did), rqst->name, ntohl(id_didname), + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(id_devino)); + + rqst->cnid = id_devino; + if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) + return -1; + + rqst->cnid = id_didname; + if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) + return -1; + + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + if ( ! didname) { + LOG(log_debug, logtype_cnid, "dbd_lookup(CNID hint: %u, DID:%u, \"%s\", 0x%llx/0x%llx): CNID resolve problem: server side rename oder reused inode", + ntohl(rqst->cnid), ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + if (rqst->cnid == id_devino) { + LOG(log_debug, logtype_cnid, "dbd_lookup: server side mv (with resource fork)"); + update = 1; + } else { + rqst->cnid = id_devino; + if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) + return -1; + rply->result = CNID_DBD_RES_NOTFOUND; + rqst->cnid = CNID_INVALID; /* invalidate CNID hint */ + return 1; + } + } + + if ( ! devino) { + LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: changed dev/ino", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + rqst->cnid = id_didname; + if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) + return -1; + rply->result = CNID_DBD_RES_NOTFOUND; + rqst->cnid = CNID_INVALID; /* invalidate CNID hint */ + return 1; + } + + /* This is also a catch all if we've forgot to catch some possibility with the preceding ifs*/ + if (!update) { + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + /* Fix up the database */ + rc = dbd_update(dbd, rqst, rply); + if (rc >0) { + rply->cnid = rqst->cnid; + } + + LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): Got CNID (needed update): %u", + ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid)); + + return rc; +} diff --git a/etc/cnid_dbd/dbd_rebuild_add.c b/etc/cnid_dbd/dbd_rebuild_add.c new file mode 100644 index 0000000..3aee1c9 --- /dev/null +++ b/etc/cnid_dbd/dbd_rebuild_add.c @@ -0,0 +1,83 @@ +/* + * + * Copyright (C) Joerg Lenneis 2005 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include +#include + +#include "pack.h" +#include "dbif.h" +#include "dbd.h" + + +/* rebuild_add: Enter all fields (including the CNID) into the database and + update the current cnid, for emergency repairs. */ + +int dbd_rebuild_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + DBT key, data; + cnid_t cur, tmp, id; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + rply->namelen = 0; + + key.data = &rqst->cnid; + key.size = sizeof(cnid_t); + + data.data = pack_cnid_data(rqst); + data.size = CNID_HEADER_LEN + rqst->namelen + 1; + memcpy(data.data, &rqst->cnid, sizeof(cnid_t)); + + /* FIXME: In cnid_cdb.c Bjoern does a lookup here and returns the CNID found if sucessful. Why? */ + + if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) { + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + + LOG(log_debug, logtype_cnid, + "dbd_rebuild_add(CNID: %u, did: %u, name: \"%s\", dev/ino:0x%llx/0x%llx): success", + ntohl(rqst->cnid), ntohl(rqst->did), rqst->name, + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) <= 0) { + /* FIXME: If we cannot find ROOTINFO_KEY, should this be considered + fatal or should we just return 0 and roll back? */ + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + + memcpy(&tmp, (char *) data.data + CNID_TYPE_OFS, sizeof(cnid_t)); + cur = ntohl(tmp); + id = ntohl(rqst->cnid); + + if (id > cur) { + data.size = ROOTINFO_DATALEN; + memcpy((char *) data.data + CNID_TYPE_OFS, &rqst->cnid, sizeof(cnid_t)); + if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) { + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + } + + rply->cnid = rqst->cnid; + rply->result = CNID_DBD_RES_OK; + return 1; +} + + diff --git a/etc/cnid_dbd/dbd_resolve.c b/etc/cnid_dbd/dbd_resolve.c new file mode 100644 index 0000000..20ff8f7 --- /dev/null +++ b/etc/cnid_dbd/dbd_resolve.c @@ -0,0 +1,61 @@ +/* + * + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include + +#include "dbif.h" +#include "dbd.h" +#include "pack.h" + +/* Return the did/name pair corresponding to a CNID. */ + +int dbd_resolve(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + DBT key, data; + int rc; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + rply->namelen = 0; + + key.data = (void *) &rqst->cnid; + key.size = sizeof(cnid_t); + + if ((rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0)) < 0) { + LOG(log_error, logtype_cnid, "dbd_resolve: DB Error resolving CNID %u", ntohl(rqst->cnid)); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + + if (rc == 0) { + + LOG(log_debug, logtype_cnid, "dbd_resolve: Could not resolve CNID %u", ntohl(rqst->cnid)); + + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + memcpy(&rply->did, (char *) data.data + CNID_DID_OFS, sizeof(cnid_t)); + + rply->namelen = data.size; + rply->name = (char *)data.data; + + LOG(log_debug, logtype_cnid, "dbd_resolve(CNID: %u): did: %u, name: \"%s\"", + ntohl(rqst->cnid), ntohl(rply->did), rply->name + CNID_NAME_OFS); + + rply->result = CNID_DBD_RES_OK; + return 1; +} diff --git a/etc/cnid_dbd/dbd_search.c b/etc/cnid_dbd/dbd_search.c new file mode 100644 index 0000000..685eef6 --- /dev/null +++ b/etc/cnid_dbd/dbd_search.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) Frank Lahm 2010 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include +#include + +#include "dbif.h" +#include "dbd.h" +#include "pack.h" + +int dbd_search(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + DBT key; + int results; + static char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)]; + + LOG(log_debug, logtype_cnid, "dbd_search(\"%s\"):", rqst->name); + + memset(&key, 0, sizeof(key)); + rply->name = resbuf; + rply->namelen = 0; + + key.data = (char *)rqst->name; + key.size = rqst->namelen; + + if ((results = dbif_search(dbd, &key, resbuf)) < 0) { + LOG(log_error, logtype_cnid, "dbd_search(\"%s\"): db error", rqst->name); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (results) { + LOG(log_debug, logtype_cnid, "dbd_search(\"%s\"): %d matches", rqst->name, results); + rply->namelen = results * sizeof(cnid_t); + rply->result = CNID_DBD_RES_OK; + } else { + LOG(log_debug, logtype_cnid, "dbd_search(\"%s\"): no matches", rqst->name); + rply->result = CNID_DBD_RES_NOTFOUND; + } + + return 1; +} diff --git a/etc/cnid_dbd/dbd_update.c b/etc/cnid_dbd/dbd_update.c new file mode 100644 index 0000000..7a95bfe --- /dev/null +++ b/etc/cnid_dbd/dbd_update.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2009,2010 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include + + +#include "pack.h" +#include "dbif.h" +#include "dbd.h" + + +/* + cnid_update: takes the given cnid and updates the metadata. + First, delete given CNID, then re-insert. +*/ + +int dbd_update(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + DBT key, data; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + rply->namelen = 0; + + /* Try to wipe everything, also using the indexes */ + if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) + goto err_db; + if (dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO) < 0) + goto err_db; + if (dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME) < 0) + goto err_db; + + /* Make a new entry. */ + key.data = &rqst->cnid; + key.size = sizeof(rqst->cnid); + data.data = pack_cnid_data(rqst); + data.size = CNID_HEADER_LEN + rqst->namelen + 1; + memcpy(data.data, &rqst->cnid, sizeof(rqst->cnid)); + + if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) + goto err_db; + + LOG(log_debug, logtype_cnid, "dbd_update: Updated dbd with dev/ino: 0x%llx/0x%llx, did: %u, name: %s, cnid: %u", + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(rqst->cnid)); + + rply->result = CNID_DBD_RES_OK; + return 1; + +err_db: + LOG(log_error, logtype_cnid, "dbd_update: Unable to update CNID: %u, dev/ino: 0x%llx/0x%llx, DID: %u: %s", + ntohl(rqst->cnid), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name); + + rply->result = CNID_DBD_RES_ERR_DB; + return -1; +} diff --git a/etc/cnid_dbd/dbif.c b/etc/cnid_dbd/dbif.c new file mode 100644 index 0000000..3dae61c --- /dev/null +++ b/etc/cnid_dbd/dbif.c @@ -0,0 +1,1327 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2009 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "db_param.h" +#include "dbif.h" +#include "pack.h" + +#define DB_ERRLOGFILE "db_errlog" + +/*! + * Get the db stamp which is the st_ctime of the file "cnid2.db" and store it in buffer + */ +static int dbif_stamp(DBD *dbd, void *buffer, int size) +{ + EC_INIT; + struct stat st; + int cwd = -1; + + if (size < 8) + EC_FAIL; + + /* Remember cwd */ + if ((cwd = open(".", O_RDONLY)) < 0) { + LOG(log_error, logtype_cnid, "error opening cwd: %s", strerror(errno)); + EC_FAIL; + } + + /* chdir to db_envhome */ + if ((chdir(dbd->db_envhome)) != 0) { + LOG(log_error, logtype_cnid, "error chdiring to db_env '%s': %s", dbd->db_envhome, strerror(errno)); + EC_FAIL; + } + + if (stat(dbd->db_table[DBIF_CNID].name, &st) < 0) { + LOG(log_error, logtype_cnid, "error stating database %s: %s", dbd->db_table[DBIF_CNID].name, db_strerror(errno)); + EC_FAIL; + } + + LOG(log_maxdebug, logtype_cnid,"stamp: %s", asctime(localtime(&st.st_ctime))); + + memset(buffer, 0, size); + memcpy(buffer, &st.st_ctime, sizeof(st.st_ctime)); + +EC_CLEANUP: + if (cwd != -1) { + if (fchdir(cwd) != 0) { + LOG(log_error, logtype_cnid, "error chdiring back: %s", strerror(errno)); + EC_STATUS(-1); + } + close(cwd); + } + EC_EXIT; +} + +/*! + * Inititialize rootinfo key (which has CNID 0 as key) + * + * This also "stamps" the database, which means storing st.st_ctime of the + * "cnid2.db" file in the rootinfo data at the DEV offset + * + * @param dbd (rw) database handle + * @param version (r) database version number + * + * @returns -1 on error, 0 on success + */ +static int dbif_init_rootinfo(DBD *dbd, int version) +{ + DBT key, data; + uint32_t uint32; + char buf[ROOTINFO_DATALEN]; + + LOG(log_debug, logtype_cnid, "Setting CNID database version to %u", version); + + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + data.data = buf; + data.size = ROOTINFO_DATALEN; + + memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN); + + uint32 = htonl(CNID_START - 1); + memcpy(buf + CNID_TYPE_OFS, &uint32, sizeof(uint32)); + + uint32 = htonl(version); + memcpy(buf + CNID_DID_OFS, &uint32, sizeof(uint32)); + + if (dbif_stamp(dbd, buf + CNID_DEV_OFS, CNID_DEV_LEN) < 0) + return -1; + + if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) + return -1; + if (dbif_txn_commit(dbd) != 1) { + LOG(log_error, logtype_cnid, "dbif_init_rootinfo: cant commit txn"); + return -1; + } + + return 0; +} + +/*! + * Return CNID database version number + * + * Returns version in *version + * + * @returns -1 on error, 0 if theres no rootinfo key yet, 1 if *version is returned + */ +static int dbif_getversion(DBD *dbd, uint32_t *version) +{ + DBT key, data; + int ret; + + LOG(log_maxdebug, logtype_cnid, "dbif_getversion: reading version info"); + + *version = -1; + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + switch (dbif_get(dbd, DBIF_CNID, &key, &data, 0)) { + case 1: /* found */ + memcpy(version, (char *)data.data + CNID_DID_OFS, sizeof(uint32_t)); + *version = ntohl(*version); + LOG(log_debug, logtype_cnid, "CNID database version %u", *version); + ret = 1; + break; + case 0: /* not found */ + LOG(log_debug, logtype_cnid, "dbif_getversion: no version info found"); + ret = 0; + break; + default: + LOG(log_error, logtype_cnid, "dbif_getversion: database error"); + ret = -1; + break; + } + + return ret; +} + +/*! + * Set CNID database version number + * + * Initializes rootinfo key as neccessary + * @returns -1 on error, 0 on success + */ +static int dbif_setversion(DBD *dbd, uint32_t version) +{ + int ret; + DBT key, data; + uint32_t v; + + LOG(log_debug, logtype_cnid, "Setting CNID database version to %u", version); + + v = version; + v = htonl(v); + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if ((ret = dbif_get(dbd, DBIF_CNID, &key, &data, 0)) == -1) + return -1; + if (ret == 0) { + /* No rootinfo key yet, init it */ + if (dbif_init_rootinfo(dbd, CNID_VERSION) != 0) + return -1; + /* Now try again */ + if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) == -1) + return -1; + } + memcpy((char *)data.data + CNID_DID_OFS, &v, sizeof(v)); + data.size = ROOTINFO_DATALEN; + if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) + return -1; + + return 0; +} + +/*! + * Upgrade CNID database versions, initialize rootinfo key as as necessary in dbif_setversion() + * + * For now this does nothing, as upgrading from ver. 0 to 1 is done in dbif_open + */ +#define UNINTIALIZED_DB UINT32_MAX +static int dbif_upgrade(DBD *dbd) +{ + uint32_t version = CNID_VERSION_UNINTIALIZED_DB; + + if (dbif_getversion(dbd, &version) == -1) + return -1; + if (version == CNID_VERSION_UNINTIALIZED_DB) { + version = CNID_VERSION; + if (dbif_setversion(dbd, CNID_VERSION) != 0) + return -1; + } + + /* + * Do upgrade stuff ... + */ + + /* Write current version to database */ + if (version != CNID_VERSION) { + if (dbif_setversion(dbd, CNID_VERSION) != 0) + return -1; + } + + LOG(log_debug, logtype_cnid, "Finished CNID database version upgrade check"); + + return 0; +} + +/* --------------- */ +static int dbif_openlog(DBD *dbd) +{ + int ret = 0; + int cwd = -1; + + if ( ! dbd->db_filename) + /* in memory db */ + return 0; + + /* Remember cwd */ + if ((cwd = open(".", O_RDONLY)) < 0) { + LOG(log_error, logtype_cnid, "error opening cwd: %s", strerror(errno)); + return -1; + } + + /* chdir to db_envhome */ + if ((chdir(dbd->db_envhome)) != 0) { + LOG(log_error, logtype_cnid, "error chdiring to db_env '%s': %s", dbd->db_envhome, strerror(errno)); + ret = -1; + goto exit; + } + + if ((dbd->db_errlog = fopen(DB_ERRLOGFILE, "a")) == NULL) + LOG(log_warning, logtype_cnid, "error creating/opening DB errlogfile: %s", strerror(errno)); + + if (dbd->db_errlog != NULL) { + dbd->db_env->set_errfile(dbd->db_env, dbd->db_errlog); + dbd->db_env->set_msgfile(dbd->db_env, dbd->db_errlog); + } + +exit: + if (cwd != -1) { + if ((fchdir(cwd)) != 0) { + LOG(log_error, logtype_cnid, "error chdiring back: %s", strerror(errno)); + ret = -1; + } + close(cwd); + } + return ret; +} + +/* --------------- */ +static int dbif_logautorem(DBD *dbd) +{ + int ret = 0; + int cwd = -1; + char **logfiles = NULL; + char **file; + + if ( ! dbd->db_filename) + /* in memory db */ + return 0; + + /* Remember cwd */ + if ((cwd = open(".", O_RDONLY)) < 0) { + LOG(log_error, logtype_cnid, "error opening cwd: %s", strerror(errno)); + return -1; + } + + /* chdir to db_envhome */ + if ((chdir(dbd->db_envhome)) != 0) { + LOG(log_error, logtype_cnid, "error chdiring to db_env '%s': %s", dbd->db_envhome, strerror(errno)); + ret = -1; + goto exit; + } + + if ((ret = dbd->db_env->log_archive(dbd->db_env, &logfiles, 0)) != 0) { + LOG(log_error, logtype_cnid, "error getting list of stale logfiles: %s", + db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + ret = -1; + goto exit; + } + + if (logfiles != NULL) { + for (file = logfiles; *file != NULL; file++) { + if (unlink(*file) < 0) + LOG(log_warning, logtype_cnid, "Error removing stale logfile %s: %s", *file, strerror(errno)); + } + free(logfiles); + } + +exit: + if (cwd != -1) { + if ((fchdir(cwd)) != 0) { + LOG(log_error, logtype_cnid, "error chdiring back: %s", strerror(errno)); + ret = -1; + } + close(cwd); + } + return ret; +} + +/* --------------- */ +DBD *dbif_init(const char *envhome, const char *filename) +{ + DBD *dbd; + + if ( NULL == (dbd = calloc(sizeof(DBD), 1)) ) + return NULL; + + /* filename == NULL means in memory db */ + if (filename) { + if (! envhome) + return NULL; + + dbd->db_envhome = strdup(envhome); + if (NULL == dbd->db_envhome) { + free(dbd); + return NULL; + } + + dbd->db_filename = strdup(filename); + if (NULL == dbd->db_filename) { + free(dbd->db_envhome); + free(dbd); + return NULL; + } + } + + dbd->db_table[DBIF_CNID].name = "cnid2.db"; + dbd->db_table[DBIF_IDX_DEVINO].name = "devino.db"; + dbd->db_table[DBIF_IDX_DIDNAME].name = "didname.db"; + dbd->db_table[DBIF_IDX_NAME].name = "name.db"; + + dbd->db_table[DBIF_CNID].type = DB_BTREE; + dbd->db_table[DBIF_IDX_DEVINO].type = DB_BTREE; + dbd->db_table[DBIF_IDX_DIDNAME].type = DB_BTREE; + dbd->db_table[DBIF_IDX_NAME].type = DB_BTREE; + + dbd->db_table[DBIF_CNID].openflags = DB_CREATE; + dbd->db_table[DBIF_IDX_DEVINO].openflags = DB_CREATE; + dbd->db_table[DBIF_IDX_DIDNAME].openflags = DB_CREATE; + dbd->db_table[DBIF_IDX_NAME].openflags = DB_CREATE; + + dbd->db_table[DBIF_IDX_NAME].flags = DB_DUPSORT; + + return dbd; +} + +/* + We must open the db_env with an absolute pathname, as `dbd` keeps chdir'ing, which + breaks e.g. bdb logfile-rotation with relative pathnames. + But still we use relative paths with DB_ERRLOGFILE + in order to avoid creating absolute paths by copying. Both have no problem with + a relative path. +*/ +int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags) +{ + int ret; + + if ((ret = db_env_create(&dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error creating DB environment: %s", + db_strerror(ret)); + dbd->db_env = NULL; + return -1; + } + + dbd->db_param = *dbp; + + if ((dbif_openlog(dbd)) != 0) + return -1; + + if (dbenv_oflags & DB_RECOVER) { + + LOG(log_debug, logtype_cnid, "Running recovery"); + + dbd->db_env->set_verbose(dbd->db_env, DB_VERB_RECOVERY, 1); + /* Open the database for recovery using DB_PRIVATE option which is faster */ + if ((ret = dbd->db_env->open(dbd->db_env, dbd->db_envhome, dbenv_oflags | DB_PRIVATE, 0))) { + LOG(log_error, logtype_cnid, "error opening DB environment: %s", + db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } + dbenv_oflags = (dbenv_oflags & ~DB_RECOVER); + + if (dbd->db_errlog != NULL) + fflush(dbd->db_errlog); + + if ((ret = dbd->db_env->close(dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error closing DB environment after recovery: %s", + db_strerror(ret)); + dbd->db_env = NULL; + return -1; + } + dbd->db_errlog = NULL; + + if ((ret = db_env_create(&dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error creating DB environment after recovery: %s", + db_strerror(ret)); + dbd->db_env = NULL; + return -1; + } + + if ((dbif_openlog(dbd)) != 0) + return -1; + + LOG(log_debug, logtype_cnid, "Finished recovery."); + } + + if ((ret = dbd->db_env->set_cachesize(dbd->db_env, 0, 1024 * dbp->cachesize, 0))) { + LOG(log_error, logtype_cnid, "error setting DB environment cachesize to %i: %s", + dbp->cachesize, db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } + + if ((ret = dbd->db_env->set_lk_max_locks(dbd->db_env, dbp->maxlocks))) { + LOG(log_error, logtype_cnid, "error setting DB environment maxlocks to %i: %s", + 10000, db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } + + if ((ret = dbd->db_env->set_lk_max_objects(dbd->db_env, dbp->maxlockobjs))) { + LOG(log_error, logtype_cnid, "error setting DB environment max lockobjects to %i: %s", + 10000, db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } + + if ((ret = dbd->db_env->open(dbd->db_env, dbd->db_envhome, dbenv_oflags, 0))) { + LOG(log_error, logtype_cnid, "error opening DB environment after recovery: %s", + db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } + + if ((ret = dbd->db_env->set_flags(dbd->db_env, DB_AUTO_COMMIT, 1))) { + LOG(log_error, logtype_cnid, "error setting DB_AUTO_COMMIT flag: %s", + db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } + + if (dbp->logfile_autoremove) { + if ((dbif_logautorem(dbd)) != 0) + return -1; + +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 7) + if ((ret = dbd->db_env->log_set_config(dbd->db_env, DB_LOG_AUTO_REMOVE, 1))) { + LOG(log_error, logtype_cnid, "error setting DB_LOG_AUTO_REMOVE flag: %s", + db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } +#else + if ((ret = dbd->db_env->set_flags(dbd->db_env, DB_LOG_AUTOREMOVE, 1))) { + LOG(log_error, logtype_cnid, "error setting DB_LOG_AUTOREMOVE flag: %s", + db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } +#endif + } + + return 0; +} + +/* --------------- */ +int dbif_open(DBD *dbd, struct db_param *dbp, int reindex) +{ + int ret, i, cwd; + u_int32_t count; + struct stat st; + DB *upgrade_db; + + /* Try to upgrade if it's a normal on-disk database */ + if (dbd->db_envhome) { + /* Remember cwd */ + if ((cwd = open(".", O_RDONLY)) < 0) { + LOG(log_error, logtype_cnid, "error opening cwd: %s", strerror(errno)); + return -1; + } + + /* chdir to db_envhome. makes it easier checking for old db files and creating db_errlog file */ + if ((chdir(dbd->db_envhome)) != 0) { + LOG(log_error, logtype_cnid, "error chdiring to db_env '%s': %s", dbd->db_envhome, strerror(errno)); + return -1; + } + + if ((stat(dbd->db_filename, &st)) == 0) { + LOG(log_debug, logtype_cnid, "See if we can upgrade the CNID database..."); + if ((ret = db_create(&upgrade_db, dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error creating handle for database: %s", db_strerror(ret)); + return -1; + } + if ((ret = upgrade_db->upgrade(upgrade_db, dbd->db_filename, 0))) { + LOG(log_error, logtype_cnid, "error upgarding database: %s", db_strerror(ret)); + return -1; + } + if ((ret = upgrade_db->close(upgrade_db, 0))) { + LOG(log_error, logtype_cnid, "error closing database: %s", db_strerror(ret)); + return -1; + } + if ((ret = dbd->db_env->txn_checkpoint(dbd->db_env, 0, 0, DB_FORCE))) { + LOG(log_error, logtype_cnid, "error forcing checkpoint: %s", db_strerror(ret)); + return -1; + } + LOG(log_debug, logtype_cnid, "Finished BerkeleyBD upgrade check"); + } + + if ((fchdir(cwd)) != 0) { + LOG(log_error, logtype_cnid, "error chdiring back: %s", strerror(errno)); + return -1; + } + } + + /* Now open databases ... */ + for (i = 0; i != DBIF_DB_CNT; i++) { + if ((ret = db_create(&dbd->db_table[i].db, dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error creating handle for database %s: %s", + dbd->db_table[i].name, db_strerror(ret)); + return -1; + } + + if (dbd->db_table[i].flags) { + if ((ret = dbd->db_table[i].db->set_flags(dbd->db_table[i].db, + dbd->db_table[i].flags))) { + LOG(log_error, logtype_cnid, "error setting flags for database %s: %s", + dbd->db_table[i].name, db_strerror(ret)); + return -1; + } + } + + if ( ! dbd->db_env) { /* In memory db */ + if ((ret = dbd->db_table[i].db->set_cachesize(dbd->db_table[i].db, + 0, + dbp->cachesize, + 4)) /* split in 4 memory chunks */ + < 0) { + LOG(log_error, logtype_cnid, "error setting cachesize %u KB for database %s: %s", + dbp->cachesize / 1024, dbd->db_table[i].name, db_strerror(ret)); + return -1; + } + } + + if (dbd->db_table[i].db->open(dbd->db_table[i].db, + dbd->db_txn, + dbd->db_filename, + dbd->db_table[i].name, + dbd->db_table[i].type, + dbd->db_table[i].openflags, + 0664) < 0) { + LOG(log_error, logtype_cnid, "Cant open database"); + return -1; + } + + if (reindex && i > 0) { + LOG(log_info, logtype_cnid, "Truncating CNID index."); + if ((ret = dbd->db_table[i].db->truncate(dbd->db_table[i].db, NULL, &count, 0))) { + LOG(log_error, logtype_cnid, "error truncating database %s: %s", + dbd->db_table[i].name, db_strerror(ret)); + return -1; + } + } + } + + /* TODO: Implement CNID DB versioning info on new databases. */ + + /* Associate the secondary with the primary. */ + if (reindex) + LOG(log_info, logtype_cnid, "Reindexing did/name index..."); + if ((ret = dbd->db_table[0].db->associate(dbd->db_table[DBIF_CNID].db, + dbd->db_txn, + dbd->db_table[DBIF_IDX_DIDNAME].db, + didname, + (reindex) ? DB_CREATE : 0)) + != 0) { + LOG(log_error, logtype_cnid, "Failed to associate didname database: %s",db_strerror(ret)); + return -1; + } + if (reindex) + LOG(log_info, logtype_cnid, "... done."); + + if (reindex) + LOG(log_info, logtype_cnid, "Reindexing dev/ino index..."); + if ((ret = dbd->db_table[0].db->associate(dbd->db_table[0].db, + dbd->db_txn, + dbd->db_table[DBIF_IDX_DEVINO].db, + devino, + (reindex) ? DB_CREATE : 0)) + != 0) { + LOG(log_error, logtype_cnid, "Failed to associate devino database: %s",db_strerror(ret)); + return -1; + } + if (reindex) + LOG(log_info, logtype_cnid, "... done."); + + if (reindex) + LOG(log_info, logtype_cnid, "Reindexing name index..."); + + /* + * Upgrading from version 0 to 1 requires adding the name index below which + * must be done by specifying the DB_CREATE flag + */ + uint32_t version = CNID_VERSION; + if (dbd->db_envhome && !reindex) { + if (dbif_getversion(dbd, &version) == -1) + return -1; + } + + if ((ret = dbd->db_table[0].db->associate(dbd->db_table[0].db, + dbd->db_txn, + dbd->db_table[DBIF_IDX_NAME].db, + idxname, + (reindex + || + ((CNID_VERSION == CNID_VERSION_1) && (version == CNID_VERSION_0))) + ? DB_CREATE : 0)) != 0) { + LOG(log_error, logtype_cnid, "Failed to associate name index: %s", db_strerror(ret)); + return -1; + } + if (reindex) + LOG(log_info, logtype_cnid, "... done."); + + if ((dbd->db_envhome) && ((ret = dbif_upgrade(dbd)) != 0)) { + LOG(log_error, logtype_cnid, "Error upgrading CNID database to version %d", CNID_VERSION); + return -1; + } + + return 0; +} + +/* ------------------------ */ +static int dbif_closedb(DBD *dbd) +{ + int i; + int ret; + int err = 0; + + for (i = DBIF_DB_CNT -1; i >= 0; i--) { + if (dbd->db_table[i].db != NULL && (ret = dbd->db_table[i].db->close(dbd->db_table[i].db, 0))) { + LOG(log_error, logtype_cnid, "error closing database %s: %s", dbd->db_table[i].name, db_strerror(ret)); + err++; + } + } + if (err) + return -1; + return 0; +} + +/* ------------------------ */ +int dbif_close(DBD *dbd) +{ + int ret; + int err = 0; + + if (dbif_closedb(dbd)) + err++; + + if (dbd->db_env != NULL && (ret = dbd->db_env->close(dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error closing DB environment: %s", db_strerror(ret)); + err++; + } + if (dbd->db_errlog != NULL && fclose(dbd->db_errlog) == EOF) { + LOG(log_error, logtype_cnid, "error closing DB logfile: %s", strerror(errno)); + err++; + } + + free(dbd->db_filename); + free(dbd); + dbd = NULL; + + if (err) + return -1; + return 0; +} + +/* + In order to support silent database upgrades: + destroy env at cnid_dbd shutdown. + */ +int dbif_env_remove(const char *path) +{ + int ret; + DBD *dbd; + + LOG(log_debug, logtype_cnid, "Trying to remove BerkeleyDB environment"); + + if (NULL == (dbd = dbif_init(path, "cnid2.db"))) + return -1; + + /* Get db_env handle */ + if ((ret = db_env_create(&dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error creating DB environment: %s", db_strerror(ret)); + dbd->db_env = NULL; + return -1; + } + + if ((dbif_openlog(dbd)) != 0) + return -1; + + /* Open environment with recovery */ + if ((ret = dbd->db_env->open(dbd->db_env, + dbd->db_envhome, + DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER | DB_PRIVATE, + 0))) { + LOG(log_error, logtype_cnid, "error opening DB environment: %s", + db_strerror(ret)); + dbd->db_env->close(dbd->db_env, 0); + dbd->db_env = NULL; + return -1; + } + + if (dbd->db_errlog != NULL) + fflush(dbd->db_errlog); + + /* Remove logfiles */ + if ((ret = dbd->db_env->log_archive(dbd->db_env, NULL, DB_ARCH_REMOVE))) { + LOG(log_error, logtype_cnid, "error removing transaction logfiles: %s", db_strerror(ret)); + return -1; + } + + if ((ret = dbd->db_env->close(dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error closing DB environment after recovery: %s", db_strerror(ret)); + dbd->db_env = NULL; + return -1; + } + + LOG(log_debug, logtype_cnid, "BerkeleyDB environment recovery done."); + + /* Get a new db_env handle and then remove environment */ + if ((ret = db_env_create(&dbd->db_env, 0))) { + LOG(log_error, logtype_cnid, "error acquiring db_end handle: %s", db_strerror(ret)); + dbd->db_env = NULL; + return -1; + } + if ((ret = dbd->db_env->remove(dbd->db_env, dbd->db_envhome, 0))) { + LOG(log_error, logtype_cnid, "error removing BerkeleyDB environment: %s", db_strerror(ret)); + return -1; + } + + LOG(log_debug, logtype_cnid, "Removed BerkeleyDB environment."); + + return 0; +} + +/* + * The following three functions are wrappers for DB->get(), DB->put() and DB->del(). + * All three return -1 on error. dbif_get()/dbif_del return 1 if the key was found and 0 + * otherwise. dbif_put() returns 0 if key/val was successfully updated and 1 if + * the DB_NOOVERWRITE flag was specified and the key already exists. + * + * All return codes other than DB_NOTFOUND and DB_KEYEXIST from the DB->() + * functions are not expected and therefore error conditions. + */ + +int dbif_get(DBD *dbd, const int dbi, DBT *key, DBT *val, u_int32_t flags) +{ + int ret; + + ret = dbd->db_table[dbi].db->get(dbd->db_table[dbi].db, + dbd->db_txn, + key, + val, + flags); + + if (ret == DB_NOTFOUND) + return 0; + if (ret) { + LOG(log_error, logtype_cnid, "error retrieving value from %s: %s", + dbd->db_table[dbi].name, db_strerror(ret)); + return -1; + } else + return 1; +} + +/* search by secondary return primary */ +int dbif_pget(DBD *dbd, const int dbi, DBT *key, DBT *pkey, DBT *val, u_int32_t flags) +{ + int ret; + + ret = dbd->db_table[dbi].db->pget(dbd->db_table[dbi].db, + dbd->db_txn, + key, + pkey, + val, + flags); + + if (ret == DB_NOTFOUND || ret == DB_SECONDARY_BAD) { + return 0; + } + if (ret) { + LOG(log_error, logtype_cnid, "error retrieving value from %s: %s", + dbd->db_table[dbi].name, db_strerror(ret)); + return -1; + } else + return 1; +} + +/* -------------------------- */ +int dbif_put(DBD *dbd, const int dbi, DBT *key, DBT *val, u_int32_t flags) +{ + int ret; + + if (dbif_txn_begin(dbd) < 0) { + LOG(log_error, logtype_cnid, "error setting key/value in %s", dbd->db_table[dbi].name); + return -1; + } + + ret = dbd->db_table[dbi].db->put(dbd->db_table[dbi].db, + dbd->db_txn, + key, + val, + flags); + + + if (ret) { + if ((flags & DB_NOOVERWRITE) && ret == DB_KEYEXIST) { + return 1; + } else { + LOG(log_error, logtype_cnid, "error setting key/value in %s: %s", + dbd->db_table[dbi].name, db_strerror(ret)); + return -1; + } + } else + return 0; +} + +int dbif_del(DBD *dbd, const int dbi, DBT *key, u_int32_t flags) +{ + int ret; + + /* For cooperation with the dbd utility and its usage of a cursor */ + if (dbd->db_cur) { + dbd->db_cur->close(dbd->db_cur); + dbd->db_cur = NULL; + } + + if (dbif_txn_begin(dbd) < 0) { + LOG(log_error, logtype_cnid, "error deleting key/value from %s", dbd->db_table[dbi].name); + return -1; + } + + ret = dbd->db_table[dbi].db->del(dbd->db_table[dbi].db, + dbd->db_txn, + key, + flags); + + if (ret == DB_NOTFOUND) { + LOG(log_debug, logtype_cnid, "key not found"); + return 0; + } + if (ret) { + LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s", + dbd->db_table[dbi].name, db_strerror(ret)); + return -1; + } else + return 1; +} + +/*! + * Search the database by name + * + * @param resbuf (w) buffer for search results CNIDs, maxsize is assumed to be + * DBD_MAX_SRCH_RSLTS * sizefof(cnid_t) + * + * @returns -1 on error, 0 when nothing found, else the number of matches + */ +int dbif_search(DBD *dbd, DBT *key, char *resbuf) +{ + int ret = 0; + int count = 0; + DBC *cursorp = NULL; + DBT pkey, data; + char *cnids = resbuf; + cnid_t cnid; + char *namebkp = key->data; + int namelenbkp = key->size; + + memset(&pkey, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + /* Get a cursor */ + ret = dbd->db_table[DBIF_IDX_NAME].db->cursor(dbd->db_table[DBIF_IDX_NAME].db, + NULL, + &cursorp, + 0); + if (ret != 0) { + LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(ret)); + ret = -1; + goto exit; + } + + ret = cursorp->pget(cursorp, key, &pkey, &data, DB_SET_RANGE); + while (count < DBD_MAX_SRCH_RSLTS && ret != DB_NOTFOUND) { + if (!((namelenbkp <= key->size) && (strncmp(namebkp, key->data, namelenbkp) == 0))) + break; + count++; + memcpy(cnids, pkey.data, sizeof(cnid_t)); + memcpy(&cnid, pkey.data, sizeof(cnid_t)); + cnids += sizeof(cnid_t); + LOG(log_debug, logtype_cnid, "match: CNID %" PRIu32, ntohl(cnid)); + + ret = cursorp->pget(cursorp, key, &pkey, &data, DB_NEXT); + } + + ret = count; + +exit: + if (cursorp != NULL) + cursorp->close(cursorp); + return ret; +} + +int dbif_txn_begin(DBD *dbd) +{ + int ret; + + /* If we already have an active txn, just return */ + if (dbd->db_txn) + return 0; + + /* If our DBD has no env, just return (-> in memory db) */ + if (dbd->db_env == NULL) + return 0; + + ret = dbd->db_env->txn_begin(dbd->db_env, NULL, &dbd->db_txn, 0); + + if (ret) { + LOG(log_error, logtype_cnid, "error starting transaction: %s", db_strerror(ret)); + return -1; + } else + return 0; +} + +int dbif_txn_commit(DBD *dbd) +{ + int ret; + + if (! dbd->db_txn) + return 0; + + /* If our DBD has no env, just return (-> in memory db) */ + if (dbd->db_env == NULL) + return 0; + + ret = dbd->db_txn->commit(dbd->db_txn, 0); + dbd->db_txn = NULL; + + if (ret) { + LOG(log_error, logtype_cnid, "error committing transaction: %s", db_strerror(ret)); + return -1; + } else + return 1; +} + +int dbif_txn_abort(DBD *dbd) +{ + int ret; + + if (! dbd->db_txn) + return 0; + + /* If our DBD has no env, just return (-> in memory db) */ + if (dbd->db_env == NULL) + return 0; + + ret = dbd->db_txn->abort(dbd->db_txn); + dbd->db_txn = NULL; + + if (ret) { + LOG(log_error, logtype_cnid, "error aborting transaction: %s", db_strerror(ret)); + return -1; + } else + return 0; +} + +/* + ret = 1 -> commit txn if db_param.txn_frequency + ret = 0 -> abort txn db_param.txn_frequency -> exit! + anything else -> exit! + + @returns 0 on success (abort or commit), -1 on error +*/ +int dbif_txn_close(DBD *dbd, int ret) +{ + if (ret == 0) { + if (dbif_txn_abort(dbd) < 0) { + LOG( log_error, logtype_cnid, "Fatal error aborting transaction. Exiting!"); + return -1; + } + } else if (ret == 1) { + ret = dbif_txn_commit(dbd); + if ( ret < 0) { + LOG( log_error, logtype_cnid, "Fatal error committing transaction. Exiting!"); + return -1; + } + } else { + return -1; + } + + return 0; +} + +int dbif_txn_checkpoint(DBD *dbd, u_int32_t kbyte, u_int32_t min, u_int32_t flags) +{ + int ret; + ret = dbd->db_env->txn_checkpoint(dbd->db_env, kbyte, min, flags); + if (ret) { + LOG(log_error, logtype_cnid, "error checkpointing transaction susystem: %s", db_strerror(ret)); + return -1; + } else + return 0; +} + +int dbif_count(DBD *dbd, const int dbi, u_int32_t *count) +{ + int ret; + DB_BTREE_STAT *sp; + DB *db = dbd->db_table[dbi].db; + + ret = db->stat(db, NULL, &sp, 0); + + if (ret) { + LOG(log_error, logtype_cnid, "error getting stat infotmation on database: %s", db_strerror(ret)); + return -1; + } + + *count = sp->bt_ndata; + free(sp); + + return 0; +} + +int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd) +{ + DBT key, data; + int rc; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if ((rc = dbif_get(srcdbd, DBIF_CNID, &key, &data, 0)) <= 0) { + LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error getting rootinfo record"); + return -1; + } + + memset(&key, 0, sizeof(key)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if ((rc = dbif_put(destdbd, DBIF_CNID, &key, &data, 0))) { + LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error writing rootinfo key"); + return -1; + } + + return 0; +} + +int dbif_dump(DBD *dbd, int dumpindexes) +{ + int rc; + uint32_t max = 0, count = 0, cnid, type, did, lastid, version; + uint64_t dev, ino; + time_t stamp; + DBC *cur; + DBT key = { 0 }, data = { 0 }; + DB *db = dbd->db_table[DBIF_CNID].db; + char *typestring[2] = {"f", "d"}; + char timebuf[64]; + + printf("CNID database dump:\n"); + + rc = db->cursor(db, NULL, &cur, 0); + if (rc) { + LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(rc)); + return -1; + } + + cur->c_get(cur, &key, &data, DB_FIRST); + while (rc == 0) { + /* Parse and print data */ + memcpy(&cnid, key.data, 4); + cnid = ntohl(cnid); + if (cnid > max) + max = cnid; + + /* Rootinfo node ? */ + if (cnid == 0) { + memcpy(&stamp, (char *)data.data + CNID_DEV_OFS, sizeof(time_t)); + memcpy(&lastid, (char *)data.data + CNID_TYPE_OFS, CNID_TYPE_LEN); + lastid = ntohl(lastid); + memcpy(&version, (char *)data.data + CNID_DID_OFS, CNID_DID_LEN); + version = ntohl(version); + + strftime(timebuf, sizeof(timebuf), "%b %d %Y %H:%M:%S", localtime(&stamp)); + printf("CNID db version: %u, dbd stamp: 0x%08x (%s), next free CNID: %u\n", + version, (unsigned int)stamp, timebuf, lastid + 1); + } else { + /* dev */ + memcpy(&dev, (char *)data.data + CNID_DEV_OFS, 8); + dev = ntoh64(dev); + /* ino */ + memcpy(&ino, (char *)data.data + CNID_INO_OFS, 8); + ino = ntoh64(ino); + /* type */ + memcpy(&type, (char *)data.data + CNID_TYPE_OFS, 4); + type = ntohl(type); + /* did */ + memcpy(&did, (char *)data.data + CNID_DID_OFS, 4); + did = ntohl(did); + + count++; + printf("id: %10u, did: %10u, type: %s, dev: 0x%llx, ino: 0x%016llx, name: %s\n", + cnid, did, typestring[type], + (long long unsigned int)dev, (long long unsigned int)ino, + (char *)data.data + CNID_NAME_OFS); + + } + + rc = cur->c_get(cur, &key, &data, DB_NEXT); + } + + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_cnid, "Error iterating over btree: %s", db_strerror(rc)); + return -1; + } + + rc = cur->c_close(cur); + if (rc) { + LOG(log_error, logtype_cnid, "Couldn't close cursor: %s", db_strerror(rc)); + return -1; + } + printf("%u CNIDs in database. Max CNID: %u.\n", count, max); + + /* Dump indexes too ? */ + if (dumpindexes) { + /* DBIF_IDX_DEVINO */ + printf("\ndev/inode index:\n"); + count = 0; + db = dbd->db_table[DBIF_IDX_DEVINO].db; + rc = db->cursor(db, NULL, &cur, 0); + if (rc) { + LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(rc)); + return -1; + } + + cur->c_get(cur, &key, &data, DB_FIRST); + while (rc == 0) { + /* Parse and print data */ + + /* cnid */ + memcpy(&cnid, data.data, CNID_LEN); + cnid = ntohl(cnid); + if (cnid == 0) { + /* Rootinfo node */ + } else { + /* dev */ + memcpy(&dev, key.data, CNID_DEV_LEN); + dev = ntoh64(dev); + /* ino */ + memcpy(&ino, (char *)key.data + CNID_DEV_LEN, CNID_INO_LEN); + ino = ntoh64(ino); + + printf("id: %10u <== dev: 0x%llx, ino: 0x%016llx\n", + cnid, (unsigned long long int)dev, (unsigned long long int)ino); + count++; + } + rc = cur->c_get(cur, &key, &data, DB_NEXT); + } + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_cnid, "Error iterating over btree: %s", db_strerror(rc)); + return -1; + } + + rc = cur->c_close(cur); + if (rc) { + LOG(log_error, logtype_cnid, "Couldn't close cursor: %s", db_strerror(rc)); + return -1; + } + printf("%u items\n", count); + + /* Now dump DBIF_IDX_DIDNAME */ + printf("\ndid/name index:\n"); + count = 0; + db = dbd->db_table[DBIF_IDX_DIDNAME].db; + rc = db->cursor(db, NULL, &cur, 0); + if (rc) { + LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(rc)); + return -1; + } + + cur->c_get(cur, &key, &data, DB_FIRST); + while (rc == 0) { + /* Parse and print data */ + + /* cnid */ + memcpy(&cnid, data.data, CNID_LEN); + cnid = ntohl(cnid); + if (cnid == 0) { + /* Rootinfo node */ + } else { + /* did */ + memcpy(&did, key.data, CNID_LEN); + did = ntohl(did); + + printf("id: %10u <== did: %10u, name: %s\n", cnid, did, (char *)key.data + CNID_LEN); + count++; + } + rc = cur->c_get(cur, &key, &data, DB_NEXT); + } + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_cnid, "Error iterating over btree: %s", db_strerror(rc)); + return -1; + } + + rc = cur->c_close(cur); + if (rc) { + LOG(log_error, logtype_cnid, "Couldn't close cursor: %s", db_strerror(rc)); + return -1; + } + printf("%u items\n", count); + } + + return 0; +} + +/* + Iterates over dbd, returning cnids. + Uses in-value of cnid to seek to that cnid, then gets next and return that in cnid. + If close=1, close cursor. + Return -1 on error, 0 on EOD (end-of-database), 1 if returning cnid. +*/ +int dbif_idwalk(DBD *dbd, cnid_t *cnid, int close) +{ + int rc; + int flag; + cnid_t id; + + static DBT key = { 0 }, data = { 0 }; + DB *db = dbd->db_table[DBIF_CNID].db; + + if (close) { + if (dbd->db_cur) { + dbd->db_cur->close(dbd->db_cur); + dbd->db_cur = NULL; + } + return 0; + } + + /* An dbif_del will have closed our cursor too */ + if ( ! dbd->db_cur ) { + if ((rc = db->cursor(db, NULL, &dbd->db_cur, 0)) != 0) { + LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(rc)); + return -1; + } + flag = DB_SET_RANGE; /* This will seek to next cnid after the one just deleted */ + id = htonl(*cnid); + key.data = &id; + key.size = sizeof(cnid_t); + } else + flag = DB_NEXT; + + if ((rc = dbd->db_cur->get(dbd->db_cur, &key, &data, flag)) == 0) { + memcpy(cnid, key.data, sizeof(cnid_t)); + *cnid = ntohl(*cnid); + return 1; + } + + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_cnid, "Error iterating over btree: %s", db_strerror(rc)); + dbd->db_cur->close(dbd->db_cur); + dbd->db_cur = NULL; + return -1; + } + + if (dbd->db_cur) { + dbd->db_cur->close(dbd->db_cur); + dbd->db_cur = NULL; + } + + return 0; +} diff --git a/etc/cnid_dbd/dbif.h b/etc/cnid_dbd/dbif.h new file mode 100644 index 0000000..a6c88a9 --- /dev/null +++ b/etc/cnid_dbd/dbif.h @@ -0,0 +1,114 @@ +/* + Copyright (C) Joerg Lenneis 2003 + Copyright (C) Frank Lahm 2009 + All Rights Reserved. See COPYING. + + + API usage + ========= + + Initialisation + -------------- + 1. Provide storage for a DBD * handle + DBD *dbd; + 2. Call dbif_init with a filename to receive a DBD handle: + dbd = dbif_init("cnid2.db"); + Pass NULL to create an in-memory db. + Note: the DBD type is NOT from BerkeleyDB ! We've defined it. + 3. Call dbif_env_open to open an dbd environment if you called dbif_init + with a filename. Pass a db_param here for on-disk databases. + 4. Call dbif_open to finally open the CNID database itself. Pass db_param + here for in-memory database. + + Querying the CNID database + -------------------------- + Call dbif_[get|pget|put|del]. They map to the corresponding BerkeleyDB calls + with the same names. + + Transactions + ------------ + We use AUTO_COMMIT for the BDB database accesses. This avoids explicit transactions + for every bdb access which speeds up reads. But in order to be able to rollback + in case of errors we start a transaction once we encounter the first write from + dbif_put or dbif_del. + Thus you shouldn't call dbif_txn_[begin|abort|commit], they're used internally. + + Checkpoiting + ------------ + Call dbif_txn_checkpoint. + + Closing + ------- + Call dbif_close. + + Silent Upgrade Support + ---------------------- + + On cnid_dbd shutdown we reopen the environment with recovery, close and then + remove it. This enables an upgraded netatalk installation possibly linked against + a newer bdb lib to succesfully open/create an environment and then silently + upgrade the database itself. How nice! +*/ + +#ifndef CNID_DBD_DBIF_H +#define CNID_DBD_DBIF_H 1 + +#include +#include +#include "db_param.h" + +#define DBIF_DB_CNT 4 + +#define DBIF_CNID 0 +#define DBIF_IDX_DEVINO 1 +#define DBIF_IDX_DIDNAME 2 +#define DBIF_IDX_NAME 3 + +#define LOCKFILENAME "lock" +#define LOCK_FREE 0 +#define LOCK_UNLOCK 1 +#define LOCK_EXCL 2 +#define LOCK_SHRD 3 + +/* Structures */ +typedef struct { + char *name; + DB *db; + uint32_t flags; + uint32_t openflags; + DBTYPE type; +} db_table; + +typedef struct { + DB_ENV *db_env; + struct db_param db_param; + DB_TXN *db_txn; + DBC *db_cur; /* for dbif_walk */ + char *db_envhome; + char *db_filename; + FILE *db_errlog; + db_table db_table[DBIF_DB_CNT]; +} DBD; + +extern DBD *dbif_init(const char *envhome, const char *dbname); +extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags); +extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex); +extern int dbif_close(DBD *dbd); +extern int dbif_env_remove(const char *path); + +extern int dbif_get(DBD *, const int, DBT *, DBT *, u_int32_t); +extern int dbif_pget(DBD *, const int, DBT *, DBT *, DBT *, u_int32_t); +extern int dbif_put(DBD *, const int, DBT *, DBT *, u_int32_t); +extern int dbif_del(DBD *, const int, DBT *, u_int32_t); +extern int dbif_count(DBD *, const int, u_int32_t *); +extern int dbif_search(DBD *dbd, DBT *key, char *resbuf); +extern int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd); +extern int dbif_txn_begin(DBD *); +extern int dbif_txn_commit(DBD *); +extern int dbif_txn_abort(DBD *); +extern int dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */ +extern int dbif_txn_checkpoint(DBD *, u_int32_t, u_int32_t, u_int32_t); + +extern int dbif_dump(DBD *dbd, int dumpindexes); +extern int dbif_idwalk(DBD *dbd, cnid_t *cnid, int close); +#endif diff --git a/etc/cnid_dbd/main.c b/etc/cnid_dbd/main.c new file mode 100644 index 0000000..ddcf667 --- /dev/null +++ b/etc/cnid_dbd/main.c @@ -0,0 +1,598 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (c) Frank Lahm 2009 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "db_param.h" +#include "dbif.h" +#include "dbd.h" +#include "comm.h" +#include "pack.h" + +/* + Note: DB_INIT_LOCK is here so we can run the db_* utilities while netatalk is running. + It's a likey performance hit, but it might we worth it. + */ +#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN) + +static DBD *dbd; +static int exit_sig = 0; +static int db_locked; +static bstring dbpath; +static struct db_param *dbp; +static struct vol *vol; + +static void sig_exit(int signo) +{ + exit_sig = signo; + return; +} + +static void block_sigs_onoff(int block) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + if (block) + sigprocmask(SIG_BLOCK, &set, NULL); + else + sigprocmask(SIG_UNBLOCK, &set, NULL); + return; +} + +/* + The dbd_XXX and comm_XXX functions all obey the same protocol for return values: + + 1: Success, if transactions are used commit. + 0: Failure, but we continue to serve requests. If transactions are used abort/rollback. + -1: Fatal error, either from t + he database or from the socket. Abort the transaction if applicable + (which might fail as well) and then exit. + + We always try to notify the client process about the outcome, the result field + of the cnid_dbd_rply structure contains further details. + +*/ + +/*! + * Get lock on db lock file + * + * @args cmd (r) lock command: + * LOCK_FREE: close lockfd + * LOCK_UNLOCK: unlock lockm keep lockfd open + * LOCK_EXCL: F_WRLCK on lockfd + * LOCK_SHRD: F_RDLCK on lockfd + * @args dbpath (r) path to lockfile, only used on first call, + * later the stored fd is used + * @returns LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error + * LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on + * success, 0 if the lock couldn't be acquired, -1 on other errors + */ +static int get_lock(int cmd, const char *dbpath) +{ + static int lockfd = -1; + int ret; + char lockpath[PATH_MAX]; + struct stat st; + + LOG(log_debug, logtype_cnid, "get_lock(%s, \"%s\")", + cmd == LOCK_EXCL ? "LOCK_EXCL" : + cmd == LOCK_SHRD ? "LOCK_SHRD" : + cmd == LOCK_FREE ? "LOCK_FREE" : + cmd == LOCK_UNLOCK ? "LOCK_UNLOCK" : "UNKNOWN", + dbpath ? dbpath : ""); + + switch (cmd) { + case LOCK_FREE: + if (lockfd == -1) + return -1; + close(lockfd); + lockfd = -1; + return 0; + + case LOCK_UNLOCK: + if (lockfd == -1) + return -1; + return unlock(lockfd, 0, SEEK_SET, 0); + + case LOCK_EXCL: + case LOCK_SHRD: + if (lockfd == -1) { + if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) { + LOG(log_error, logtype_cnid, ".AppleDB pathname too long"); + return -1; + } + strncpy(lockpath, dbpath, PATH_MAX - 1); + strcat(lockpath, "/"); + strcat(lockpath, LOCKFILENAME); + + if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) { + LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno)); + return -1; + } + + if ((stat(dbpath, &st)) != 0) { + LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno)); + return -1; + } + + if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) { + LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s", + strerror(errno)); + return -1; + } + } + + if (cmd == LOCK_EXCL) + ret = write_lock(lockfd, 0, SEEK_SET, 0); + else + ret = read_lock(lockfd, 0, SEEK_SET, 0); + + if (ret != 0) { + if (cmd == LOCK_SHRD) + LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again..."); + return 0; + } + + LOG(log_debug, logtype_cnid, "get_lock: got %s lock", + cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD"); + return cmd; + + default: + return -1; + } /* switch(cmd) */ + + /* deadc0de, never get here */ + return -1; +} + +static int open_db(void) +{ + EC_INIT; + + /* Get db lock */ + if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) { + LOG(log_error, logtype_cnid, "main: fatal db lock error"); + EC_FAIL; + } + + if (NULL == (dbd = dbif_init(bdata(dbpath), "cnid2.db"))) + EC_FAIL; + + /* Only recover if we got the lock */ + if (dbif_env_open(dbd, dbp, DBOPTIONS | DB_RECOVER) < 0) + EC_FAIL; + + LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment"); + + if (dbif_open(dbd, dbp, 0) < 0) + EC_FAIL; + + LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases"); + +EC_CLEANUP: + if (ret != 0) { + if (dbd) { + (void)dbif_close(dbd); + dbd = NULL; + } + } + + EC_EXIT; +} + +static int delete_db(void) +{ + EC_INIT; + int cwd = -1; + + EC_ZERO( get_lock(LOCK_FREE, bdata(dbpath)) ); + EC_NEG1( cwd = open(".", O_RDONLY) ); + chdir(cfrombstr(dbpath)); + system("rm -f cnid2.db lock log.* __db.*"); + + if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) { + LOG(log_error, logtype_cnid, "main: fatal db lock error"); + EC_FAIL; + } + + LOG(log_warning, logtype_cnid, "Recreated CNID BerkeleyDB databases of volume \"%s\"", vol->v_localname); + +EC_CLEANUP: + if (cwd != -1) { + fchdir(cwd); + close(cwd); + } + EC_EXIT; +} + + +/** + * Close dbd if open, delete it, reopen + * + * Also tries to copy the rootinfo key, that would allow for keeping the db stamp + * and last used CNID + **/ +static int reinit_db(void) +{ + EC_INIT; + DBT key, data; + bool copyRootInfo = false; + + if (dbd) { + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) <= 0) { + LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error getting rootinfo record"); + copyRootInfo = false; + } else { + copyRootInfo = true; + } + (void)dbif_close(dbd); + } + + EC_ZERO_LOG( delete_db() ); + EC_ZERO_LOG( open_db() ); + + if (copyRootInfo == true) { + memset(&key, 0, sizeof(key)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) != 0) { + LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error writing rootinfo key"); + EC_FAIL; + } + } + +EC_CLEANUP: + EC_EXIT; +} + +static int loop(struct db_param *dbp) +{ + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + time_t timeout; + int ret, cret; + int count; + time_t now, time_next_flush, time_last_rqst; + char timebuf[64]; + static char namebuf[MAXPATHLEN + 1]; + sigset_t set; + + sigemptyset(&set); + sigprocmask(SIG_SETMASK, NULL, &set); + sigdelset(&set, SIGINT); + sigdelset(&set, SIGTERM); + + count = 0; + now = time(NULL); + time_next_flush = now + dbp->flush_interval; + time_last_rqst = now; + + rqst.name = namebuf; + + strftime(timebuf, 63, "%b %d %H:%M:%S.",localtime(&time_next_flush)); + LOG(log_debug, logtype_cnid, "Checkpoint interval: %d seconds. Next checkpoint: %s", + dbp->flush_interval, timebuf); + + while (1) { + timeout = MIN(time_next_flush, time_last_rqst + dbp->idle_timeout); + if (timeout > now) + timeout -= now; + else + timeout = 1; + + if ((cret = comm_rcv(&rqst, timeout, &set, &now)) < 0) + return -1; + + if (cret == 0) { + /* comm_rcv returned from select without receiving anything. */ + if (exit_sig) { + /* Received signal (TERM|INT) */ + return 0; + } + if (now - time_last_rqst >= dbp->idle_timeout && comm_nbe() <= 0) { + /* Idle timeout */ + return 0; + } + /* still active connections, reset time_last_rqst */ + time_last_rqst = now; + } else { + /* We got a request */ + time_last_rqst = now; + + memset(&rply, 0, sizeof(rply)); + switch(rqst.op) { + /* ret gets set here */ + case CNID_DBD_OP_OPEN: + case CNID_DBD_OP_CLOSE: + /* open/close are noops for now. */ + rply.namelen = 0; + ret = 1; + break; + case CNID_DBD_OP_ADD: + ret = dbd_add(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_GET: + ret = dbd_get(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_RESOLVE: + ret = dbd_resolve(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_LOOKUP: + ret = dbd_lookup(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_UPDATE: + ret = dbd_update(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_DELETE: + ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID); + break; + case CNID_DBD_OP_GETSTAMP: + ret = dbd_getstamp(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_REBUILD_ADD: + ret = dbd_rebuild_add(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_SEARCH: + ret = dbd_search(dbd, &rqst, &rply); + break; + case CNID_DBD_OP_WIPE: + ret = reinit_db(); + break; + default: + LOG(log_error, logtype_cnid, "loop: unknown op %d", rqst.op); + ret = -1; + break; + } + + if ((cret = comm_snd(&rply)) < 0 || ret < 0) { + dbif_txn_abort(dbd); + return -1; + } + + if (ret == 0 || cret == 0) { + if (dbif_txn_abort(dbd) < 0) + return -1; + } else { + ret = dbif_txn_commit(dbd); + if ( ret < 0) + return -1; + else if ( ret > 0 ) + /* We had a designated txn because we wrote to the db */ + count++; + } + } /* got a request */ + + /* + Shall we checkpoint bdb ? + "flush_interval" seconds passed ? + */ + if (now >= time_next_flush) { + LOG(log_info, logtype_cnid, "Checkpointing BerkeleyDB for volume '%s'", dbp->dir); + if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) + return -1; + count = 0; + time_next_flush = now + dbp->flush_interval; + + strftime(timebuf, 63, "%b %d %H:%M:%S.",localtime(&time_next_flush)); + LOG(log_debug, logtype_cnid, "Checkpoint interval: %d seconds. Next checkpoint: %s", + dbp->flush_interval, timebuf); + } + + /* + Shall we checkpoint bdb ? + Have we commited "count" more changes than "flush_frequency" ? + */ + if (count > dbp->flush_frequency) { + LOG(log_info, logtype_cnid, "Checkpointing BerkeleyDB after %d writes for volume '%s'", count, dbp->dir); + if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) + return -1; + count = 0; + } + } /* while(1) */ +} + +/* ------------------------ */ +static void switch_to_user(char *dir) +{ + struct stat st; + + if (chdir(dir) < 0) { + LOG(log_error, logtype_cnid, "chdir to %s failed: %s", dir, strerror(errno)); + exit(1); + } + + if (stat(".", &st) < 0) { + LOG(log_error, logtype_cnid, "error in stat for %s: %s", dir, strerror(errno)); + exit(1); + } + if (!getuid()) { + LOG(log_debug, logtype_cnid, "Setting uid/gid to %i/%i", st.st_uid, st.st_gid); + if (setgid(st.st_gid) < 0 || setuid(st.st_uid) < 0) { + LOG(log_error, logtype_cnid, "uid/gid: %s", strerror(errno)); + exit(1); + } + } +} + + +/* ----------------------- */ +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_exit; + sv.sa_flags = 0; + sigemptyset(&sv.sa_mask); + sigaddset(&sv.sa_mask, SIGINT); + sigaddset(&sv.sa_mask, SIGTERM); + if (sigaction(SIGINT, &sv, NULL) < 0 || sigaction(SIGTERM, &sv, NULL) < 0) { + LOG(log_error, logtype_cnid, "main: sigaction: %s", strerror(errno)); + exit(1); + } + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGPIPE, &sv, NULL) < 0) { + LOG(log_error, logtype_cnid, "main: sigaction: %s", strerror(errno)); + exit(1); + } +} + +static uid_t uid_from_name(const char *name) +{ + struct passwd *pwd; + + pwd = getpwnam(name); + if (pwd == NULL) + return 0; + return pwd->pw_uid; +} + +/* ------------------------ */ +int main(int argc, char *argv[]) +{ + EC_INIT; + int delete_bdb = 0; + int ctrlfd = -1, clntfd = -1; + AFPObj obj = { 0 }; + char *volpath = NULL; + char *username = NULL; + + while (( ret = getopt( argc, argv, ":dF:l:p:t:u:vV")) != -1 ) { + switch (ret) { + case 'd': + /* this is now just ignored, as we do it automatically anyway */ + delete_bdb = 1; + break; + case 'F': + obj.cmdlineconfigfile = strdup(optarg); + break; + case 'p': + volpath = strdup(optarg); + break; + case 'l': + clntfd = atoi(optarg); + break; + case 't': + ctrlfd = atoi(optarg); + break; + case 'u': + username = strdup(optarg); + break; + case 'v': + case 'V': + printf("cnid_dbd (Netatalk %s)\n", VERSION); + return -1; + case ':': + break; + } + } + + if (ctrlfd == -1 || clntfd == -1 || !volpath) { + LOG(log_error, logtype_cnid, "main: bad IPC fds"); + exit(EXIT_FAILURE); + } + + EC_ZERO( afp_config_parse(&obj, "cnid_dbd") ); + + if (username) { + strlcpy(obj.username, username, MAXUSERLEN); + obj.uid = uid_from_name(username); + if (!obj.uid) { + EC_FAIL_LOG("unknown user: '%s'", username); + } + } + + LOG(log_debug, logtype_cnid, "user: %s, path %s", + username ? username : "-", volpath); + + EC_ZERO( load_volumes(&obj, lv_all) ); + EC_NULL( vol = getvolbypath(&obj, volpath) ); + EC_ZERO( load_charset(vol) ); + pack_setvol(vol); + + EC_NULL( dbpath = bfromcstr(vol->v_dbpath) ); + EC_ZERO( bcatcstr(dbpath, "/.AppleDB") ); + + LOG(log_debug, logtype_cnid, "db dir: \"%s\"", bdata(dbpath)); + + switch_to_user(bdata(dbpath)); + + set_signal(); + + /* SIGINT and SIGTERM are always off, unless we are in pselect */ + block_sigs_onoff(1); + + if ((dbp = db_param_read(bdata(dbpath))) == NULL) + EC_FAIL; + LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file"); + + if (open_db() != 0) { + LOG(log_error, logtype_cnid, "Failed to open CNID database for volume \"%s\"", vol->v_localname); + EC_ZERO_LOG( reinit_db() ); + } + + if (comm_init(dbp, ctrlfd, clntfd) < 0) { + ret = -1; + goto close_db; + } + + if (loop(dbp) < 0) { + ret = -1; + goto close_db; + } + +close_db: + if (dbif_close(dbd) < 0) + ret = -1; + + if (dbif_env_remove(bdata(dbpath)) < 0) + ret = -1; + +EC_CLEANUP: + if (ret != 0) + exit(1); + + if (exit_sig) + LOG(log_info, logtype_cnid, "main: Exiting on signal %i", exit_sig); + else + LOG(log_info, logtype_cnid, "main: Idle timeout, exiting"); + + EC_EXIT; +} diff --git a/etc/cnid_dbd/pack.c b/etc/cnid_dbd/pack.c new file mode 100644 index 0000000..dc61dde --- /dev/null +++ b/etc/cnid_dbd/pack.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "pack.h" + +static const struct vol *volume; + +/* --------------- */ +/* + * This implementation is portable, but could probably be faster by using htonl + * where appropriate. Also, this again doubles code from the cdb backend. + */ +static void pack_devino(unsigned char *buf, dev_t dev, ino_t ino) +{ + buf[CNID_DEV_LEN - 1] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 2] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 3] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 4] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 5] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 6] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 7] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 8] = dev; + + buf[CNID_DEV_LEN + CNID_INO_LEN - 1] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 2] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 3] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 4] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 5] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 6] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 7] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 8] = ino; +} + +/* --------------- */ +int didname(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) +{ +int len; + + memset(skey, 0, sizeof(DBT)); + skey->data = (char *)pdata->data + CNID_DID_OFS; + /* FIXME: At least DB 4.0.14 and 4.1.25 pass in the correct length of + pdata.size. strlen is therefore not needed. Also, skey should be zeroed + out already. */ + len = strlen((char *)skey->data + CNID_DID_LEN); + skey->size = CNID_DID_LEN + len + 1; + return (0); +} + +/* --------------- */ +int devino(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) +{ + memset(skey, 0, sizeof(DBT)); + skey->data = (char *)pdata->data + CNID_DEVINO_OFS; + skey->size = CNID_DEVINO_LEN; + return (0); +} + +/* --------------- */ +int idxname(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) +{ + static char buffer[MAXPATHLEN +2]; + uint16_t flags = CONV_TOLOWER; + memset(skey, 0, sizeof(DBT)); + + if (convert_charset(volume->v_volcharset, + volume->v_volcharset, + volume->v_maccharset, + (char *)pdata->data + CNID_NAME_OFS, + strlen((char *)pdata->data + CNID_NAME_OFS), + buffer, + MAXPATHLEN, + &flags) == (size_t)-1) { + LOG(log_error, logtype_cnid, "idxname: conversion error"); + } + + skey->data = buffer; + skey->size = strlen(skey->data); + return (0); +} + +void pack_setvol(const struct vol *vol) +{ + volume = vol; +} + +/* The equivalent to make_cnid_data in the cnid library. Non re-entrant. We + differ from make_cnid_data in that we never return NULL, rqst->name cannot + ever cause start[] to overflow because name length is checked in libatalk. */ + +unsigned char *pack_cnid_data(struct cnid_dbd_rqst *rqst) +{ + static unsigned char start[CNID_HEADER_LEN + MAXPATHLEN + 1]; + unsigned char *buf = start +CNID_LEN; + u_int32_t i; + + pack_devino(buf, rqst->dev, rqst->ino); + buf += CNID_DEVINO_LEN; + + i = htonl(rqst->type); + memcpy(buf, &i, sizeof(i)); + buf += sizeof(i); + + /* did is already in network byte order */ + buf = memcpy(buf, &rqst->did, sizeof(rqst->did)); + buf += sizeof(rqst->did); + buf = memcpy(buf, rqst->name, rqst->namelen); + *(buf + rqst->namelen) = '\0'; + + return start; +} + diff --git a/etc/cnid_dbd/pack.h b/etc/cnid_dbd/pack.h new file mode 100644 index 0000000..5566bea --- /dev/null +++ b/etc/cnid_dbd/pack.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 + * All Rights Reserved. See COPYING. + */ + +#ifndef CNID_DBD_PACK_H +#define CNID_DBD_PACK_H 1 + +#include +#include + +extern unsigned char *pack_cnid_data(struct cnid_dbd_rqst *); +extern int didname(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey); +extern int devino(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey); +extern int idxname(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey); +extern void pack_setvol(const struct vol *vol); +#endif /* CNID_DBD_PACK_H */ diff --git a/etc/cnid_dbd/usockfd.c b/etc/cnid_dbd/usockfd.c new file mode 100644 index 0000000..269c657 --- /dev/null +++ b/etc/cnid_dbd/usockfd.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "usockfd.h" + +#include + +int usockfd_create(char *usock_fn, mode_t mode, int backlog) +{ + int sockfd; + struct sockaddr_un addr; + + + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + LOG(log_error, logtype_cnid, "error in socket call: %s", + strerror(errno)); + return -1; + } + + if (unlink(usock_fn) < 0 && errno != ENOENT) { + LOG(log_error, logtype_cnid, "error unlinking unix socket file %s: %s", + usock_fn, strerror(errno)); + return -1; + } + memset((char *) &addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, usock_fn, sizeof(addr.sun_path) - 1); + if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) < 0) { + LOG(log_error, logtype_cnid, "error binding to socket for %s: %s", + usock_fn, strerror(errno)); + return -1; + } + + if (listen(sockfd, backlog) < 0) { + LOG(log_error, logtype_cnid, "error in listen for %s: %s", + usock_fn, strerror(errno)); + return -1; + } + +#ifdef chmod +#undef chmod +#endif + if (chmod(usock_fn, mode) < 0) { + LOG(log_error, logtype_cnid, "error changing permissions for %s: %s", + usock_fn, strerror(errno)); + close(sockfd); + return -1; + } + + return sockfd; +} + +/* --------------- + * create a tcp socket + */ +int tsockfd_create(char *host, char *port, int backlog) +{ + int sockfd, flag, ret; + struct addrinfo hints, *servinfo, *p; + + /* Prepare hint for getaddrinfo */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ((ret = getaddrinfo(host, port, &hints, &servinfo)) != 0) { + LOG(log_error, logtype_cnid, "tsockfd_create: getaddrinfo: %s\n", gai_strerror(ret)); + return -1; + } + + /* create a socket */ + /* loop through all the results and bind to the first we can */ + for (p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + LOG(log_info, logtype_cnid, "tsockfd_create: socket: %s", strerror(errno)); + continue; + } + + /* + * Set some socket options: + * SO_REUSEADDR deals w/ quick close/opens + * TCP_NODELAY diables Nagle + */ +#ifdef SO_REUSEADDR + flag = 1; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); +#endif + +#ifdef USE_TCP_NODELAY +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + flag = 1; + setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag)); +#endif /* USE_TCP_NODELAY */ + + if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + close(sockfd); + LOG(log_info, logtype_cnid, "tsockfd_create: bind: %s\n", strerror(errno)); + continue; + } + + if (listen(sockfd, backlog) < 0) { + close(sockfd); + LOG(log_info, logtype_cnid, "tsockfd_create: listen: %s\n", strerror(errno)); + continue; + } + + /* We got a socket */ + break; + } + + if (p == NULL) { + LOG(log_error, logtype_cnid, "tsockfd_create: no suitable network config %s:%s", host, port); + freeaddrinfo(servinfo); + return -1; + } + + freeaddrinfo(servinfo); + return sockfd; +} + +/* --------------------- */ +int usockfd_check(int sockfd, const sigset_t *sigset) +{ + int fd; + socklen_t size; + fd_set readfds; + int ret; + + FD_ZERO(&readfds); + FD_SET(sockfd, &readfds); + + if ((ret = pselect(sockfd + 1, &readfds, NULL, NULL, NULL, sigset)) < 0) { + if (errno == EINTR) + return 0; + LOG(log_error, logtype_cnid, "error in select: %s", + strerror(errno)); + return -1; + } + + if (ret) { + size = 0; + if ((fd = accept(sockfd, NULL, &size)) < 0) { + if (errno == EINTR) + return 0; + LOG(log_error, logtype_cnid, "error in accept: %s", + strerror(errno)); + return -1; + } + return fd; + } else + return 0; +} diff --git a/etc/cnid_dbd/usockfd.h b/etc/cnid_dbd/usockfd.h new file mode 100644 index 0000000..44f01ae --- /dev/null +++ b/etc/cnid_dbd/usockfd.h @@ -0,0 +1,41 @@ +/* + * + * Copyright (C) Joerg Lenneis 2003 + * All Rights Reserved. See COPYING. + */ + +#ifndef CNID_DBD_USOCKFD_H +#define CNID_DBD_USOCKFD_H 1 + + + +#include + + +extern int usockfd_create (char *, mode_t, int); +extern int tsockfd_create (char *, char *, int); +extern int usockfd_check (int, const sigset_t *); + +#ifndef OSSH_ALIGNBYTES +#define OSSH_ALIGNBYTES (sizeof(int) - 1) +#endif +#ifndef __CMSG_ALIGN +#ifndef u_int +#define u_int unsigned int +#endif +#define __CMSG_ALIGN(p) (((u_int)(p) + OSSH_ALIGNBYTES) &~ OSSH_ALIGNBYTES) +#endif + +/* Length of the contents of a control message of length len */ +#ifndef CMSG_LEN +#define CMSG_LEN(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) +#endif + +/* Length of the space taken up by a padded control message of length len */ +#ifndef CMSG_SPACE +#define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len)) +#endif + + + +#endif /* CNID_DBD_USOCKFD_H */ diff --git a/etc/netatalk/Makefile.am b/etc/netatalk/Makefile.am new file mode 100644 index 0000000..5392b9d --- /dev/null +++ b/etc/netatalk/Makefile.am @@ -0,0 +1,34 @@ +# Makefile.am for etc/netatlk/ + +pkgconfdir = @PKGCONFDIR@ + +sbin_PROGRAMS = netatalk + +netatalk_SOURCES = netatalk.c afp_avahi.c afp_mdns.c afp_zeroconf.c +netatalk_CFLAGS = \ + @ZEROCONF_CFLAGS@ \ + -D_PATH_CONFDIR=\"$(pkgconfdir)/\" \ + -D_PATH_STATEDIR='"$(localstatedir)/netatalk/"' \ + -D_PATH_AFPD=\"$(sbindir)/afpd\" \ + -D_PATH_CNID_METAD=\"$(sbindir)/cnid_metad\" + +netatalk_LDADD = \ + @MYSQL_LIBS@ \ + @ZEROCONF_LIBS@ \ + $(top_builddir)/libatalk/libatalk.la + +netatalk_LDFLAGS = + +if USE_BUILTIN_LIBEVENT +netatalk_CFLAGS += \ + -I$(top_srcdir)/libevent/include \ + -I$(top_builddir)/libevent/include + +netatalk_LDADD += \ + $(top_builddir)/libevent/libevent.la +else +netatalk_CFLAGS += @LIBEVENT_CFLAGS@ +netatalk_LDFLAGS += @LIBEVENT_LDFLAGS@ -levent +endif + +noinst_HEADERS = afp_zeroconf.h afp_avahi.h afp_mdns.h diff --git a/etc/netatalk/Makefile.in b/etc/netatalk/Makefile.in new file mode 100644 index 0000000..b148b8f --- /dev/null +++ b/etc/netatalk/Makefile.in @@ -0,0 +1,787 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for etc/netatlk/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +sbin_PROGRAMS = netatalk$(EXEEXT) +@USE_BUILTIN_LIBEVENT_TRUE@am__append_1 = \ +@USE_BUILTIN_LIBEVENT_TRUE@ -I$(top_srcdir)/libevent/include \ +@USE_BUILTIN_LIBEVENT_TRUE@ -I$(top_builddir)/libevent/include + +@USE_BUILTIN_LIBEVENT_TRUE@am__append_2 = \ +@USE_BUILTIN_LIBEVENT_TRUE@ $(top_builddir)/libevent/libevent.la + +@USE_BUILTIN_LIBEVENT_FALSE@am__append_3 = @LIBEVENT_CFLAGS@ +@USE_BUILTIN_LIBEVENT_FALSE@am__append_4 = @LIBEVENT_LDFLAGS@ -levent +subdir = etc/netatalk +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(sbin_PROGRAMS) +am_netatalk_OBJECTS = netatalk-netatalk.$(OBJEXT) \ + netatalk-afp_avahi.$(OBJEXT) netatalk-afp_mdns.$(OBJEXT) \ + netatalk-afp_zeroconf.$(OBJEXT) +netatalk_OBJECTS = $(am_netatalk_OBJECTS) +netatalk_DEPENDENCIES = $(top_builddir)/libatalk/libatalk.la \ + $(am__append_2) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +netatalk_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(netatalk_CFLAGS) \ + $(CFLAGS) $(netatalk_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(netatalk_SOURCES) +DIST_SOURCES = $(netatalk_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgconfdir = @PKGCONFDIR@ +netatalk_SOURCES = netatalk.c afp_avahi.c afp_mdns.c afp_zeroconf.c +netatalk_CFLAGS = @ZEROCONF_CFLAGS@ -D_PATH_CONFDIR=\"$(pkgconfdir)/\" \ + -D_PATH_STATEDIR='"$(localstatedir)/netatalk/"' \ + -D_PATH_AFPD=\"$(sbindir)/afpd\" \ + -D_PATH_CNID_METAD=\"$(sbindir)/cnid_metad\" $(am__append_1) \ + $(am__append_3) +netatalk_LDADD = @MYSQL_LIBS@ @ZEROCONF_LIBS@ \ + $(top_builddir)/libatalk/libatalk.la $(am__append_2) +netatalk_LDFLAGS = $(am__append_4) +noinst_HEADERS = afp_zeroconf.h afp_avahi.h afp_mdns.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign etc/netatalk/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign etc/netatalk/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +netatalk$(EXEEXT): $(netatalk_OBJECTS) $(netatalk_DEPENDENCIES) $(EXTRA_netatalk_DEPENDENCIES) + @rm -f netatalk$(EXEEXT) + $(AM_V_CCLD)$(netatalk_LINK) $(netatalk_OBJECTS) $(netatalk_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netatalk-afp_avahi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netatalk-afp_mdns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netatalk-afp_zeroconf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netatalk-netatalk.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +netatalk-netatalk.o: netatalk.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-netatalk.o -MD -MP -MF $(DEPDIR)/netatalk-netatalk.Tpo -c -o netatalk-netatalk.o `test -f 'netatalk.c' || echo '$(srcdir)/'`netatalk.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-netatalk.Tpo $(DEPDIR)/netatalk-netatalk.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netatalk.c' object='netatalk-netatalk.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-netatalk.o `test -f 'netatalk.c' || echo '$(srcdir)/'`netatalk.c + +netatalk-netatalk.obj: netatalk.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-netatalk.obj -MD -MP -MF $(DEPDIR)/netatalk-netatalk.Tpo -c -o netatalk-netatalk.obj `if test -f 'netatalk.c'; then $(CYGPATH_W) 'netatalk.c'; else $(CYGPATH_W) '$(srcdir)/netatalk.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-netatalk.Tpo $(DEPDIR)/netatalk-netatalk.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netatalk.c' object='netatalk-netatalk.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-netatalk.obj `if test -f 'netatalk.c'; then $(CYGPATH_W) 'netatalk.c'; else $(CYGPATH_W) '$(srcdir)/netatalk.c'; fi` + +netatalk-afp_avahi.o: afp_avahi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-afp_avahi.o -MD -MP -MF $(DEPDIR)/netatalk-afp_avahi.Tpo -c -o netatalk-afp_avahi.o `test -f 'afp_avahi.c' || echo '$(srcdir)/'`afp_avahi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-afp_avahi.Tpo $(DEPDIR)/netatalk-afp_avahi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_avahi.c' object='netatalk-afp_avahi.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-afp_avahi.o `test -f 'afp_avahi.c' || echo '$(srcdir)/'`afp_avahi.c + +netatalk-afp_avahi.obj: afp_avahi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-afp_avahi.obj -MD -MP -MF $(DEPDIR)/netatalk-afp_avahi.Tpo -c -o netatalk-afp_avahi.obj `if test -f 'afp_avahi.c'; then $(CYGPATH_W) 'afp_avahi.c'; else $(CYGPATH_W) '$(srcdir)/afp_avahi.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-afp_avahi.Tpo $(DEPDIR)/netatalk-afp_avahi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_avahi.c' object='netatalk-afp_avahi.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-afp_avahi.obj `if test -f 'afp_avahi.c'; then $(CYGPATH_W) 'afp_avahi.c'; else $(CYGPATH_W) '$(srcdir)/afp_avahi.c'; fi` + +netatalk-afp_mdns.o: afp_mdns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-afp_mdns.o -MD -MP -MF $(DEPDIR)/netatalk-afp_mdns.Tpo -c -o netatalk-afp_mdns.o `test -f 'afp_mdns.c' || echo '$(srcdir)/'`afp_mdns.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-afp_mdns.Tpo $(DEPDIR)/netatalk-afp_mdns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_mdns.c' object='netatalk-afp_mdns.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-afp_mdns.o `test -f 'afp_mdns.c' || echo '$(srcdir)/'`afp_mdns.c + +netatalk-afp_mdns.obj: afp_mdns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-afp_mdns.obj -MD -MP -MF $(DEPDIR)/netatalk-afp_mdns.Tpo -c -o netatalk-afp_mdns.obj `if test -f 'afp_mdns.c'; then $(CYGPATH_W) 'afp_mdns.c'; else $(CYGPATH_W) '$(srcdir)/afp_mdns.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-afp_mdns.Tpo $(DEPDIR)/netatalk-afp_mdns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_mdns.c' object='netatalk-afp_mdns.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-afp_mdns.obj `if test -f 'afp_mdns.c'; then $(CYGPATH_W) 'afp_mdns.c'; else $(CYGPATH_W) '$(srcdir)/afp_mdns.c'; fi` + +netatalk-afp_zeroconf.o: afp_zeroconf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-afp_zeroconf.o -MD -MP -MF $(DEPDIR)/netatalk-afp_zeroconf.Tpo -c -o netatalk-afp_zeroconf.o `test -f 'afp_zeroconf.c' || echo '$(srcdir)/'`afp_zeroconf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-afp_zeroconf.Tpo $(DEPDIR)/netatalk-afp_zeroconf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_zeroconf.c' object='netatalk-afp_zeroconf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-afp_zeroconf.o `test -f 'afp_zeroconf.c' || echo '$(srcdir)/'`afp_zeroconf.c + +netatalk-afp_zeroconf.obj: afp_zeroconf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -MT netatalk-afp_zeroconf.obj -MD -MP -MF $(DEPDIR)/netatalk-afp_zeroconf.Tpo -c -o netatalk-afp_zeroconf.obj `if test -f 'afp_zeroconf.c'; then $(CYGPATH_W) 'afp_zeroconf.c'; else $(CYGPATH_W) '$(srcdir)/afp_zeroconf.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netatalk-afp_zeroconf.Tpo $(DEPDIR)/netatalk-afp_zeroconf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='afp_zeroconf.c' object='netatalk-afp_zeroconf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netatalk_CFLAGS) $(CFLAGS) -c -o netatalk-afp_zeroconf.obj `if test -f 'afp_zeroconf.c'; then $(CYGPATH_W) 'afp_zeroconf.c'; else $(CYGPATH_W) '$(srcdir)/afp_zeroconf.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-sbinPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-sbinPROGRAMS + + +# 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/etc/netatalk/afp_avahi.c b/etc/netatalk/afp_avahi.c new file mode 100644 index 0000000..d6b55dc --- /dev/null +++ b/etc/netatalk/afp_avahi.c @@ -0,0 +1,335 @@ +/* + * Author: Daniel S. Haischt + * Purpose: Avahi based Zeroconf support + * Docs: http://avahi.org/download/doxygen/ + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_AVAHI + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "afp_zeroconf.h" +#include "afp_avahi.h" + +/***************************************************************** + * Global variables + *****************************************************************/ +struct context *ctx = NULL; + +/***************************************************************** + * Private functions + *****************************************************************/ + +static void publish_reply(AvahiEntryGroup *g, + AvahiEntryGroupState state, + void *userdata); + +/* + * This function tries to register the AFP DNS + * SRV service type. + */ +static void register_stuff(void) { + uint port; + const struct vol *volume; + char name[MAXINSTANCENAMELEN+1]; + AvahiStringList *strlist = NULL; + AvahiStringList *strlist2 = NULL; + char tmpname[256]; + + assert(ctx->client); + + if (!ctx->group) { + if (!(ctx->group = avahi_entry_group_new(ctx->client, publish_reply, ctx))) { + LOG(log_error, logtype_afpd, "Failed to create entry group: %s", + avahi_strerror(avahi_client_errno(ctx->client))); + goto fail; + } + } + + if (avahi_entry_group_is_empty(ctx->group)) { + /* Register our service */ + + /* Build AFP volumes list */ + int i = 0; + strlist = avahi_string_list_add_printf(strlist, "sys=waMa=0,adVF=0x100"); + + for (volume = getvolumes(); volume; volume = volume->v_next) { + + if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, -1, tmpname, 255) <= 0) { + LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine"); + goto fail; + } + + if (volume->v_flags & AFPVOL_TM) { + if (volume->v_uuid) { + LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine", + volume->v_localname, volume->v_uuid); + strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1,adVU=%s", + i++, tmpname, volume->v_uuid); + } else { + LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.", + volume->v_localname); + strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1", + i++, tmpname); + } + } + } + + port = atoi(ctx->obj->options.port); + + LOG(log_info, logtype_afpd, "hostname: %s", ctx->obj->options.hostname); + + if (convert_string(ctx->obj->options.unixcharset, + CH_UTF8, + ctx->obj->options.hostname, + -1, + name, + MAXINSTANCENAMELEN) <= 0) { + LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name: %s", ctx->obj->options.hostname); + goto fail; + } + + LOG(log_info, logtype_afpd, "Registering server '%s' with Bonjour", name); + + if (avahi_entry_group_add_service(ctx->group, + AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + 0, + name, + AFP_DNS_SERVICE_TYPE, + NULL, + NULL, + port, + NULL) < 0) { + LOG(log_error, logtype_afpd, "Failed to add service: %s", + avahi_strerror(avahi_client_errno(ctx->client))); + goto fail; + } + + if (i && avahi_entry_group_add_service_strlst(ctx->group, + AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + 0, + name, + ADISK_SERVICE_TYPE, + NULL, + NULL, + 9, /* discard */ + strlist) < 0) { + LOG(log_error, logtype_afpd, "Failed to add service: %s", + avahi_strerror(avahi_client_errno(ctx->client))); + goto fail; + } /* if */ + + if (ctx->obj->options.mimicmodel) { + strlist2 = avahi_string_list_add_printf(strlist2, "model=%s", ctx->obj->options.mimicmodel); + if (avahi_entry_group_add_service_strlst(ctx->group, + AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + 0, + name, + DEV_INFO_SERVICE_TYPE, + NULL, + NULL, + 0, + strlist2) < 0) { + LOG(log_error, logtype_afpd, "Failed to add service: %s", + avahi_strerror(avahi_client_errno(ctx->client))); + goto fail; + } + } /* if (config->obj.options.mimicmodel) */ + + if (avahi_entry_group_commit(ctx->group) < 0) { + LOG(log_error, logtype_afpd, "Failed to commit entry group: %s", + avahi_strerror(avahi_client_errno(ctx->client))); + goto fail; + } + + } /* if avahi_entry_group_is_empty*/ + + return; + +fail: + time(NULL); +// avahi_threaded_poll_quit(ctx->threaded_poll); +} + +/* Called when publishing of service data completes */ +static void publish_reply(AvahiEntryGroup *g, + AvahiEntryGroupState state, + AVAHI_GCC_UNUSED void *userdata) +{ + assert(ctx->group == NULL || g == ctx->group); + + switch (state) { + + case AVAHI_ENTRY_GROUP_ESTABLISHED : + /* The entry group has been established successfully */ + LOG(log_debug, logtype_afpd, "publish_reply: AVAHI_ENTRY_GROUP_ESTABLISHED"); + break; + + case AVAHI_ENTRY_GROUP_COLLISION: + /* With multiple names there's no way to know which one collided */ + LOG(log_error, logtype_afpd, "publish_reply: AVAHI_ENTRY_GROUP_COLLISION", + avahi_strerror(avahi_client_errno(ctx->client))); + avahi_threaded_poll_quit(ctx->threaded_poll); + break; + + case AVAHI_ENTRY_GROUP_FAILURE: + LOG(log_error, logtype_afpd, "Failed to register service: %s", + avahi_strerror(avahi_client_errno(ctx->client))); + avahi_threaded_poll_quit(ctx->threaded_poll); + break; + + case AVAHI_ENTRY_GROUP_UNCOMMITED: + break; + case AVAHI_ENTRY_GROUP_REGISTERING: + break; + } +} + +static void client_callback(AvahiClient *client, + AvahiClientState state, + void *userdata) +{ + ctx->client = client; + + switch (state) { + case AVAHI_CLIENT_S_RUNNING: + /* The server has startup successfully and registered its host + * name on the network, so it's time to create our services */ + if (!ctx->group) + register_stuff(); + break; + + case AVAHI_CLIENT_S_COLLISION: + if (ctx->group) + avahi_entry_group_reset(ctx->group); + break; + + case AVAHI_CLIENT_FAILURE: { + if (avahi_client_errno(client) == AVAHI_ERR_DISCONNECTED) { + int error; + + avahi_client_free(ctx->client); + ctx->client = NULL; + ctx->group = NULL; + + /* Reconnect to the server */ + if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll), + AVAHI_CLIENT_NO_FAIL, + client_callback, + ctx, + &error))) { + + LOG(log_error, logtype_afpd, "Failed to contact server: %s", + avahi_strerror(error)); + + avahi_threaded_poll_quit(ctx->threaded_poll); + } + + } else { + LOG(log_error, logtype_afpd, "Client failure: %s", + avahi_strerror(avahi_client_errno(client))); + avahi_threaded_poll_quit(ctx->threaded_poll); + } + break; + } + + case AVAHI_CLIENT_S_REGISTERING: + break; + case AVAHI_CLIENT_CONNECTING: + break; + } +} + +/************************************************************************ + * Public funcions + ************************************************************************/ + +/* + * Tries to setup the Zeroconf thread and any + * neccessary config setting. + */ +void av_zeroconf_register(const AFPObj *obj) { + int error; + + /* initialize the struct that holds our config settings. */ + if (ctx) { + LOG(log_debug, logtype_afpd, "Resetting zeroconf records"); + avahi_entry_group_reset(ctx->group); + } else { + ctx = calloc(1, sizeof(struct context)); + ctx->obj = obj; + assert(ctx); + } + +/* first of all we need to initialize our threading env */ + if (!(ctx->threaded_poll = avahi_threaded_poll_new())) { + goto fail; + } + +/* now we need to acquire a client */ + if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll), + AVAHI_CLIENT_NO_FAIL, + client_callback, + NULL, + &error))) { + LOG(log_error, logtype_afpd, "Failed to create client object: %s", + avahi_strerror(error)); + goto fail; + } + + if (avahi_threaded_poll_start(ctx->threaded_poll) < 0) { + LOG(log_error, logtype_afpd, "Failed to create thread: %s", + avahi_strerror(avahi_client_errno(ctx->client))); + goto fail; + } else { + LOG(log_info, logtype_afpd, "Successfully started avahi loop."); + } + + ctx->thread_running = 1; + return; + +fail: + av_zeroconf_unregister(); + + return; +} + +/* + * Tries to shutdown this loop impl. + * Call this function from inside this thread. + */ +int av_zeroconf_unregister() { + LOG(log_debug, logtype_afpd, "av_zeroconf_unregister"); + + if (ctx) { + if (ctx->threaded_poll) + avahi_threaded_poll_stop(ctx->threaded_poll); + if (ctx->client) + avahi_client_free(ctx->client); + if (ctx->threaded_poll) + avahi_threaded_poll_free(ctx->threaded_poll); + free(ctx); + ctx = NULL; + } + return 0; +} + +#endif /* USE_AVAHI */ + diff --git a/etc/netatalk/afp_avahi.h b/etc/netatalk/afp_avahi.h new file mode 100644 index 0000000..588a688 --- /dev/null +++ b/etc/netatalk/afp_avahi.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */ +/* + * Author: Daniel S. Haischt + * Purpose: Avahi based Zeroconf support + * Docs: http://avahi.org/download/doxygen/ + * + */ + +#ifndef AFPD_AVAHI_H +#define AFPD_AVAHI_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +struct context { + /* Avahi stuff */ + int thread_running; + AvahiThreadedPoll *threaded_poll; + AvahiClient *client; + AvahiEntryGroup *group; + /* Netatalk stuff */ + const AFPObj *obj; +}; + +/* prototype definitions */ +void av_zeroconf_register(const AFPObj *obj); +int av_zeroconf_unregister(void); + +#endif /* AFPD_AVAHI_H */ diff --git a/etc/netatalk/afp_mdns.c b/etc/netatalk/afp_mdns.c new file mode 100644 index 0000000..e298270 --- /dev/null +++ b/etc/netatalk/afp_mdns.c @@ -0,0 +1,349 @@ +/* + * Author: Lee Essen + * Based on: avahi support from Daniel S. Haischt + * Purpose: mdns based Zeroconf support + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_MDNS + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "afp_zeroconf.h" +#include "afp_mdns.h" + +/* + * We'll store all the DNSServiceRef's here so that we can + * deallocate them later + */ +static DNSServiceRef *svc_refs = NULL; +static int svc_ref_count = 0; +static pthread_t poller; + +/* + * Its easier to use asprintf to set the TXT record values + */ + +int TXTRecordPrintf(TXTRecordRef * rec, const char * key, const char * fmt, ... ) +{ + int ret = 0; + char *str; + va_list ap; + va_start( ap, fmt ); + + if( 0 > vasprintf(&str, fmt, ap ) ) { + va_end(ap); + return -1; + } + va_end(ap); + + if( kDNSServiceErr_NoError != TXTRecordSetValue(rec, key, strlen(str), str) ) { + ret = -1; + } + + free(str); + return ret; +} + +int TXTRecordKeyPrintf(TXTRecordRef * rec, const char * key_fmt, int key_var, const char * fmt, ...) +{ + int ret = 0; + char *key = NULL, *str = NULL; + va_list ap; + + if( 0 > asprintf(&key, key_fmt, key_var)) + return -1; + + va_start( ap, fmt ); + if( 0 > vasprintf(&str, fmt, ap )) { + va_end(ap); + ret = -1; + goto exit; + } + va_end(ap); + + if( kDNSServiceErr_NoError != TXTRecordSetValue(rec, key, strlen(str), str) ) { + ret = -1; + goto exit; + } + +exit: + if (str) + free(str); + if (key) + free(key); + return ret; +} + +static struct pollfd *fds; + +/* + * This is the thread that polls the filehandles + */ +static void *polling_thread(void *arg) { + // First we loop through getting the filehandles and adding them to our poll, we + // need to allocate our pollfd's + DNSServiceErrorType error; + fds = calloc(svc_ref_count, sizeof(struct pollfd)); + assert(fds); + + for(int i=0; i < svc_ref_count; i++) { + int fd = DNSServiceRefSockFD(svc_refs[i]); + fds[i].fd = fd; + fds[i].events = POLLIN; + } + + // Now we can poll and process the results... + while(poll(fds, svc_ref_count, -1) > 0) { + for(int i=0; i < svc_ref_count; i++) { + if(fds[i].revents & POLLIN) { + error = DNSServiceProcessResult(svc_refs[i]); + } + } + } + return(NULL); +} + +/* + * This is the callback for the service register function ... actually there isn't a lot + * we can do if we get problems, so we don't really need to do anything other than report + * the issue. + */ +static void RegisterReply(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, + const char *name, const char *regtype, const char *domain, void *context) +{ + if (errorCode != kDNSServiceErr_NoError) { + LOG(log_error, logtype_afpd, "Failed to register mDNS service: %s%s%s: code=%d", + name, regtype, domain, errorCode); + } +} + +/* + * This function unregisters anything we have already + * registered and frees associated memory + */ +static void unregister_stuff() { + pthread_cancel(poller); + + for (int i = 0; i < svc_ref_count; i++) + close(fds[i].fd); + free(fds); + fds = NULL; + + if(svc_refs) { + for(int i=0; i < svc_ref_count; i++) { + DNSServiceRefDeallocate(svc_refs[i]); + } + free(svc_refs); + svc_refs = NULL; + svc_ref_count = 0; + } +} + +/* + * This function tries to register the AFP DNS + * SRV service type. + */ +static void register_stuff(const AFPObj *obj) { + uint port; + const struct vol *volume; + char name[MAXINSTANCENAMELEN+1]; + DNSServiceErrorType error; + TXTRecordRef txt_adisk; + TXTRecordRef txt_devinfo; + char tmpname[256]; + + // If we had already registered, then we will unregister and re-register + if(svc_refs) unregister_stuff(); + + /* Register our service, prepare the TXT record */ + TXTRecordCreate(&txt_adisk, 0, NULL); + if( 0 > TXTRecordPrintf(&txt_adisk, "sys", "waMa=0,adVF=0x100") ) { + LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for sys"); + goto fail; + } + + /* Build AFP volumes list */ + int i = 0; + + for (volume = getvolumes(); volume; volume = volume->v_next) { + + if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, -1, tmpname, 255) <= 0) { + LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine"); + goto fail; + } + + if (volume->v_flags & AFPVOL_TM) { + if (volume->v_uuid) { + LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine", + volume->v_localname, volume->v_uuid); + if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1,adVU=%s", + tmpname, volume->v_uuid) ) { + LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i); + goto fail; + } + } else { + LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.", + volume->v_localname); + if( 0 > TXTRecordKeyPrintf(&txt_adisk, "dk%u", i++, "adVN=%s,adVF=0xa1", tmpname) ) { + LOG ( log_error, logtype_afpd, "Could not set Zeroconf TXTRecord for dk%u", i); + goto fail; + } + } + } + } + + /* AFP_DNS_SERVICE_TYPE */ + svc_ref_count = 1; + if (i) { + /* ADISK_SERVICE_TYPE */ + svc_ref_count++; + } + if (obj->options.mimicmodel) { + /* DEV_INFO_SERVICE_TYPE */ + svc_ref_count++; + } + + // Allocate the memory to store our service refs + svc_refs = calloc(svc_ref_count, sizeof(DNSServiceRef)); + assert(svc_refs); + svc_ref_count = 0; + + port = atoi(obj->options.port); + + if (convert_string(obj->options.unixcharset, + CH_UTF8, + obj->options.hostname, + -1, + name, + MAXINSTANCENAMELEN) <= 0) { + LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name"); + goto fail; + } + + error = DNSServiceRegister(&svc_refs[svc_ref_count++], + 0, // no flags + 0, // all network interfaces + name, + AFP_DNS_SERVICE_TYPE, + "", // default domains + NULL, // default host name + htons(port), + 0, // length of TXT + NULL, // no TXT + RegisterReply, // callback + NULL); // no context + if (error != kDNSServiceErr_NoError) { + LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d", + AFP_DNS_SERVICE_TYPE, error); + goto fail; + } + + if (i) { + error = DNSServiceRegister(&svc_refs[svc_ref_count++], + 0, // no flags + 0, // all network interfaces + name, + ADISK_SERVICE_TYPE, + "", // default domains + NULL, // default host name + htons(port), + TXTRecordGetLength(&txt_adisk), + TXTRecordGetBytesPtr(&txt_adisk), + RegisterReply, // callback + NULL); // no context + if (error != kDNSServiceErr_NoError) { + LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d", + ADISK_SERVICE_TYPE, error); + goto fail; + } + } + + if (obj->options.mimicmodel) { + LOG(log_info, logtype_afpd, "Registering server as model '%s'", + obj->options.mimicmodel); + TXTRecordCreate(&txt_devinfo, 0, NULL); + if ( 0 > TXTRecordPrintf(&txt_devinfo, "model", obj->options.mimicmodel) ) { + LOG ( log_error, logtype_afpd, "Could not create Zeroconf TXTRecord for model"); + goto fail; + } + + error = DNSServiceRegister(&svc_refs[svc_ref_count++], + 0, // no flags + 0, // all network interfaces + name, + DEV_INFO_SERVICE_TYPE, + "", // default domains + NULL, // default host name + /* + * We would probably use port 0 zero, but we can't, from man DNSServiceRegister: + * "A value of 0 for a port is passed to register placeholder services. + * Place holder services are not found when browsing, but other + * clients cannot register with the same name as the placeholder service." + * We therefor use port 9 which is used by the adisk service type. + */ + htons(9), + TXTRecordGetLength(&txt_devinfo), + TXTRecordGetBytesPtr(&txt_devinfo), + RegisterReply, // callback + NULL); // no context + TXTRecordDeallocate(&txt_devinfo); + if (error != kDNSServiceErr_NoError) { + LOG(log_error, logtype_afpd, "Failed to add service: %s, error=%d", + DEV_INFO_SERVICE_TYPE, error); + goto fail; + } + } /* if (config->obj.options.mimicmodel) */ + + /* + * Now we can create the thread that will poll for the results + * and handle the calling of the callbacks + */ + if(pthread_create(&poller, NULL, polling_thread, NULL) != 0) { + LOG(log_error, logtype_afpd, "Unable to start mDNS polling thread"); + goto fail; + } + +fail: + TXTRecordDeallocate(&txt_adisk); + return; +} + +/************************************************************************ + * Public funcions + ************************************************************************/ + +/* + * Tries to setup the Zeroconf thread and any + * neccessary config setting. + */ +void md_zeroconf_register(const AFPObj *obj) { + int error; + + register_stuff(obj); + return; +} + +/* + * Tries to shutdown this loop impl. + * Call this function from inside this thread. + */ +int md_zeroconf_unregister() { + unregister_stuff(); + return 0; +} + +#endif /* USE_MDNS */ + diff --git a/etc/netatalk/afp_mdns.h b/etc/netatalk/afp_mdns.h new file mode 100644 index 0000000..7e876c2 --- /dev/null +++ b/etc/netatalk/afp_mdns.h @@ -0,0 +1,22 @@ +/* + * Author: Lee Essen + * Based on: avahi support from Daniel S. Haischt + * Purpose: mdns based Zeroconf support + */ + +#ifndef AFPD_MDNS_H +#define AFPD_MDNS_H + +#include +#include +#include + +#include + +#include + +/* prototype definitions */ +void md_zeroconf_register(const AFPObj *obj); +int md_zeroconf_unregister(void); + +#endif /* AFPD_MDNS_H */ diff --git a/etc/netatalk/afp_zeroconf.c b/etc/netatalk/afp_zeroconf.c new file mode 100644 index 0000000..c5359ca --- /dev/null +++ b/etc/netatalk/afp_zeroconf.c @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */ +/* + * Author: Daniel S. Haischt + * Purpose: Zeroconf facade, that abstracts access to a + * particular Zeroconf implementation + * Doc: http://www.dns-sd.org/ + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "afp_zeroconf.h" + +#ifdef HAVE_MDNS +#include "afp_mdns.h" +#elif defined (HAVE_AVAHI) +#include "afp_avahi.h" +#endif + + +/* + * Functions (actually they are just facades) + */ +void zeroconf_register(const AFPObj *configs) +{ +#if defined (HAVE_MDNS) + LOG(log_debug, logtype_afpd, "Attempting to register with mDNS using mDNSResponder"); + + md_zeroconf_register(configs); +#elif defined (HAVE_AVAHI) + LOG(log_debug, logtype_afpd, "Attempting to register with mDNS using Avahi"); + + av_zeroconf_register(configs); +#endif +} + +void zeroconf_deregister(void) +{ +#if defined (HAVE_MDNS) + LOG(log_debug, logtype_afpd, "Attempting to de-register mDNS using mDNSResponder"); + md_zeroconf_unregister(); +#elif defined (HAVE_AVAHI) + LOG(log_debug, logtype_afpd, "Attempting to de-register mDNS using Avahi"); + av_zeroconf_unregister(); +#endif +} diff --git a/etc/netatalk/afp_zeroconf.h b/etc/netatalk/afp_zeroconf.h new file mode 100644 index 0000000..88bb6e7 --- /dev/null +++ b/etc/netatalk/afp_zeroconf.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */ +/* + * Author: Daniel S. Haischt + * Purpose: Zeroconf facade, that abstracts access to a + * particular Zeroconf implementation + * Doc: http://www.dns-sd.org/ + * + */ + +#ifndef AFPD_ZEROCONF_H +#define AFPD_ZEROCONF_H + +#include + +#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp" +#define ADISK_SERVICE_TYPE "_adisk._tcp" +#define DEV_INFO_SERVICE_TYPE "_device-info._tcp" + +#define MAXINSTANCENAMELEN 63 + +/* + * Prototype Definitions + */ + +/* + * registers service with a particular Zerconf implemenation. + */ +void zeroconf_register(const AFPObj *obj); + +/* + * de-registers the ntpd service with a particular Zerconf implemenation. + */ +void zeroconf_deregister(void); + +#endif /* AFPD_ZEROCONF_H */ diff --git a/etc/netatalk/netatalk.c b/etc/netatalk/netatalk.c new file mode 100644 index 0000000..f5e9ee6 --- /dev/null +++ b/etc/netatalk/netatalk.c @@ -0,0 +1,475 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "afp_zeroconf.h" + +#include + +/* how many seconds we wait to shutdown from SIGTERM before we send SIGKILL */ +#define KILL_GRACETIME 5 + +/* defines that control whether services should run by default */ +#define NETATALK_SRV_NEEDED -1 +#define NETATALK_SRV_OPTIONAL 0 +#define NETATALK_SRV_ERROR NETATALK_SRV_NEEDED + +/* forward declaration */ +static pid_t run_process(const char *path, ...); +static void kill_childs(int sig, ...); + +/* static variables */ +static AFPObj obj; +static pid_t afpd_pid = NETATALK_SRV_NEEDED; +static pid_t cnid_metad_pid = NETATALK_SRV_NEEDED; +static pid_t dbus_pid = NETATALK_SRV_OPTIONAL; +static uint afpd_restarts, cnid_metad_restarts, dbus_restarts; +static struct event_base *base; +struct event *sigterm_ev, *sigquit_ev, *sigchld_ev, *sighup_ev, *timer_ev; +static int in_shutdown; +static const char *dbus_path; + +/****************************************************************** + * Misc stuff + ******************************************************************/ + +static bool service_running(pid_t pid) +{ + if ((pid != NETATALK_SRV_NEEDED) && (pid != NETATALK_SRV_OPTIONAL)) + return true; + return false; +} + +/* Set Tracker Miners to index all our volumes */ +static int set_sl_volumes(void) +{ + EC_INIT; + const struct vol *volumes, *vol; + struct bstrList *vollist = bstrListCreate(); + bstring sep = bfromcstr(", "); + bstring volnamelist = NULL, cmd = NULL; + + EC_NULL_LOG( volumes = getvolumes() ); + + for (vol = volumes; vol; vol = vol->v_next) { + if (vol->v_flags & AFPVOL_SPOTLIGHT) { + bstring volnamequot = bformat("'%s'", vol->v_path); + bstrListPush(vollist, volnamequot); + } + } + + volnamelist = bjoin(vollist, sep); + cmd = bformat("gsettings set org.freedesktop.Tracker.Miner.Files index-recursive-directories \"[%s]\"", + bdata(volnamelist) ? bdata(volnamelist) : ""); + LOG(log_debug, logtype_sl, "set_sl_volumes: %s", bdata(cmd)); + system(bdata(cmd)); + + /* Disable default root user home indexing */ + system("gsettings set org.freedesktop.Tracker.Miner.Files index-single-directories \"[]\""); + +EC_CLEANUP: + if (cmd) + bdestroy(cmd); + if (sep) + bdestroy(sep); + if (vollist) + bstrListDestroy(vollist); + if (volnamelist) + bdestroy(volnamelist); + EC_EXIT; +} + +/****************************************************************** + * libevent helper functions + ******************************************************************/ + +/* libevent logging callback */ +static void libevent_logmsg_cb(int severity, const char *msg) +{ + switch (severity) { + case _EVENT_LOG_DEBUG: + LOG(log_debug, logtype_default, "libevent: %s", msg); + break; + case _EVENT_LOG_MSG: + LOG(log_info, logtype_default, "libevent: %s", msg); + break; + case _EVENT_LOG_WARN: + LOG(log_warning, logtype_default, "libevent: %s", msg); + break; + case _EVENT_LOG_ERR: + LOG(log_error, logtype_default, "libevent: %s", msg); + break; + default: + LOG(log_error, logtype_default, "libevent: %s", msg); + break; /* never reached */ + } +} + +/****************************************************************** + * libevent event callbacks + ******************************************************************/ + +/* SIGTERM callback */ +static void sigterm_cb(evutil_socket_t fd, short what, void *arg) +{ + sigset_t sigs; + struct timeval tv; + + LOG(log_info, logtype_afpd, "Exiting on SIGTERM"); + + if (in_shutdown) + return; + in_shutdown = 1; + + /* block any signal but SIGCHLD */ + sigfillset(&sigs); + sigdelset(&sigs, SIGCHLD); + sigprocmask(SIG_SETMASK, &sigs, NULL); + + /* add 10 sec timeout timer, remove all events but SIGCHLD */ + tv.tv_sec = KILL_GRACETIME; + tv.tv_usec = 0; + event_base_loopexit(base, &tv); + event_del(sigterm_ev); + event_del(sigquit_ev); + event_del(sighup_ev); + event_del(timer_ev); + +#ifdef HAVE_TRACKER + system("tracker-control -t"); +#endif + kill_childs(SIGTERM, &afpd_pid, &cnid_metad_pid, &dbus_pid, NULL); +} + +/* SIGQUIT callback */ +static void sigquit_cb(evutil_socket_t fd, short what, void *arg) +{ + LOG(log_note, logtype_afpd, "Exiting on SIGQUIT"); +#ifdef HAVE_TRACKER + system("tracker-control -t"); +#endif + kill_childs(SIGQUIT, &afpd_pid, &cnid_metad_pid, &dbus_pid, NULL); +} + +/* SIGHUP callback */ +static void sighup_cb(evutil_socket_t fd, short what, void *arg) +{ + LOG(log_note, logtype_afpd, "Received SIGHUP, sending all processes signal to reload config"); + + if (!(obj.options.flags & OPTION_NOZEROCONF)) { + zeroconf_deregister(); + load_volumes(&obj, lv_all | lv_force); + zeroconf_register(&obj); + LOG(log_note, logtype_default, "Re-registered with Zeroconf"); + } + + kill_childs(SIGHUP, &afpd_pid, &cnid_metad_pid, NULL); +} + +/* SIGCHLD callback */ +static void sigchld_cb(evutil_socket_t fd, short what, void *arg) +{ + int status; + pid_t pid; + + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status)) + LOG(log_info, logtype_default, "child[%d]: exited %d", pid, WEXITSTATUS(status)); + else + LOG(log_info, logtype_default, "child[%d]: done", pid); + } else { + if (WIFSIGNALED(status)) + LOG(log_info, logtype_default, "child[%d]: killed by signal %d", pid, WTERMSIG(status)); + else + LOG(log_info, logtype_default, "child[%d]: died", pid); + } + + if (pid == afpd_pid) + afpd_pid = NETATALK_SRV_ERROR; + else if (pid == cnid_metad_pid) + cnid_metad_pid = NETATALK_SRV_ERROR; + else if (pid == dbus_pid) + dbus_pid = NETATALK_SRV_ERROR; + else + LOG(log_error, logtype_afpd, "Bad pid: %d", pid); + } + + if (in_shutdown + && !service_running(afpd_pid) + && !service_running(cnid_metad_pid) + && !service_running(dbus_pid)) { + event_base_loopbreak(base); + } +} + +/* timer callback */ +static void timer_cb(evutil_socket_t fd, short what, void *arg) +{ + if (in_shutdown) + return; + + if (afpd_pid == NETATALK_SRV_NEEDED) { + afpd_restarts++; + LOG(log_note, logtype_afpd, "Restarting 'afpd' (restarts: %u)", afpd_restarts); + if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == -1) { + LOG(log_error, logtype_default, "Error starting 'afpd'"); + } + } + + if (cnid_metad_pid == NETATALK_SRV_NEEDED) { + cnid_metad_restarts++; + LOG(log_note, logtype_afpd, "Restarting 'cnid_metad' (restarts: %u)", cnid_metad_restarts); + if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == -1) { + LOG(log_error, logtype_default, "Error starting 'cnid_metad'"); + } + } + +#ifdef HAVE_TRACKER + if (dbus_pid == NETATALK_SRV_NEEDED) { + dbus_restarts++; + LOG(log_note, logtype_afpd, "Restarting 'dbus' (restarts: %u)", dbus_restarts); + if ((dbus_pid = run_process(dbus_path, "--config-file=" _PATH_CONFDIR "dbus-session.conf", NULL)) == -1) { + LOG(log_error, logtype_default, "Error starting '%s'", dbus_path); + } + } +#endif +} + +/****************************************************************** + * helper functions + ******************************************************************/ + +/* kill processes passed as varargs of type "pid_t *", terminate list with NULL */ +static void kill_childs(int sig, ...) +{ + va_list args; + pid_t *pid; + + va_start(args, sig); + + while ((pid = va_arg(args, pid_t *)) != NULL) { + if (*pid == NETATALK_SRV_ERROR || *pid == NETATALK_SRV_OPTIONAL) + continue; + kill(*pid, sig); + } + va_end(args); +} + +/* this get called when error conditions are met that require us to exit gracefully */ +static void netatalk_exit(int ret) +{ + server_unlock(PATH_NETATALK_LOCK); + exit(ret); +} + +/* this forks() and exec() "path" with varags as argc[] */ +static pid_t run_process(const char *path, ...) +{ + int i = 0; +#define MYARVSIZE 64 + char *myargv[MYARVSIZE]; + va_list args; + pid_t pid; + + if ((pid = fork()) < 0) { + LOG(log_error, logtype_cnid, "error in fork: %s", strerror(errno)); + return -1; + } + + if (pid == 0) { + myargv[i++] = (char *)path; + va_start(args, path); + while (i < MYARVSIZE) { + if ((myargv[i++] = va_arg(args, char *)) == NULL) + break; + } + va_end(args); + + (void)execv(path, myargv); + + /* Yikes! We're still here, so exec failed... */ + LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno)); + exit(1); + } + return pid; +} + +static void usage(void) +{ + printf("usage: netatalk [-F configfile] \n"); +} + +int main(int argc, char **argv) +{ + int c, ret, debug = 0; + sigset_t blocksigs; + struct timeval tv; + + /* Log SIGBUS/SIGSEGV SBT */ + fault_setup(NULL); + + while ((c = getopt(argc, argv, ":dF:")) != -1) { + switch(c) { + case 'd': + debug = 1; + break; + case 'F': + obj.cmdlineconfigfile = strdup(optarg); + break; + default: + usage(); + exit(EXIT_FAILURE); + } + } + + if (check_lockfile("netatalk", PATH_NETATALK_LOCK) != 0) + exit(EXITERR_SYS); + + if (!debug && daemonize(0, 0) != 0) + exit(EXITERR_SYS); + + if (create_lockfile("netatalk", PATH_NETATALK_LOCK) != 0) + exit(EXITERR_SYS); + + sigfillset(&blocksigs); + sigprocmask(SIG_SETMASK, &blocksigs, NULL); + + if (afp_config_parse(&obj, "netatalk") != 0) + netatalk_exit(EXITERR_CONF); + + load_volumes(&obj, lv_all); + + event_set_log_callback(libevent_logmsg_cb); + event_set_fatal_callback(netatalk_exit); + + LOG(log_note, logtype_default, "Netatalk AFP server starting"); + + if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == NETATALK_SRV_ERROR) { + LOG(log_error, logtype_afpd, "Error starting 'afpd'"); + netatalk_exit(EXITERR_CONF); + } + + if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == NETATALK_SRV_ERROR) { + LOG(log_error, logtype_afpd, "Error starting 'cnid_metad'"); + netatalk_exit(EXITERR_CONF); + } + + if ((base = event_base_new()) == NULL) { + LOG(log_error, logtype_afpd, "Error starting event loop"); + netatalk_exit(EXITERR_CONF); + } + + sigterm_ev = event_new(base, SIGTERM, EV_SIGNAL, sigterm_cb, NULL); + sigquit_ev = event_new(base, SIGQUIT, EV_SIGNAL | EV_PERSIST, sigquit_cb, NULL); + sighup_ev = event_new(base, SIGHUP, EV_SIGNAL | EV_PERSIST, sighup_cb, NULL); + sigchld_ev = event_new(base, SIGCHLD, EV_SIGNAL | EV_PERSIST, sigchld_cb, NULL); + timer_ev = event_new(base, -1, EV_PERSIST, timer_cb, NULL); + + tv.tv_sec = 1; + tv.tv_usec = 0; + + event_add(sigterm_ev, NULL); + event_add(sigquit_ev, NULL); + event_add(sigchld_ev, NULL); + event_add(sighup_ev, NULL); + event_add(timer_ev, &tv); + + sigfillset(&blocksigs); + sigdelset(&blocksigs, SIGTERM); + sigdelset(&blocksigs, SIGQUIT); + sigdelset(&blocksigs, SIGCHLD); + sigdelset(&blocksigs, SIGHUP); + sigprocmask(SIG_SETMASK, &blocksigs, NULL); + +#ifdef HAVE_TRACKER + if (obj.options.flags & OPTION_SPOTLIGHT) { + setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=" _PATH_STATEDIR "spotlight.ipc", 1); + setenv("XDG_DATA_HOME", _PATH_STATEDIR, 0); + setenv("XDG_CACHE_HOME", _PATH_STATEDIR, 0); + setenv("TRACKER_USE_LOG_FILES", "1", 0); + + if (atalk_iniparser_getboolean(obj.iniconfig, INISEC_GLOBAL, "start dbus", 1)) { + dbus_path = atalk_iniparser_getstring(obj.iniconfig, INISEC_GLOBAL, "dbus daemon", DBUS_DAEMON_PATH); + LOG(log_note, logtype_default, "Starting dbus: %s", dbus_path); + if ((dbus_pid = run_process(dbus_path, "--config-file=" _PATH_CONFDIR "dbus-session.conf", NULL)) == NETATALK_SRV_ERROR) { + LOG(log_error, logtype_default, "Error starting '%s'", dbus_path); + netatalk_exit(EXITERR_CONF); + } + + /* Allow dbus some time to start up */ + sleep(1); + } + + set_sl_volumes(); + + if (atalk_iniparser_getboolean(obj.iniconfig, INISEC_GLOBAL, "start tracker", 1)) { + LOG(log_note, logtype_default, "Starting Tracker"); + system(TRACKER_PREFIX "/bin/tracker-control -s"); + } + } +#endif + + /* Now register with zeroconf, we also need the volumes for that */ + if (! (obj.options.flags & OPTION_NOZEROCONF)) { + zeroconf_register(&obj); + LOG(log_note, logtype_default, "Registered with Zeroconf"); + } + + /* run the event loop */ + ret = event_base_dispatch(base); + + if (service_running(afpd_pid) || service_running(cnid_metad_pid) || service_running(dbus_pid)) { + if (service_running(afpd_pid)) + LOG(log_error, logtype_afpd, "AFP service did not shutdown, killing it"); + if (service_running(cnid_metad_pid)) + LOG(log_error, logtype_afpd, "CNID database service did not shutdown, killing it"); + if (service_running(dbus_pid)) + LOG(log_error, logtype_afpd, "DBUS session daemon still running, killing it"); + kill_childs(SIGKILL, &afpd_pid, &cnid_metad_pid, &dbus_pid, NULL); + } + + LOG(log_note, logtype_afpd, "Netatalk AFP server exiting"); + + netatalk_exit(ret); +} diff --git a/etc/spotlight/Makefile.am b/etc/spotlight/Makefile.am new file mode 100644 index 0000000..95f1ba4 --- /dev/null +++ b/etc/spotlight/Makefile.am @@ -0,0 +1,35 @@ +# Makefile.am for etc/spotlight/ + +pkgconfdir = @PKGCONFDIR@ +noinst_LTLIBRARIES = +noinst_PROGRAMS = +noinst_HEADERS = sparql_map.h +BUILT_SOURCES = + +AM_YFLAGS = -d + +if HAVE_TRACKER +BUILT_SOURCES += sparql_parser.h +noinst_PROGRAMS += srp +noinst_LTLIBRARIES += libspotlight.la + +libspotlight_la_SOURCES = \ + sparql_map.c \ + sparql_parser.y \ + spotlight_rawquery_lexer.l + +libspotlight_la_CFLAGS = \ + -DDBUS_API_SUBJECT_TO_CHANGE \ + @TRACKER_CFLAGS@ \ + -D_PATH_STATEDIR='"$(localstatedir)/netatalk"' + +libspotlight_la_LDFLAGS = @TRACKER_LIBS@ @TRACKER_MINER_LIBS@ + +srp_SOURCES = \ + sparql_map.c \ + sparql_parser.y \ + spotlight_rawquery_lexer.l + +srp_CFLAGS = -DMAIN -I$(top_srcdir)/include @TRACKER_CFLAGS@ +srp_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ +endif diff --git a/etc/spotlight/Makefile.in b/etc/spotlight/Makefile.in new file mode 100644 index 0000000..fff629f --- /dev/null +++ b/etc/spotlight/Makefile.in @@ -0,0 +1,830 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for etc/spotlight/ + + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = $(am__EXEEXT_1) +@HAVE_TRACKER_TRUE@am__append_1 = sparql_parser.h +@HAVE_TRACKER_TRUE@am__append_2 = srp +@HAVE_TRACKER_TRUE@am__append_3 = libspotlight.la +subdir = etc/spotlight +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + $(top_srcdir)/ylwrap sparql_parser.c sparql_parser.h \ + spotlight_rawquery_lexer.c +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libspotlight_la_LIBADD = +am__libspotlight_la_SOURCES_DIST = sparql_map.c sparql_parser.y \ + spotlight_rawquery_lexer.l +@HAVE_TRACKER_TRUE@am_libspotlight_la_OBJECTS = \ +@HAVE_TRACKER_TRUE@ libspotlight_la-sparql_map.lo \ +@HAVE_TRACKER_TRUE@ libspotlight_la-sparql_parser.lo \ +@HAVE_TRACKER_TRUE@ libspotlight_la-spotlight_rawquery_lexer.lo +libspotlight_la_OBJECTS = $(am_libspotlight_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libspotlight_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libspotlight_la_CFLAGS) $(CFLAGS) $(libspotlight_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@HAVE_TRACKER_TRUE@am_libspotlight_la_rpath = +@HAVE_TRACKER_TRUE@am__EXEEXT_1 = srp$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am__srp_SOURCES_DIST = sparql_map.c sparql_parser.y \ + spotlight_rawquery_lexer.l +@HAVE_TRACKER_TRUE@am_srp_OBJECTS = srp-sparql_map.$(OBJEXT) \ +@HAVE_TRACKER_TRUE@ srp-sparql_parser.$(OBJEXT) \ +@HAVE_TRACKER_TRUE@ srp-spotlight_rawquery_lexer.$(OBJEXT) +srp_OBJECTS = $(am_srp_OBJECTS) +@HAVE_TRACKER_TRUE@srp_DEPENDENCIES = \ +@HAVE_TRACKER_TRUE@ $(top_builddir)/libatalk/libatalk.la +srp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(srp_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ || +LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) +LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS) +AM_V_LEX = $(am__v_LEX_@AM_V@) +am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) +am__v_LEX_0 = @echo " LEX " $@; +am__v_LEX_1 = +YLWRAP = $(top_srcdir)/ylwrap +@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ || +am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ + -e s/c++$$/h++/ -e s/c$$/h/ +YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) +LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS) +AM_V_YACC = $(am__v_YACC_@AM_V@) +am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@) +am__v_YACC_0 = @echo " YACC " $@; +am__v_YACC_1 = +SOURCES = $(libspotlight_la_SOURCES) $(srp_SOURCES) +DIST_SOURCES = $(am__libspotlight_la_SOURCES_DIST) \ + $(am__srp_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgconfdir = @PKGCONFDIR@ +noinst_LTLIBRARIES = $(am__append_3) +noinst_HEADERS = sparql_map.h +BUILT_SOURCES = $(am__append_1) +AM_YFLAGS = -d +@HAVE_TRACKER_TRUE@libspotlight_la_SOURCES = \ +@HAVE_TRACKER_TRUE@ sparql_map.c \ +@HAVE_TRACKER_TRUE@ sparql_parser.y \ +@HAVE_TRACKER_TRUE@ spotlight_rawquery_lexer.l + +@HAVE_TRACKER_TRUE@libspotlight_la_CFLAGS = \ +@HAVE_TRACKER_TRUE@ -DDBUS_API_SUBJECT_TO_CHANGE \ +@HAVE_TRACKER_TRUE@ @TRACKER_CFLAGS@ \ +@HAVE_TRACKER_TRUE@ -D_PATH_STATEDIR='"$(localstatedir)/netatalk"' + +@HAVE_TRACKER_TRUE@libspotlight_la_LDFLAGS = @TRACKER_LIBS@ @TRACKER_MINER_LIBS@ +@HAVE_TRACKER_TRUE@srp_SOURCES = \ +@HAVE_TRACKER_TRUE@ sparql_map.c \ +@HAVE_TRACKER_TRUE@ sparql_parser.y \ +@HAVE_TRACKER_TRUE@ spotlight_rawquery_lexer.l + +@HAVE_TRACKER_TRUE@srp_CFLAGS = -DMAIN -I$(top_srcdir)/include @TRACKER_CFLAGS@ +@HAVE_TRACKER_TRUE@srp_LDADD = $(top_builddir)/libatalk/libatalk.la @MYSQL_LIBS@ +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .l .lo .o .obj .y +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign etc/spotlight/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign etc/spotlight/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +sparql_parser.h: sparql_parser.c + @if test ! -f $@; then rm -f sparql_parser.c; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) sparql_parser.c; else :; fi +libspotlight.la: $(libspotlight_la_OBJECTS) $(libspotlight_la_DEPENDENCIES) $(EXTRA_libspotlight_la_DEPENDENCIES) + $(AM_V_CCLD)$(libspotlight_la_LINK) $(am_libspotlight_la_rpath) $(libspotlight_la_OBJECTS) $(libspotlight_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +srp$(EXEEXT): $(srp_OBJECTS) $(srp_DEPENDENCIES) $(EXTRA_srp_DEPENDENCIES) + @rm -f srp$(EXEEXT) + $(AM_V_CCLD)$(srp_LINK) $(srp_OBJECTS) $(srp_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libspotlight_la-sparql_map.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libspotlight_la-sparql_parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libspotlight_la-spotlight_rawquery_lexer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp-sparql_map.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp-sparql_parser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp-spotlight_rawquery_lexer.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libspotlight_la-sparql_map.lo: sparql_map.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspotlight_la_CFLAGS) $(CFLAGS) -MT libspotlight_la-sparql_map.lo -MD -MP -MF $(DEPDIR)/libspotlight_la-sparql_map.Tpo -c -o libspotlight_la-sparql_map.lo `test -f 'sparql_map.c' || echo '$(srcdir)/'`sparql_map.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libspotlight_la-sparql_map.Tpo $(DEPDIR)/libspotlight_la-sparql_map.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sparql_map.c' object='libspotlight_la-sparql_map.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspotlight_la_CFLAGS) $(CFLAGS) -c -o libspotlight_la-sparql_map.lo `test -f 'sparql_map.c' || echo '$(srcdir)/'`sparql_map.c + +libspotlight_la-sparql_parser.lo: sparql_parser.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspotlight_la_CFLAGS) $(CFLAGS) -MT libspotlight_la-sparql_parser.lo -MD -MP -MF $(DEPDIR)/libspotlight_la-sparql_parser.Tpo -c -o libspotlight_la-sparql_parser.lo `test -f 'sparql_parser.c' || echo '$(srcdir)/'`sparql_parser.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libspotlight_la-sparql_parser.Tpo $(DEPDIR)/libspotlight_la-sparql_parser.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sparql_parser.c' object='libspotlight_la-sparql_parser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspotlight_la_CFLAGS) $(CFLAGS) -c -o libspotlight_la-sparql_parser.lo `test -f 'sparql_parser.c' || echo '$(srcdir)/'`sparql_parser.c + +libspotlight_la-spotlight_rawquery_lexer.lo: spotlight_rawquery_lexer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspotlight_la_CFLAGS) $(CFLAGS) -MT libspotlight_la-spotlight_rawquery_lexer.lo -MD -MP -MF $(DEPDIR)/libspotlight_la-spotlight_rawquery_lexer.Tpo -c -o libspotlight_la-spotlight_rawquery_lexer.lo `test -f 'spotlight_rawquery_lexer.c' || echo '$(srcdir)/'`spotlight_rawquery_lexer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libspotlight_la-spotlight_rawquery_lexer.Tpo $(DEPDIR)/libspotlight_la-spotlight_rawquery_lexer.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spotlight_rawquery_lexer.c' object='libspotlight_la-spotlight_rawquery_lexer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libspotlight_la_CFLAGS) $(CFLAGS) -c -o libspotlight_la-spotlight_rawquery_lexer.lo `test -f 'spotlight_rawquery_lexer.c' || echo '$(srcdir)/'`spotlight_rawquery_lexer.c + +srp-sparql_map.o: sparql_map.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -MT srp-sparql_map.o -MD -MP -MF $(DEPDIR)/srp-sparql_map.Tpo -c -o srp-sparql_map.o `test -f 'sparql_map.c' || echo '$(srcdir)/'`sparql_map.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/srp-sparql_map.Tpo $(DEPDIR)/srp-sparql_map.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sparql_map.c' object='srp-sparql_map.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -c -o srp-sparql_map.o `test -f 'sparql_map.c' || echo '$(srcdir)/'`sparql_map.c + +srp-sparql_map.obj: sparql_map.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -MT srp-sparql_map.obj -MD -MP -MF $(DEPDIR)/srp-sparql_map.Tpo -c -o srp-sparql_map.obj `if test -f 'sparql_map.c'; then $(CYGPATH_W) 'sparql_map.c'; else $(CYGPATH_W) '$(srcdir)/sparql_map.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/srp-sparql_map.Tpo $(DEPDIR)/srp-sparql_map.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sparql_map.c' object='srp-sparql_map.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -c -o srp-sparql_map.obj `if test -f 'sparql_map.c'; then $(CYGPATH_W) 'sparql_map.c'; else $(CYGPATH_W) '$(srcdir)/sparql_map.c'; fi` + +srp-sparql_parser.o: sparql_parser.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -MT srp-sparql_parser.o -MD -MP -MF $(DEPDIR)/srp-sparql_parser.Tpo -c -o srp-sparql_parser.o `test -f 'sparql_parser.c' || echo '$(srcdir)/'`sparql_parser.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/srp-sparql_parser.Tpo $(DEPDIR)/srp-sparql_parser.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sparql_parser.c' object='srp-sparql_parser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -c -o srp-sparql_parser.o `test -f 'sparql_parser.c' || echo '$(srcdir)/'`sparql_parser.c + +srp-sparql_parser.obj: sparql_parser.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -MT srp-sparql_parser.obj -MD -MP -MF $(DEPDIR)/srp-sparql_parser.Tpo -c -o srp-sparql_parser.obj `if test -f 'sparql_parser.c'; then $(CYGPATH_W) 'sparql_parser.c'; else $(CYGPATH_W) '$(srcdir)/sparql_parser.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/srp-sparql_parser.Tpo $(DEPDIR)/srp-sparql_parser.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sparql_parser.c' object='srp-sparql_parser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -c -o srp-sparql_parser.obj `if test -f 'sparql_parser.c'; then $(CYGPATH_W) 'sparql_parser.c'; else $(CYGPATH_W) '$(srcdir)/sparql_parser.c'; fi` + +srp-spotlight_rawquery_lexer.o: spotlight_rawquery_lexer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -MT srp-spotlight_rawquery_lexer.o -MD -MP -MF $(DEPDIR)/srp-spotlight_rawquery_lexer.Tpo -c -o srp-spotlight_rawquery_lexer.o `test -f 'spotlight_rawquery_lexer.c' || echo '$(srcdir)/'`spotlight_rawquery_lexer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/srp-spotlight_rawquery_lexer.Tpo $(DEPDIR)/srp-spotlight_rawquery_lexer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spotlight_rawquery_lexer.c' object='srp-spotlight_rawquery_lexer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -c -o srp-spotlight_rawquery_lexer.o `test -f 'spotlight_rawquery_lexer.c' || echo '$(srcdir)/'`spotlight_rawquery_lexer.c + +srp-spotlight_rawquery_lexer.obj: spotlight_rawquery_lexer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -MT srp-spotlight_rawquery_lexer.obj -MD -MP -MF $(DEPDIR)/srp-spotlight_rawquery_lexer.Tpo -c -o srp-spotlight_rawquery_lexer.obj `if test -f 'spotlight_rawquery_lexer.c'; then $(CYGPATH_W) 'spotlight_rawquery_lexer.c'; else $(CYGPATH_W) '$(srcdir)/spotlight_rawquery_lexer.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/srp-spotlight_rawquery_lexer.Tpo $(DEPDIR)/srp-spotlight_rawquery_lexer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spotlight_rawquery_lexer.c' object='srp-spotlight_rawquery_lexer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(srp_CFLAGS) $(CFLAGS) -c -o srp-spotlight_rawquery_lexer.obj `if test -f 'spotlight_rawquery_lexer.c'; then $(CYGPATH_W) 'spotlight_rawquery_lexer.c'; else $(CYGPATH_W) '$(srcdir)/spotlight_rawquery_lexer.c'; fi` + +.l.c: + $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) + +.y.c: + $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -rm -f sparql_parser.c + -rm -f sparql_parser.h + -rm -f spotlight_rawquery_lexer.c + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + cscopelist ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/etc/spotlight/sparql_map.c b/etc/spotlight/sparql_map.c new file mode 100644 index 0000000..3a0e469 --- /dev/null +++ b/etc/spotlight/sparql_map.c @@ -0,0 +1,136 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include + +#include "sparql_map.h" + +#define NOTSUPPORTED NULL +#define SPECIAL NULL + +struct spotlight_sparql_map spotlight_sparql_map[] = { + /* ssm_spotlight_attr ssm_enabled, ssm_type, ssm_sparql_attr */ + {"*", true, ssmt_fts, "fts:match"}, + + /* Filesystem metadata */ + {"kMDItemFSLabel", true, ssmt_num, NOTSUPPORTED}, + {"kMDItemDisplayName", true, ssmt_str, "nfo:fileName"}, + {"kMDItemFSName", true, ssmt_str, "nfo:fileName"}, + {"kMDItemFSContentChangeDate", true, ssmt_date, "nfo:fileLastModified"}, + + /* Common metadata */ + {"kMDItemTextContent", true, ssmt_fts, "fts:match"}, + {"kMDItemContentCreationDate", true, ssmt_date, "nie:contentCreated"}, + {"kMDItemContentModificationDate", true, ssmt_date, "nfo:fileLastModified"}, + {"kMDItemAttributeChangeDate", true, ssmt_date, "nfo:fileLastModified"}, + {"kMDItemLastUsedDate", true, ssmt_date, "nfo:fileLastAccessed"}, + {"kMDItemAuthors", true, ssmt_str, "dc:creator"}, + {"kMDItemCopyright", true, ssmt_str, "nie:copyright"}, + {"kMDItemCountry", true, ssmt_str, "nco:country"}, + {"kMDItemCreator", true, ssmt_str, "dc:creator"}, + {"kMDItemDurationSeconds", true, ssmt_num, "nfo:duration"}, + {"kMDItemNumberOfPages", true, ssmt_num, "nfo:pageCount"}, + {"kMDItemTitle", true, ssmt_str, "nie:title"}, + {"_kMDItemGroupId", true, ssmt_type, SPECIAL}, + {"kMDItemContentTypeTree", true, ssmt_type, SPECIAL}, + + /* Image metadata */ + {"kMDItemPixelWidth", true, ssmt_num, "nfo:width"}, + {"kMDItemPixelHeight", true, ssmt_num, "nfo:height"}, + {"kMDItemColorSpace", true, ssmt_str, "nexif:colorSpace"}, + {"kMDItemBitsPerSample", true, ssmt_num, "nfo:colorDepth"}, + {"kMDItemFocalLength", true, ssmt_num, "nmm:focalLength"}, + {"kMDItemISOSpeed", true, ssmt_num, "nmm:isoSpeed"}, + {"kMDItemOrientation", true, ssmt_bool, "nfo:orientation"}, + {"kMDItemResolutionWidthDPI", true, ssmt_num, "nfo:horizontalResolution"}, + {"kMDItemResolutionHeightDPI", true, ssmt_num, "nfo:verticalResolution"}, + {"kMDItemExposureTimeSeconds", true, ssmt_num, "nmm:exposureTime"}, + + /* Audio metadata */ + {"kMDItemComposer", true, ssmt_str, "nmm:composer"}, + {"kMDItemMusicalGenre", true, ssmt_str, "nfo:genre"}, + + {NULL, false, ssmt_str, NULL} +}; + +struct MDTypeMap MDTypeMap[] = { + {"1", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nmo#Email"}, + {"2", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#Contact"}, + {"3", kMDTypeMapNotSup, NULL}, /* PrefPane */ + {"4", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Font"}, + {"5", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Bookmark"}, + {"6", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#Contact"}, + {"7", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Video"}, + {"8", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Executable"}, + {"9", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Folder"}, + {"10", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Audio"}, + {"11", kMDTypeMapMime, "application/pdf"}, + {"12", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Presentation"}, + {"13", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Image"}, + {"public.jpeg", kMDTypeMapMime, "image/jpeg"}, + {"public.tiff", kMDTypeMapMime, "image/tiff"}, + {"com.compuserve.gif", kMDTypeMapMime, "image/gif"}, + {"public.png", kMDTypeMapMime, "image/png"}, + {"com.microsoft.bmp", kMDTypeMapMime, "image/bmp"}, + {"public.content", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Document"}, + {"public.mp3", kMDTypeMapMime, "audio/mpeg"}, + {"public.mpeg-4-audio", kMDTypeMapMime, "audio/x-aac"}, + {"com.apple.application", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Software"}, + {"public.text", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#TextDocument"}, + {"public.plain-text", kMDTypeMapMime, "text/plain"}, + {"public.rtf", kMDTypeMapMime, "text/rtf"}, + {"public.html", kMDTypeMapMime, "text/html"}, + {"public.xml", kMDTypeMapMime, "text/xml"}, + {"public.source-code", kMDTypeMapRDF, "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#SourceCode"}, + {NULL, kMDTypeMapNotSup, NULL} +}; + +void configure_spotlight_attributes(const char *attributes_in) +{ + char *attr, *attributes; + int i; + + for (i = 0; spotlight_sparql_map[i].ssm_spotlight_attr != NULL; i++) + spotlight_sparql_map[i].ssm_enabled = false; + + /* + * Go through the attribute map and for every element scan + * attributes_in with strtok(). If it's contained, keep it + * enabled, otherwise disable it. + */ + + attributes = strdup(attributes_in); + + for (attr = strtok(attributes, ","); attr; attr = strtok(NULL, ",")) { + + for (i = 0; spotlight_sparql_map[i].ssm_spotlight_attr != NULL; i++) + + if (strcmp(attr, spotlight_sparql_map[i].ssm_spotlight_attr) == 0) { + LOG(log_info, logtype_sl, "Enabling Spotlight attribute: %s", + spotlight_sparql_map[i].ssm_spotlight_attr); + spotlight_sparql_map[i].ssm_enabled = true; + break; + } + } + + free(attributes); +} diff --git a/etc/spotlight/sparql_map.h b/etc/spotlight/sparql_map.h new file mode 100644 index 0000000..3b92474 --- /dev/null +++ b/etc/spotlight/sparql_map.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef SPOTLIGHT_SPARQL_MAP_H +#define SPOTLIGHT_SPARQL_MAP_H + +enum ssm_type { + ssmt_bool, /* a boolean value that doesn't requires a SPARQL FILTER */ + ssmt_num, /* a numeric value that requires a SPARQL FILTER */ + ssmt_str, /* a string value that requieres a SPARQL FILTER */ + ssmt_fts, /* a string value that will be queried with SPARQL 'fts:match' */ + ssmt_date, /* date values are handled in a special map function map_daterange() */ + ssmt_type /* kMDItemContentType, requires special mapping */ +}; + +enum kMDTypeMap { + kMDTypeMapNotSup, /* not supported */ + kMDTypeMapRDF, /* query with rdf:type */ + kMDTypeMapMime /* query with nie:mimeType */ +}; + +struct spotlight_sparql_map { + const char *ssm_spotlight_attr; + bool ssm_enabled; + enum ssm_type ssm_type; + const char *ssm_sparql_attr; +}; + +struct MDTypeMap { + const char *mdtm_value; /* MD query value of attributes '_kMDItemGroupId' and 'kMDItemContentTypeTree' */ + enum kMDTypeMap mdtm_type; /* whether SPARQL query must search attribute rdf:type or nie:mime_Type */ + const char *mdtm_sparql; /* the SPARQL query match string */ +}; + +extern struct spotlight_sparql_map spotlight_sparql_map[]; +extern struct spotlight_sparql_map spotlight_sparql_date_map[]; +extern struct MDTypeMap MDTypeMap[]; +#endif diff --git a/etc/spotlight/sparql_parser.c b/etc/spotlight/sparql_parser.c new file mode 100644 index 0000000..48e5c1a --- /dev/null +++ b/etc/spotlight/sparql_parser.c @@ -0,0 +1,2060 @@ +/* A Bison parser, made by GNU Bison 2.7. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.7" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* Copy the first part of user declarations. */ +/* Line 371 of yacc.c */ +#line 1 "sparql_parser.y" + + #include + + #include + #include + #include + #include + + #include + + #include + #include + #include + #include + + #include "sparql_map.h" + + struct yy_buffer_state; + typedef struct yy_buffer_state *YY_BUFFER_STATE; + extern int yylex (void); + extern void yyerror (char const *); + extern void *yyterminate(void); + extern YY_BUFFER_STATE yy_scan_string( const char *str); + extern void yy_delete_buffer ( YY_BUFFER_STATE buffer ); + + /* forward declarations */ + static const char *map_expr(const char *attr, char op, const char *val); + static const char *map_daterange(const char *dateattr, time_t date1, time_t date2); + static time_t isodate2unix(const char *s); + + /* global vars, eg needed by the lexer */ + slq_t *ssp_slq; + + /* local vars */ + static gchar *ssp_result; + static char sparqlvar; + static char *result_limit; + +/* Line 371 of yacc.c */ +#line 107 "sparql_parser.c" + +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "y.tab.h". */ +#ifndef YY_YY_Y_TAB_H_INCLUDED +# define YY_YY_Y_TAB_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + WORD = 258, + BOOL = 259, + FUNC_INRANGE = 260, + DATE_ISO = 261, + OBRACE = 262, + CBRACE = 263, + EQUAL = 264, + UNEQUAL = 265, + GT = 266, + LT = 267, + COMMA = 268, + QUOTE = 269, + AND = 270, + OR = 271 + }; +#endif +/* Tokens. */ +#define WORD 258 +#define BOOL 259 +#define FUNC_INRANGE 260 +#define DATE_ISO 261 +#define OBRACE 262 +#define CBRACE 263 +#define EQUAL 264 +#define UNEQUAL 265 +#define GT 266 +#define LT 267 +#define COMMA 268 +#define QUOTE 269 +#define AND 270 +#define OR 271 + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ +/* Line 387 of yacc.c */ +#line 46 "sparql_parser.y" + + int ival; + const char *sval; + bool bval; + time_t tval; + + +/* Line 387 of yacc.c */ +#line 190 "sparql_parser.c" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + +extern YYSTYPE yylval; + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +/* "%code provides" blocks. */ +/* Line 387 of yacc.c */ +#line 40 "sparql_parser.y" + + #define SPRAW_TIME_OFFSET 978307200 + extern int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result); + extern slq_t *ssp_slq; + + +/* Line 387 of yacc.c */ +#line 222 "sparql_parser.c" + +#endif /* !YY_YY_Y_TAB_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +/* Line 390 of yacc.c */ +#line 229 "sparql_parser.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(N) (N) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 52 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 17 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 7 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 22 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 51 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 271 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = +{ + 0, 0, 3, 4, 7, 9, 11, 15, 17, 19, + 23, 27, 31, 37, 43, 49, 55, 62, 69, 76, + 83, 92, 97 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 18, 0, -1, -1, 18, 19, -1, 20, -1, 4, + -1, 21, 16, 21, -1, 21, -1, 22, -1, 7, + 20, 8, -1, 20, 15, 20, -1, 20, 16, 20, + -1, 3, 9, 14, 3, 14, -1, 3, 10, 14, + 3, 14, -1, 3, 12, 14, 3, 14, -1, 3, + 11, 14, 3, 14, -1, 3, 9, 14, 3, 14, + 3, -1, 3, 10, 14, 3, 14, 3, -1, 3, + 12, 14, 3, 14, 3, -1, 3, 11, 14, 3, + 14, 3, -1, 5, 7, 3, 13, 23, 13, 23, + 8, -1, 6, 7, 3, 8, -1, 3, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 68, 68, 70, 74, 88, 99, 107, 108, 109, + 110, 117, 130, 131, 132, 133, 134, 135, 136, 137, + 141, 145, 146 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 1 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "WORD", "BOOL", "FUNC_INRANGE", + "DATE_ISO", "OBRACE", "CBRACE", "EQUAL", "UNEQUAL", "GT", "LT", "COMMA", + "QUOTE", "AND", "OR", "$accept", "input", "line", "expr", "match", + "function", "date", YY_NULL +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 17, 18, 18, 19, 20, 20, 20, 20, 20, + 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, + 22, 23, 23 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 2, 1, 1, 3, 1, 1, 3, + 3, 3, 5, 5, 5, 5, 6, 6, 6, 6, + 8, 4, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 0, 1, 0, 5, 0, 0, 3, 4, 7, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 10, 11, 6, 0, + 0, 0, 0, 0, 12, 13, 15, 14, 22, 0, + 0, 16, 17, 19, 18, 0, 0, 0, 0, 21, + 20 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 1, 7, 8, 9, 10, 40 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -10 +static const yytype_int8 yypact[] = +{ + -10, 10, -10, 9, -10, -2, -1, -10, 8, -9, + -10, 2, 12, 13, 14, 26, -7, -1, -1, 27, + 28, 29, 30, 31, 22, -10, 20, -10, -10, 23, + 24, 25, 32, 19, 37, 38, 39, 40, -10, 41, + 34, -10, -10, -10, -10, 42, 19, 36, 43, -10, + -10 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -10, -10, -10, -6, 33, -10, 3 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = +{ + 16, 25, 3, 4, 5, 15, 6, 19, 17, 18, + 2, 26, 27, 3, 4, 5, 20, 6, 11, 12, + 13, 14, 38, 17, 18, 39, 21, 22, 23, 24, + 3, 29, 30, 31, 32, 33, 18, 34, 35, 36, + 41, 42, 43, 44, 49, 47, 37, 46, 45, 48, + 0, 50, 28 +}; + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-10))) + +#define yytable_value_is_error(Yytable_value) \ + YYID (0) + +static const yytype_int8 yycheck[] = +{ + 6, 8, 3, 4, 5, 7, 7, 16, 15, 16, + 0, 17, 18, 3, 4, 5, 14, 7, 9, 10, + 11, 12, 3, 15, 16, 6, 14, 14, 14, 3, + 3, 3, 3, 3, 3, 13, 16, 14, 14, 14, + 3, 3, 3, 3, 8, 3, 14, 13, 7, 46, + -1, 8, 19 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 18, 0, 3, 4, 5, 7, 19, 20, 21, + 22, 9, 10, 11, 12, 7, 20, 15, 16, 16, + 14, 14, 14, 14, 3, 8, 20, 20, 21, 3, + 3, 3, 3, 13, 14, 14, 14, 14, 3, 6, + 23, 3, 3, 3, 3, 7, 13, 3, 23, 8, + 8 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ + +#define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULL; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + + + +/* The lookahead symbol. */ +int yychar; + + +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); + +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 4: +/* Line 1792 of yacc.c */ +#line 74 "sparql_parser.y" + { + if (ssp_slq->slq_result_limit) + result_limit = talloc_asprintf(ssp_slq, "LIMIT %ld", ssp_slq->slq_result_limit); + else + result_limit = ""; + ssp_result = talloc_asprintf(ssp_slq, + "SELECT ?url WHERE " + "{ %s . ?obj nie:url ?url . FILTER(tracker:uri-is-descendant('file://%s/', ?url)) } %s", + (yyvsp[(1) - (1)].sval), ssp_slq->slq_scope, result_limit); + (yyval.sval) = ssp_result; +} + break; + + case 5: +/* Line 1792 of yacc.c */ +#line 88 "sparql_parser.y" + { + /* + * We can't properly handle these in expressions, fortunately this + * is probably only ever used by OS X as sole element in an + * expression ie "False" (when Finder window selected our share + * but no search string entered yet). Packet traces showed that OS + * X Spotlight server then returns a failure (ie -1) which is what + * we do here too by calling YYABORT. + */ + YYABORT; +} + break; + + case 6: +/* Line 1792 of yacc.c */ +#line 99 "sparql_parser.y" + { + if ((yyvsp[(1) - (3)].sval) == NULL || (yyvsp[(3) - (3)].sval) == NULL) + YYABORT; + if (strcmp((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)) != 0) + (yyval.sval) = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", (yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)); + else + (yyval.sval) = talloc_asprintf(ssp_slq, "%s", (yyvsp[(1) - (3)].sval)); +} + break; + + case 7: +/* Line 1792 of yacc.c */ +#line 107 "sparql_parser.y" + {(yyval.sval) = (yyvsp[(1) - (1)].sval); if ((yyval.sval) == NULL) YYABORT;} + break; + + case 8: +/* Line 1792 of yacc.c */ +#line 108 "sparql_parser.y" + {(yyval.sval) = (yyvsp[(1) - (1)].sval);} + break; + + case 9: +/* Line 1792 of yacc.c */ +#line 109 "sparql_parser.y" + {(yyval.sval) = talloc_asprintf(ssp_slq, "%s", (yyvsp[(2) - (3)].sval));} + break; + + case 10: +/* Line 1792 of yacc.c */ +#line 110 "sparql_parser.y" + { + if (!ssp_slq->slq_allow_expr) { + yyerror("Spotlight queries with logic expressions are disabled"); + YYABORT; + } + (yyval.sval) = talloc_asprintf(ssp_slq, "%s . %s", (yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)); +} + break; + + case 11: +/* Line 1792 of yacc.c */ +#line 117 "sparql_parser.y" + { + if (!ssp_slq->slq_allow_expr) { + yyerror("Spotlight queries with logic expressions are disabled"); + YYABORT; + } + if (strcmp((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)) != 0) + (yyval.sval) = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", (yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)); + else + (yyval.sval) = talloc_asprintf(ssp_slq, "%s", (yyvsp[(1) - (3)].sval)); +} + break; + + case 12: +/* Line 1792 of yacc.c */ +#line 130 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '=', (yyvsp[(4) - (5)].sval));} + break; + + case 13: +/* Line 1792 of yacc.c */ +#line 131 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '!', (yyvsp[(4) - (5)].sval));} + break; + + case 14: +/* Line 1792 of yacc.c */ +#line 132 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '<', (yyvsp[(4) - (5)].sval));} + break; + + case 15: +/* Line 1792 of yacc.c */ +#line 133 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '>', (yyvsp[(4) - (5)].sval));} + break; + + case 16: +/* Line 1792 of yacc.c */ +#line 134 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '=', (yyvsp[(4) - (6)].sval));} + break; + + case 17: +/* Line 1792 of yacc.c */ +#line 135 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '!', (yyvsp[(4) - (6)].sval));} + break; + + case 18: +/* Line 1792 of yacc.c */ +#line 136 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '<', (yyvsp[(4) - (6)].sval));} + break; + + case 19: +/* Line 1792 of yacc.c */ +#line 137 "sparql_parser.y" + {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '>', (yyvsp[(4) - (6)].sval));} + break; + + case 20: +/* Line 1792 of yacc.c */ +#line 141 "sparql_parser.y" + {(yyval.sval) = map_daterange((yyvsp[(3) - (8)].sval), (yyvsp[(5) - (8)].tval), (yyvsp[(7) - (8)].tval));} + break; + + case 21: +/* Line 1792 of yacc.c */ +#line 145 "sparql_parser.y" + {(yyval.tval) = isodate2unix((yyvsp[(3) - (4)].sval));} + break; + + case 22: +/* Line 1792 of yacc.c */ +#line 146 "sparql_parser.y" + {(yyval.tval) = atoi((yyvsp[(1) - (1)].sval)) + SPRAW_TIME_OFFSET;} + break; + + +/* Line 1792 of yacc.c */ +#line 1607 "sparql_parser.c" + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +/* Line 2055 of yacc.c */ +#line 149 "sparql_parser.y" + + +static time_t isodate2unix(const char *s) +{ + struct tm tm; + + if (strptime(s, "%Y-%m-%dT%H:%M:%SZ", &tm) == NULL) + return (time_t)-1; + return mktime(&tm); +} + +static const char *map_daterange(const char *dateattr, time_t date1, time_t date2) +{ + EC_INIT; + char *result = NULL; + struct spotlight_sparql_map *p; + struct tm *tmp; + char buf1[64], buf2[64]; + + EC_NULL_LOG( tmp = localtime(&date1) ); + strftime(buf1, sizeof(buf1), "%Y-%m-%dT%H:%M:%SZ", tmp); + EC_NULL_LOG( tmp = localtime(&date2) ); + strftime(buf2, sizeof(buf2), "%Y-%m-%dT%H:%M:%SZ", tmp); + + for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) { + if (strcmp(dateattr, p->ssm_spotlight_attr) == 0) { + result = talloc_asprintf(ssp_slq, + "?obj %s ?%c FILTER (?%c > '%s' && ?%c < '%s')", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + buf1, + sparqlvar, + buf2); + sparqlvar++; + break; + } + } + +EC_CLEANUP: + if (ret != 0) + return NULL; + return result; +} + +static char *map_type_search(const char *attr, char op, const char *val) +{ + char *result = NULL; + const char *sparqlAttr; + + for (struct MDTypeMap *p = MDTypeMap; p->mdtm_value; p++) { + if (strcmp(p->mdtm_value, val) == 0) { + switch (p->mdtm_type) { + case kMDTypeMapRDF: + sparqlAttr = "rdf:type"; + break; + case kMDTypeMapMime: + sparqlAttr = "nie:mimeType"; + break; + default: + return NULL; + } + result = talloc_asprintf(ssp_slq, "?obj %s '%s'", + sparqlAttr, + p->mdtm_sparql); + break; + } + } + return result; +} + +static const char *map_expr(const char *attr, char op, const char *val) +{ + EC_INIT; + char *result = NULL; + struct spotlight_sparql_map *p; + time_t t; + struct tm *tmp; + char buf1[64]; + bstring q = NULL, search = NULL, replace = NULL; + + for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) { + if (p->ssm_enabled && (strcmp(p->ssm_spotlight_attr, attr) == 0)) { + if (p->ssm_type != ssmt_type && p->ssm_sparql_attr == NULL) { + yyerror("unsupported Spotlight attribute"); + EC_FAIL; + } + switch (p->ssm_type) { + case ssmt_bool: + result = talloc_asprintf(ssp_slq, "?obj %s '%s'", p->ssm_sparql_attr, val); + break; + case ssmt_num: + result = talloc_asprintf(ssp_slq, "?obj %s ?%c FILTER(?%c %c%c '%s')", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + op, + op == '!' ? '=' : ' ', /* append '=' to '!' */ + val); + sparqlvar++; + break; + case ssmt_str: + q = bformat("^%s$", val); + search = bfromcstr("*"); + replace = bfromcstr(".*"); + bfindreplace(q, search, replace, 0); + result = talloc_asprintf(ssp_slq, "?obj %s ?%c FILTER(regex(?%c, '%s'))", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + bdata(q)); + sparqlvar++; + break; + case ssmt_fts: + result = talloc_asprintf(ssp_slq, "?obj %s '%s'", p->ssm_sparql_attr, val); + break; + case ssmt_date: + t = atoi(val) + SPRAW_TIME_OFFSET; + EC_NULL( tmp = localtime(&t) ); + strftime(buf1, sizeof(buf1), "%Y-%m-%dT%H:%M:%SZ", tmp); + result = talloc_asprintf(ssp_slq, "?obj %s ?%c FILTER(?%c %c '%s')", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + op, + buf1); + sparqlvar++; + break; + case ssmt_type: + result = map_type_search(attr, op, val); + break; + default: + EC_FAIL; + } + break; + } + } + +EC_CLEANUP: + if (ret != 0) + result = NULL; + if (q) + bdestroy(q); + if (search) + bdestroy(search); + if (replace) + bdestroy(replace); + return result; +} + +void yyerror(const char *str) +{ +#ifdef MAIN + printf("yyerror: %s\n", str); +#else + LOG(log_error, logtype_sl, "yyerror: %s", str); +#endif +} + +int yywrap() +{ + return 1; +} + +/** + * Map a Spotlight RAW query string to a SPARQL query string + * + * @param[in] slq Spotlight query handle + * @param[out] sparql_result Mapped SPARQL query, string is allocated in + * talloc context of slq + * @return 0 on success, -1 on error + **/ +int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result) +{ + EC_INIT; + YY_BUFFER_STATE s = NULL; + ssp_result = NULL; + + ssp_slq = slq; + s = yy_scan_string(slq->slq_qstring); + sparqlvar = 'a'; + + EC_ZERO( yyparse() ); + +EC_CLEANUP: + if (s) + yy_delete_buffer(s); + if (ret == 0) + *sparql_result = ssp_result; + else + *sparql_result = NULL; + EC_EXIT; +} + +#ifdef MAIN +int main(int argc, char **argv) +{ + int ret; + YY_BUFFER_STATE s; + + if (argc != 2) { + printf("usage: %s QUERY\n", argv[0]); + return 1; + } + + ssp_slq = talloc_zero(NULL, slq_t); + ssp_slq->slq_scope = talloc_strdup(ssp_slq, "/Volumes/test"); + ssp_slq->slq_allow_expr = true; + sparqlvar = 'a'; + + s = yy_scan_string(argv[1]); + + ret = yyparse(); + + yy_delete_buffer(s); + + if (ret == 0) + printf("SPARQL: %s\n", ssp_result ? ssp_result : "(empty)"); + + return 0; +} +#endif diff --git a/etc/spotlight/sparql_parser.h b/etc/spotlight/sparql_parser.h new file mode 100644 index 0000000..d2b3b67 --- /dev/null +++ b/etc/spotlight/sparql_parser.h @@ -0,0 +1,130 @@ +/* A Bison parser, made by GNU Bison 2.7. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_Y_TAB_H_INCLUDED +# define YY_YY_Y_TAB_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + WORD = 258, + BOOL = 259, + FUNC_INRANGE = 260, + DATE_ISO = 261, + OBRACE = 262, + CBRACE = 263, + EQUAL = 264, + UNEQUAL = 265, + GT = 266, + LT = 267, + COMMA = 268, + QUOTE = 269, + AND = 270, + OR = 271 + }; +#endif +/* Tokens. */ +#define WORD 258 +#define BOOL 259 +#define FUNC_INRANGE 260 +#define DATE_ISO 261 +#define OBRACE 262 +#define CBRACE 263 +#define EQUAL 264 +#define UNEQUAL 265 +#define GT 266 +#define LT 267 +#define COMMA 268 +#define QUOTE 269 +#define AND 270 +#define OR 271 + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ +/* Line 2058 of yacc.c */ +#line 46 "sparql_parser.y" + + int ival; + const char *sval; + bool bval; + time_t tval; + + +/* Line 2058 of yacc.c */ +#line 97 "sparql_parser.h" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + +extern YYSTYPE yylval; + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +/* "%code provides" blocks. */ +/* Line 2058 of yacc.c */ +#line 40 "sparql_parser.y" + + #define SPRAW_TIME_OFFSET 978307200 + extern int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result); + extern slq_t *ssp_slq; + + +/* Line 2058 of yacc.c */ +#line 129 "sparql_parser.h" + +#endif /* !YY_YY_Y_TAB_H_INCLUDED */ diff --git a/etc/spotlight/sparql_parser.y b/etc/spotlight/sparql_parser.y new file mode 100644 index 0000000..9d60997 --- /dev/null +++ b/etc/spotlight/sparql_parser.y @@ -0,0 +1,370 @@ +%{ + #include + + #include + #include + #include + #include + + #include + + #include + #include + #include + #include + + #include "sparql_map.h" + + struct yy_buffer_state; + typedef struct yy_buffer_state *YY_BUFFER_STATE; + extern int yylex (void); + extern void yyerror (char const *); + extern void *yyterminate(void); + extern YY_BUFFER_STATE yy_scan_string( const char *str); + extern void yy_delete_buffer ( YY_BUFFER_STATE buffer ); + + /* forward declarations */ + static const char *map_expr(const char *attr, char op, const char *val); + static const char *map_daterange(const char *dateattr, time_t date1, time_t date2); + static time_t isodate2unix(const char *s); + + /* global vars, eg needed by the lexer */ + slq_t *ssp_slq; + + /* local vars */ + static gchar *ssp_result; + static char sparqlvar; + static char *result_limit; +%} + +%code provides { + #define SPRAW_TIME_OFFSET 978307200 + extern int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result); + extern slq_t *ssp_slq; +} + +%union { + int ival; + const char *sval; + bool bval; + time_t tval; +} + +%expect 5 +%error-verbose + +%type match expr line function +%type date + +%token WORD +%token BOOL +%token FUNC_INRANGE +%token DATE_ISO +%token OBRACE CBRACE EQUAL UNEQUAL GT LT COMMA QUOTE +%left AND +%left OR +%% + +input: +/* empty */ +| input line +; + +line: +expr { + if (ssp_slq->slq_result_limit) + result_limit = talloc_asprintf(ssp_slq, "LIMIT %ld", ssp_slq->slq_result_limit); + else + result_limit = ""; + ssp_result = talloc_asprintf(ssp_slq, + "SELECT ?url WHERE " + "{ %s . ?obj nie:url ?url . FILTER(tracker:uri-is-descendant('file://%s/', ?url)) } %s", + $1, ssp_slq->slq_scope, result_limit); + $$ = ssp_result; +} +; + +expr: +BOOL { + /* + * We can't properly handle these in expressions, fortunately this + * is probably only ever used by OS X as sole element in an + * expression ie "False" (when Finder window selected our share + * but no search string entered yet). Packet traces showed that OS + * X Spotlight server then returns a failure (ie -1) which is what + * we do here too by calling YYABORT. + */ + YYABORT; +} +| match OR match { + if ($1 == NULL || $3 == NULL) + YYABORT; + if (strcmp($1, $3) != 0) + $$ = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", $1, $3); + else + $$ = talloc_asprintf(ssp_slq, "%s", $1); +} +| match {$$ = $1; if ($$ == NULL) YYABORT;} +| function {$$ = $1;} +| OBRACE expr CBRACE {$$ = talloc_asprintf(ssp_slq, "%s", $2);} +| expr AND expr { + if (!ssp_slq->slq_allow_expr) { + yyerror("Spotlight queries with logic expressions are disabled"); + YYABORT; + } + $$ = talloc_asprintf(ssp_slq, "%s . %s", $1, $3); +} +| expr OR expr { + if (!ssp_slq->slq_allow_expr) { + yyerror("Spotlight queries with logic expressions are disabled"); + YYABORT; + } + if (strcmp($1, $3) != 0) + $$ = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", $1, $3); + else + $$ = talloc_asprintf(ssp_slq, "%s", $1); +} +; + +match: +WORD EQUAL QUOTE WORD QUOTE {$$ = map_expr($1, '=', $4);} +| WORD UNEQUAL QUOTE WORD QUOTE {$$ = map_expr($1, '!', $4);} +| WORD LT QUOTE WORD QUOTE {$$ = map_expr($1, '<', $4);} +| WORD GT QUOTE WORD QUOTE {$$ = map_expr($1, '>', $4);} +| WORD EQUAL QUOTE WORD QUOTE WORD {$$ = map_expr($1, '=', $4);} +| WORD UNEQUAL QUOTE WORD QUOTE WORD {$$ = map_expr($1, '!', $4);} +| WORD LT QUOTE WORD QUOTE WORD {$$ = map_expr($1, '<', $4);} +| WORD GT QUOTE WORD QUOTE WORD {$$ = map_expr($1, '>', $4);} +; + +function: +FUNC_INRANGE OBRACE WORD COMMA date COMMA date CBRACE {$$ = map_daterange($3, $5, $7);} +; + +date: +DATE_ISO OBRACE WORD CBRACE {$$ = isodate2unix($3);} +| WORD {$$ = atoi($1) + SPRAW_TIME_OFFSET;} +; + +%% + +static time_t isodate2unix(const char *s) +{ + struct tm tm; + + if (strptime(s, "%Y-%m-%dT%H:%M:%SZ", &tm) == NULL) + return (time_t)-1; + return mktime(&tm); +} + +static const char *map_daterange(const char *dateattr, time_t date1, time_t date2) +{ + EC_INIT; + char *result = NULL; + struct spotlight_sparql_map *p; + struct tm *tmp; + char buf1[64], buf2[64]; + + EC_NULL_LOG( tmp = localtime(&date1) ); + strftime(buf1, sizeof(buf1), "%Y-%m-%dT%H:%M:%SZ", tmp); + EC_NULL_LOG( tmp = localtime(&date2) ); + strftime(buf2, sizeof(buf2), "%Y-%m-%dT%H:%M:%SZ", tmp); + + for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) { + if (strcmp(dateattr, p->ssm_spotlight_attr) == 0) { + result = talloc_asprintf(ssp_slq, + "?obj %s ?%c FILTER (?%c > '%s' && ?%c < '%s')", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + buf1, + sparqlvar, + buf2); + sparqlvar++; + break; + } + } + +EC_CLEANUP: + if (ret != 0) + return NULL; + return result; +} + +static char *map_type_search(const char *attr, char op, const char *val) +{ + char *result = NULL; + const char *sparqlAttr; + + for (struct MDTypeMap *p = MDTypeMap; p->mdtm_value; p++) { + if (strcmp(p->mdtm_value, val) == 0) { + switch (p->mdtm_type) { + case kMDTypeMapRDF: + sparqlAttr = "rdf:type"; + break; + case kMDTypeMapMime: + sparqlAttr = "nie:mimeType"; + break; + default: + return NULL; + } + result = talloc_asprintf(ssp_slq, "?obj %s '%s'", + sparqlAttr, + p->mdtm_sparql); + break; + } + } + return result; +} + +static const char *map_expr(const char *attr, char op, const char *val) +{ + EC_INIT; + char *result = NULL; + struct spotlight_sparql_map *p; + time_t t; + struct tm *tmp; + char buf1[64]; + bstring q = NULL, search = NULL, replace = NULL; + + for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) { + if (p->ssm_enabled && (strcmp(p->ssm_spotlight_attr, attr) == 0)) { + if (p->ssm_type != ssmt_type && p->ssm_sparql_attr == NULL) { + yyerror("unsupported Spotlight attribute"); + EC_FAIL; + } + switch (p->ssm_type) { + case ssmt_bool: + result = talloc_asprintf(ssp_slq, "?obj %s '%s'", p->ssm_sparql_attr, val); + break; + case ssmt_num: + result = talloc_asprintf(ssp_slq, "?obj %s ?%c FILTER(?%c %c%c '%s')", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + op, + op == '!' ? '=' : ' ', /* append '=' to '!' */ + val); + sparqlvar++; + break; + case ssmt_str: + q = bformat("^%s$", val); + search = bfromcstr("*"); + replace = bfromcstr(".*"); + bfindreplace(q, search, replace, 0); + result = talloc_asprintf(ssp_slq, "?obj %s ?%c FILTER(regex(?%c, '%s'))", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + bdata(q)); + sparqlvar++; + break; + case ssmt_fts: + result = talloc_asprintf(ssp_slq, "?obj %s '%s'", p->ssm_sparql_attr, val); + break; + case ssmt_date: + t = atoi(val) + SPRAW_TIME_OFFSET; + EC_NULL( tmp = localtime(&t) ); + strftime(buf1, sizeof(buf1), "%Y-%m-%dT%H:%M:%SZ", tmp); + result = talloc_asprintf(ssp_slq, "?obj %s ?%c FILTER(?%c %c '%s')", + p->ssm_sparql_attr, + sparqlvar, + sparqlvar, + op, + buf1); + sparqlvar++; + break; + case ssmt_type: + result = map_type_search(attr, op, val); + break; + default: + EC_FAIL; + } + break; + } + } + +EC_CLEANUP: + if (ret != 0) + result = NULL; + if (q) + bdestroy(q); + if (search) + bdestroy(search); + if (replace) + bdestroy(replace); + return result; +} + +void yyerror(const char *str) +{ +#ifdef MAIN + printf("yyerror: %s\n", str); +#else + LOG(log_error, logtype_sl, "yyerror: %s", str); +#endif +} + +int yywrap() +{ + return 1; +} + +/** + * Map a Spotlight RAW query string to a SPARQL query string + * + * @param[in] slq Spotlight query handle + * @param[out] sparql_result Mapped SPARQL query, string is allocated in + * talloc context of slq + * @return 0 on success, -1 on error + **/ +int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result) +{ + EC_INIT; + YY_BUFFER_STATE s = NULL; + ssp_result = NULL; + + ssp_slq = slq; + s = yy_scan_string(slq->slq_qstring); + sparqlvar = 'a'; + + EC_ZERO( yyparse() ); + +EC_CLEANUP: + if (s) + yy_delete_buffer(s); + if (ret == 0) + *sparql_result = ssp_result; + else + *sparql_result = NULL; + EC_EXIT; +} + +#ifdef MAIN +int main(int argc, char **argv) +{ + int ret; + YY_BUFFER_STATE s; + + if (argc != 2) { + printf("usage: %s QUERY\n", argv[0]); + return 1; + } + + ssp_slq = talloc_zero(NULL, slq_t); + ssp_slq->slq_scope = talloc_strdup(ssp_slq, "/Volumes/test"); + ssp_slq->slq_allow_expr = true; + sparqlvar = 'a'; + + s = yy_scan_string(argv[1]); + + ret = yyparse(); + + yy_delete_buffer(s); + + if (ret == 0) + printf("SPARQL: %s\n", ssp_result ? ssp_result : "(empty)"); + + return 0; +} +#endif diff --git a/etc/spotlight/spotlight_rawquery_lexer.c b/etc/spotlight/spotlight_rawquery_lexer.c new file mode 100644 index 0000000..b1f0508 --- /dev/null +++ b/etc/spotlight/spotlight_rawquery_lexer.c @@ -0,0 +1,1867 @@ +#line 2 "spotlight_rawquery_lexer.l" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + + + +#line 9 "spotlight_rawquery_lexer.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 18 +#define YY_END_OF_BUFFER 19 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[57] = + { 0, + 0, 0, 19, 18, 17, 18, 5, 18, 18, 6, + 7, 16, 15, 13, 11, 14, 16, 16, 16, 18, + 18, 18, 18, 12, 0, 8, 16, 0, 0, 0, + 10, 16, 16, 16, 9, 0, 0, 0, 16, 16, + 16, 0, 0, 16, 16, 4, 0, 16, 3, 0, + 16, 0, 1, 0, 2, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 3, 4, 1, 5, 1, 6, 1, 7, + 8, 9, 1, 10, 9, 11, 1, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 1, 12, + 13, 14, 1, 1, 9, 9, 9, 9, 9, 9, + 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, + 9, 16, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 1, 1, 1, 9, 1, 17, 9, 9, 9, + + 18, 19, 20, 9, 21, 9, 9, 22, 23, 24, + 25, 9, 9, 26, 27, 28, 29, 9, 9, 9, + 9, 9, 1, 30, 1, 1, 1, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 1, 1, 32, 32, 32, 32, 32, 32, 32, + + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, + 34, 34, 34, 34, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[35] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 2, 2, 2 + } ; + +static yyconst flex_int16_t yy_base[58] = + { 0, + 0, 0, 91, 92, 92, 77, 92, 61, 82, 92, + 92, 3, 92, 92, 74, 92, 14, 25, 15, 56, + 54, 53, 52, 92, 61, 92, 57, 49, 48, 47, + 92, 27, 28, 16, 92, 46, 45, 52, 36, 30, + 37, 43, 55, 48, 38, 47, 59, 39, 45, 47, + 40, 40, 42, 40, 92, 92, 42 + } ; + +static yyconst flex_int16_t yy_def[58] = + { 0, + 56, 1, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 57, 56, 56, 56, 56, 57, 17, 17, 56, + 56, 56, 56, 56, 56, 56, 17, 56, 56, 56, + 56, 17, 17, 17, 56, 56, 56, 56, 17, 17, + 17, 56, 56, 17, 17, 17, 56, 17, 17, 56, + 17, 56, 17, 56, 56, 0, 56 + } ; + +static yyconst flex_int16_t yy_nxt[127] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 12, 14, 15, 16, 17, 12, 12, 12, 18, 12, + 12, 12, 12, 12, 12, 12, 12, 19, 12, 20, + 4, 21, 22, 23, 28, 29, 30, 32, 27, 27, + 34, 33, 39, 27, 41, 28, 29, 30, 27, 40, + 27, 27, 44, 27, 46, 49, 45, 53, 51, 27, + 27, 27, 27, 27, 55, 27, 54, 52, 27, 50, + 27, 48, 47, 27, 43, 42, 27, 37, 36, 27, + 27, 38, 37, 36, 27, 35, 31, 26, 25, 24, + 56, 3, 56, 56, 56, 56, 56, 56, 56, 56, + + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56 + } ; + +static yyconst flex_int16_t yy_chk[127] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 12, 12, 12, 17, 19, 34, + 19, 18, 32, 57, 34, 17, 17, 17, 18, 33, + 32, 33, 39, 40, 41, 45, 40, 51, 48, 39, + 41, 45, 48, 51, 54, 53, 52, 50, 49, 47, + 46, 44, 43, 42, 38, 37, 36, 30, 29, 28, + 27, 25, 23, 22, 21, 20, 15, 9, 8, 6, + 3, 56, 56, 56, 56, 56, 56, 56, 56, 56, + + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "spotlight_rawquery_lexer.l" + +#line 8 "spotlight_rawquery_lexer.l" +#include +#include +#include +#include +#ifdef HAVE_TRACKER +#include "sparql_parser.h" +#define SLQ_VAR ssp_slq +#endif +#line 509 "spotlight_rawquery_lexer.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 27 "spotlight_rawquery_lexer.l" + +#line 693 "spotlight_rawquery_lexer.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 57 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 92 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 28 "spotlight_rawquery_lexer.l" +return FUNC_INRANGE; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 29 "spotlight_rawquery_lexer.l" +return DATE_ISO; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 30 "spotlight_rawquery_lexer.l" +{yylval.bval = false; return BOOL;} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 31 "spotlight_rawquery_lexer.l" +{yylval.bval = true; return BOOL;} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 32 "spotlight_rawquery_lexer.l" +return QUOTE; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 33 "spotlight_rawquery_lexer.l" +return OBRACE; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 34 "spotlight_rawquery_lexer.l" +return CBRACE; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 35 "spotlight_rawquery_lexer.l" +return AND; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 36 "spotlight_rawquery_lexer.l" +return OR; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 37 "spotlight_rawquery_lexer.l" +return EQUAL; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 38 "spotlight_rawquery_lexer.l" +return EQUAL; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 39 "spotlight_rawquery_lexer.l" +return UNEQUAL; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 40 "spotlight_rawquery_lexer.l" +return LT; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 41 "spotlight_rawquery_lexer.l" +return GT; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 42 "spotlight_rawquery_lexer.l" +return COMMA; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 43 "spotlight_rawquery_lexer.l" +{yylval.sval = talloc_strdup(SLQ_VAR, yytext); return WORD;} + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +#line 44 "spotlight_rawquery_lexer.l" +/* ignore */ + YY_BREAK +case 18: +YY_RULE_SETUP +#line 45 "spotlight_rawquery_lexer.l" +ECHO; + YY_BREAK +#line 867 "spotlight_rawquery_lexer.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 57 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 57 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 56); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 45 "spotlight_rawquery_lexer.l" + + + diff --git a/etc/spotlight/spotlight_rawquery_lexer.l b/etc/spotlight/spotlight_rawquery_lexer.l new file mode 100644 index 0000000..34d7e05 --- /dev/null +++ b/etc/spotlight/spotlight_rawquery_lexer.l @@ -0,0 +1,45 @@ +%top{ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +} + +%{ +#include +#include +#include +#include +#ifdef HAVE_TRACKER +#include "sparql_parser.h" +#define SLQ_VAR ssp_slq +#endif +%} + +ASC [a-zA-Z0-9_\*\:\-\.] +U [\x80-\xbf] +U2 [\xc2-\xdf] +U3 [\xe0-\xef] +U4 [\xf0-\xf4] + +UANY {ASC}|{U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} +UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} + +%% +InRange return FUNC_INRANGE; +\$time\.iso return DATE_ISO; +false {yylval.bval = false; return BOOL;} +true {yylval.bval = true; return BOOL;} +\" return QUOTE; +\( return OBRACE; +\) return CBRACE; +\&\& return AND; +\|\| return OR; +\=\= return EQUAL; +\= return EQUAL; +\!\= return UNEQUAL; +\< return LT; +\> return GT; +\, return COMMA; +{UANY}+ {yylval.sval = talloc_strdup(SLQ_VAR, yytext); return WORD;} +[ \t\n] /* ignore */ +%% diff --git a/etc/uams/Makefile.am b/etc/uams/Makefile.am new file mode 100644 index 0000000..23fd3d1 --- /dev/null +++ b/etc/uams/Makefile.am @@ -0,0 +1,144 @@ +# Makefile.am for etc/uams/ + +# +# conditionally build some modules +# + +UAMS_GENERIC = uams_guest.la uams_passwd.la +uams_LINKS = uams_clrtxt.so +dhx_exec_hook = echo +dhx2_exec_hook = echo + +# these are complex: check if DHX and DHX2 module should be build + +if USE_DHX +if HAVE_OPENSSL +uams_LINKS += uams_dhx.so +UAMS_DHX = uams_dhx_passwd.la +if BUILD_PAM +UAMS_DHX_PAM = uams_dhx_pam.la +endif +if USE_PAM_SO +dhx_exec_hook += && $(LN_S) uams_dhx_pam.so uams_dhx.so +else +dhx_exec_hook += && $(LN_S) uams_dhx_passwd.so uams_dhx.so +endif + +endif +endif + +if USE_DHX2 +if HAVE_LIBGCRYPT +uams_LINKS += uams_dhx2.so +UAMS_DHX2 = uams_dhx2_passwd.la +if BUILD_PAM +UAMS_DHX2_PAM = uams_dhx2_pam.la +endif +if USE_PAM_SO +dhx2_exec_hook += && $(LN_S) uams_dhx2_pam.so uams_dhx2.so +else +dhx2_exec_hook += && $(LN_S) uams_dhx2_passwd.so uams_dhx2.so +endif +endif +endif + +# these are simple, though some the last three depend on OpenSSL + +if BUILD_PAM +UAMS_PAM = uams_pam.la +endif + +if USE_RANDNUM +UAMS_RANDNUM = uams_randnum.la +endif + +if USE_PGP +UAMS_PGP = uams_pgp.la +endif + +if USE_GSSAPI +UAMS_GSSAPI = uams_gss.la +endif + +# links + +if USE_PAM_SO +UAMS_CLRTXT_LINK = uams_pam.so +else +UAMS_CLRTXT_LINK = uams_passwd.so +endif + +# +# source files +# + +uams_guest_la_SOURCES = uams_guest.c +uams_randnum_la_SOURCES = uams_randnum.c +uams_passwd_la_SOURCES = uams_passwd.c +uams_pam_la_SOURCES = uams_pam.c +uams_pgp_la_SOURCES = uams_pgp.c +uams_dhx_passwd_la_SOURCES = uams_dhx_passwd.c +uams_dhx_pam_la_SOURCES = uams_dhx_pam.c +uams_dhx2_passwd_la_SOURCES = uams_dhx2_passwd.c +uams_dhx2_pam_la_SOURCES = uams_dhx2_pam.c +uams_gss_la_SOURCES = uams_gss.c + +# +# flags +# + +# these should be sorted out, applying both to AM_CFLAGS is senseless +AM_CFLAGS = @SSL_CFLAGS@ @LIBGCRYPT_CFLAGS@ + +uams_pam_la_CFLAGS = @PAM_CFLAGS@ +uams_dhx_pam_la_CFLAGS = @SSL_CFLAGS@ @PAM_CFLAGS@ +uams_dhx2_pam_la_CFLAGS = @LIBGCRYPT_CFLAGS@ @PAM_CFLAGS@ +uams_gss_la_CFLAGS = @GSSAPI_CFLAGS@ @KRB5_CFLAGS@ + +uams_guest_la_LDFLAGS = -module -avoid-version +uams_randnum_la_LDFLAGS = -module -avoid-version @SSL_LIBS@ +uams_passwd_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ +uams_pam_la_LDFLAGS = -module -avoid-version @PAM_LIBS@ +uams_pgp_la_LDFLAGS = -module -avoid-version @SSL_LIBS@ +uams_dhx_passwd_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ @SSL_LIBS@ +uams_dhx_pam_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ @SSL_LIBS@ @PAM_LIBS@ +uams_dhx2_passwd_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ @LIBGCRYPT_LIBS@ +uams_dhx2_pam_la_LDFLAGS = -module -avoid-version @LIBGCRYPT_LIBS@ @PAM_LIBS@ +uams_gss_la_LDFLAGS = -module -avoid-version @GSSAPI_LIBS@ @KRB5_LIBS@ + +# +# module compilation +# + +uamsdir = @UAMS_PATH@ +uams_LTLIBRARIES = \ + $(UAMS_GENERIC) \ + $(UAMS_PGP) \ + $(UAMS_PAM) \ + $(UAMS_RANDNUM) \ + $(UAMS_DHX) \ + $(UAMS_DHX_PAM) \ + $(UAMS_DHX2) \ + $(UAMS_DHX2_PAM) \ + $(UAMS_GSSAPI) + +# +# link creation +# + +install-data-hook: + (if [ -d $(DESTDIR)$(uamsdir) ] ; then \ + cd $(DESTDIR)$(uamsdir) && \ + rm -f $(uams_LINKS) && \ + $(LN_S) $(UAMS_CLRTXT_LINK) uams_clrtxt.so && \ + $(dhx_exec_hook) && \ + $(dhx2_exec_hook) ; \ + fi) + + + +uninstall-hook: + (if [ -d $(DESTDIR)$(uamsdir) ] ; then \ + cd $(DESTDIR)$(uamsdir) && \ + rm -f $(uams_LINKS) ; \ + fi) diff --git a/etc/uams/Makefile.in b/etc/uams/Makefile.in new file mode 100644 index 0000000..d49afeb --- /dev/null +++ b/etc/uams/Makefile.in @@ -0,0 +1,957 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for etc/uams/ + +# +# conditionally build some modules +# + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ + +# these are complex: check if DHX and DHX2 module should be build +@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@am__append_1 = uams_dhx.so +@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@@USE_PAM_SO_TRUE@am__append_2 = && $(LN_S) uams_dhx_pam.so uams_dhx.so +@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@@USE_PAM_SO_FALSE@am__append_3 = && $(LN_S) uams_dhx_passwd.so uams_dhx.so +@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@am__append_4 = uams_dhx2.so +@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@@USE_PAM_SO_TRUE@am__append_5 = && $(LN_S) uams_dhx2_pam.so uams_dhx2.so +@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@@USE_PAM_SO_FALSE@am__append_6 = && $(LN_S) uams_dhx2_passwd.so uams_dhx2.so +subdir = etc/uams +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(uamsdir)" +LTLIBRARIES = $(uams_LTLIBRARIES) +uams_dhx2_pam_la_LIBADD = +am_uams_dhx2_pam_la_OBJECTS = uams_dhx2_pam_la-uams_dhx2_pam.lo +uams_dhx2_pam_la_OBJECTS = $(am_uams_dhx2_pam_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +uams_dhx2_pam_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(uams_dhx2_pam_la_CFLAGS) $(CFLAGS) \ + $(uams_dhx2_pam_la_LDFLAGS) $(LDFLAGS) -o $@ +@BUILD_PAM_TRUE@@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@am_uams_dhx2_pam_la_rpath = \ +@BUILD_PAM_TRUE@@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@ -rpath \ +@BUILD_PAM_TRUE@@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@ $(uamsdir) +uams_dhx2_passwd_la_LIBADD = +am_uams_dhx2_passwd_la_OBJECTS = uams_dhx2_passwd.lo +uams_dhx2_passwd_la_OBJECTS = $(am_uams_dhx2_passwd_la_OBJECTS) +uams_dhx2_passwd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(uams_dhx2_passwd_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@am_uams_dhx2_passwd_la_rpath = \ +@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@ -rpath $(uamsdir) +uams_dhx_pam_la_LIBADD = +am_uams_dhx_pam_la_OBJECTS = uams_dhx_pam_la-uams_dhx_pam.lo +uams_dhx_pam_la_OBJECTS = $(am_uams_dhx_pam_la_OBJECTS) +uams_dhx_pam_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(uams_dhx_pam_la_CFLAGS) $(CFLAGS) $(uams_dhx_pam_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@BUILD_PAM_TRUE@@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@am_uams_dhx_pam_la_rpath = \ +@BUILD_PAM_TRUE@@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@ -rpath \ +@BUILD_PAM_TRUE@@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@ $(uamsdir) +uams_dhx_passwd_la_LIBADD = +am_uams_dhx_passwd_la_OBJECTS = uams_dhx_passwd.lo +uams_dhx_passwd_la_OBJECTS = $(am_uams_dhx_passwd_la_OBJECTS) +uams_dhx_passwd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(uams_dhx_passwd_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@am_uams_dhx_passwd_la_rpath = -rpath \ +@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@ $(uamsdir) +uams_gss_la_LIBADD = +am_uams_gss_la_OBJECTS = uams_gss_la-uams_gss.lo +uams_gss_la_OBJECTS = $(am_uams_gss_la_OBJECTS) +uams_gss_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(uams_gss_la_CFLAGS) \ + $(CFLAGS) $(uams_gss_la_LDFLAGS) $(LDFLAGS) -o $@ +@USE_GSSAPI_TRUE@am_uams_gss_la_rpath = -rpath $(uamsdir) +uams_guest_la_LIBADD = +am_uams_guest_la_OBJECTS = uams_guest.lo +uams_guest_la_OBJECTS = $(am_uams_guest_la_OBJECTS) +uams_guest_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(uams_guest_la_LDFLAGS) $(LDFLAGS) -o $@ +uams_pam_la_LIBADD = +am_uams_pam_la_OBJECTS = uams_pam_la-uams_pam.lo +uams_pam_la_OBJECTS = $(am_uams_pam_la_OBJECTS) +uams_pam_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(uams_pam_la_CFLAGS) \ + $(CFLAGS) $(uams_pam_la_LDFLAGS) $(LDFLAGS) -o $@ +@BUILD_PAM_TRUE@am_uams_pam_la_rpath = -rpath $(uamsdir) +uams_passwd_la_LIBADD = +am_uams_passwd_la_OBJECTS = uams_passwd.lo +uams_passwd_la_OBJECTS = $(am_uams_passwd_la_OBJECTS) +uams_passwd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(uams_passwd_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +uams_pgp_la_LIBADD = +am_uams_pgp_la_OBJECTS = uams_pgp.lo +uams_pgp_la_OBJECTS = $(am_uams_pgp_la_OBJECTS) +uams_pgp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(uams_pgp_la_LDFLAGS) $(LDFLAGS) -o $@ +@USE_PGP_TRUE@am_uams_pgp_la_rpath = -rpath $(uamsdir) +uams_randnum_la_LIBADD = +am_uams_randnum_la_OBJECTS = uams_randnum.lo +uams_randnum_la_OBJECTS = $(am_uams_randnum_la_OBJECTS) +uams_randnum_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(uams_randnum_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@USE_RANDNUM_TRUE@am_uams_randnum_la_rpath = -rpath $(uamsdir) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(uams_dhx2_pam_la_SOURCES) $(uams_dhx2_passwd_la_SOURCES) \ + $(uams_dhx_pam_la_SOURCES) $(uams_dhx_passwd_la_SOURCES) \ + $(uams_gss_la_SOURCES) $(uams_guest_la_SOURCES) \ + $(uams_pam_la_SOURCES) $(uams_passwd_la_SOURCES) \ + $(uams_pgp_la_SOURCES) $(uams_randnum_la_SOURCES) +DIST_SOURCES = $(uams_dhx2_pam_la_SOURCES) \ + $(uams_dhx2_passwd_la_SOURCES) $(uams_dhx_pam_la_SOURCES) \ + $(uams_dhx_passwd_la_SOURCES) $(uams_gss_la_SOURCES) \ + $(uams_guest_la_SOURCES) $(uams_pam_la_SOURCES) \ + $(uams_passwd_la_SOURCES) $(uams_pgp_la_SOURCES) \ + $(uams_randnum_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +UAMS_GENERIC = uams_guest.la uams_passwd.la +uams_LINKS = uams_clrtxt.so $(am__append_1) $(am__append_4) +dhx_exec_hook = echo $(am__append_2) $(am__append_3) +dhx2_exec_hook = echo $(am__append_5) $(am__append_6) +@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@UAMS_DHX = uams_dhx_passwd.la +@BUILD_PAM_TRUE@@HAVE_OPENSSL_TRUE@@USE_DHX_TRUE@UAMS_DHX_PAM = uams_dhx_pam.la +@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@UAMS_DHX2 = uams_dhx2_passwd.la +@BUILD_PAM_TRUE@@HAVE_LIBGCRYPT_TRUE@@USE_DHX2_TRUE@UAMS_DHX2_PAM = uams_dhx2_pam.la + +# these are simple, though some the last three depend on OpenSSL +@BUILD_PAM_TRUE@UAMS_PAM = uams_pam.la +@USE_RANDNUM_TRUE@UAMS_RANDNUM = uams_randnum.la +@USE_PGP_TRUE@UAMS_PGP = uams_pgp.la +@USE_GSSAPI_TRUE@UAMS_GSSAPI = uams_gss.la +@USE_PAM_SO_FALSE@UAMS_CLRTXT_LINK = uams_passwd.so + +# links +@USE_PAM_SO_TRUE@UAMS_CLRTXT_LINK = uams_pam.so + +# +# source files +# +uams_guest_la_SOURCES = uams_guest.c +uams_randnum_la_SOURCES = uams_randnum.c +uams_passwd_la_SOURCES = uams_passwd.c +uams_pam_la_SOURCES = uams_pam.c +uams_pgp_la_SOURCES = uams_pgp.c +uams_dhx_passwd_la_SOURCES = uams_dhx_passwd.c +uams_dhx_pam_la_SOURCES = uams_dhx_pam.c +uams_dhx2_passwd_la_SOURCES = uams_dhx2_passwd.c +uams_dhx2_pam_la_SOURCES = uams_dhx2_pam.c +uams_gss_la_SOURCES = uams_gss.c + +# +# flags +# + +# these should be sorted out, applying both to AM_CFLAGS is senseless +AM_CFLAGS = @SSL_CFLAGS@ @LIBGCRYPT_CFLAGS@ +uams_pam_la_CFLAGS = @PAM_CFLAGS@ +uams_dhx_pam_la_CFLAGS = @SSL_CFLAGS@ @PAM_CFLAGS@ +uams_dhx2_pam_la_CFLAGS = @LIBGCRYPT_CFLAGS@ @PAM_CFLAGS@ +uams_gss_la_CFLAGS = @GSSAPI_CFLAGS@ @KRB5_CFLAGS@ +uams_guest_la_LDFLAGS = -module -avoid-version +uams_randnum_la_LDFLAGS = -module -avoid-version @SSL_LIBS@ +uams_passwd_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ +uams_pam_la_LDFLAGS = -module -avoid-version @PAM_LIBS@ +uams_pgp_la_LDFLAGS = -module -avoid-version @SSL_LIBS@ +uams_dhx_passwd_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ @SSL_LIBS@ +uams_dhx_pam_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ @SSL_LIBS@ @PAM_LIBS@ +uams_dhx2_passwd_la_LDFLAGS = -module -avoid-version @CRYPT_LIBS@ @LIBGCRYPT_LIBS@ +uams_dhx2_pam_la_LDFLAGS = -module -avoid-version @LIBGCRYPT_LIBS@ @PAM_LIBS@ +uams_gss_la_LDFLAGS = -module -avoid-version @GSSAPI_LIBS@ @KRB5_LIBS@ + +# +# module compilation +# +uamsdir = @UAMS_PATH@ +uams_LTLIBRARIES = \ + $(UAMS_GENERIC) \ + $(UAMS_PGP) \ + $(UAMS_PAM) \ + $(UAMS_RANDNUM) \ + $(UAMS_DHX) \ + $(UAMS_DHX_PAM) \ + $(UAMS_DHX2) \ + $(UAMS_DHX2_PAM) \ + $(UAMS_GSSAPI) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign etc/uams/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign etc/uams/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-uamsLTLIBRARIES: $(uams_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(uams_LTLIBRARIES)'; test -n "$(uamsdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(uamsdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(uamsdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(uamsdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(uamsdir)"; \ + } + +uninstall-uamsLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(uams_LTLIBRARIES)'; test -n "$(uamsdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(uamsdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(uamsdir)/$$f"; \ + done + +clean-uamsLTLIBRARIES: + -test -z "$(uams_LTLIBRARIES)" || rm -f $(uams_LTLIBRARIES) + @list='$(uams_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +uams_dhx2_pam.la: $(uams_dhx2_pam_la_OBJECTS) $(uams_dhx2_pam_la_DEPENDENCIES) $(EXTRA_uams_dhx2_pam_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_dhx2_pam_la_LINK) $(am_uams_dhx2_pam_la_rpath) $(uams_dhx2_pam_la_OBJECTS) $(uams_dhx2_pam_la_LIBADD) $(LIBS) +uams_dhx2_passwd.la: $(uams_dhx2_passwd_la_OBJECTS) $(uams_dhx2_passwd_la_DEPENDENCIES) $(EXTRA_uams_dhx2_passwd_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_dhx2_passwd_la_LINK) $(am_uams_dhx2_passwd_la_rpath) $(uams_dhx2_passwd_la_OBJECTS) $(uams_dhx2_passwd_la_LIBADD) $(LIBS) +uams_dhx_pam.la: $(uams_dhx_pam_la_OBJECTS) $(uams_dhx_pam_la_DEPENDENCIES) $(EXTRA_uams_dhx_pam_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_dhx_pam_la_LINK) $(am_uams_dhx_pam_la_rpath) $(uams_dhx_pam_la_OBJECTS) $(uams_dhx_pam_la_LIBADD) $(LIBS) +uams_dhx_passwd.la: $(uams_dhx_passwd_la_OBJECTS) $(uams_dhx_passwd_la_DEPENDENCIES) $(EXTRA_uams_dhx_passwd_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_dhx_passwd_la_LINK) $(am_uams_dhx_passwd_la_rpath) $(uams_dhx_passwd_la_OBJECTS) $(uams_dhx_passwd_la_LIBADD) $(LIBS) +uams_gss.la: $(uams_gss_la_OBJECTS) $(uams_gss_la_DEPENDENCIES) $(EXTRA_uams_gss_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_gss_la_LINK) $(am_uams_gss_la_rpath) $(uams_gss_la_OBJECTS) $(uams_gss_la_LIBADD) $(LIBS) +uams_guest.la: $(uams_guest_la_OBJECTS) $(uams_guest_la_DEPENDENCIES) $(EXTRA_uams_guest_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_guest_la_LINK) -rpath $(uamsdir) $(uams_guest_la_OBJECTS) $(uams_guest_la_LIBADD) $(LIBS) +uams_pam.la: $(uams_pam_la_OBJECTS) $(uams_pam_la_DEPENDENCIES) $(EXTRA_uams_pam_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_pam_la_LINK) $(am_uams_pam_la_rpath) $(uams_pam_la_OBJECTS) $(uams_pam_la_LIBADD) $(LIBS) +uams_passwd.la: $(uams_passwd_la_OBJECTS) $(uams_passwd_la_DEPENDENCIES) $(EXTRA_uams_passwd_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_passwd_la_LINK) -rpath $(uamsdir) $(uams_passwd_la_OBJECTS) $(uams_passwd_la_LIBADD) $(LIBS) +uams_pgp.la: $(uams_pgp_la_OBJECTS) $(uams_pgp_la_DEPENDENCIES) $(EXTRA_uams_pgp_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_pgp_la_LINK) $(am_uams_pgp_la_rpath) $(uams_pgp_la_OBJECTS) $(uams_pgp_la_LIBADD) $(LIBS) +uams_randnum.la: $(uams_randnum_la_OBJECTS) $(uams_randnum_la_DEPENDENCIES) $(EXTRA_uams_randnum_la_DEPENDENCIES) + $(AM_V_CCLD)$(uams_randnum_la_LINK) $(am_uams_randnum_la_rpath) $(uams_randnum_la_OBJECTS) $(uams_randnum_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_dhx2_pam_la-uams_dhx2_pam.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_dhx2_passwd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_dhx_pam_la-uams_dhx_pam.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_dhx_passwd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_gss_la-uams_gss.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_guest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_pam_la-uams_pam.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_passwd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_pgp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uams_randnum.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +uams_dhx2_pam_la-uams_dhx2_pam.lo: uams_dhx2_pam.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_dhx2_pam_la_CFLAGS) $(CFLAGS) -MT uams_dhx2_pam_la-uams_dhx2_pam.lo -MD -MP -MF $(DEPDIR)/uams_dhx2_pam_la-uams_dhx2_pam.Tpo -c -o uams_dhx2_pam_la-uams_dhx2_pam.lo `test -f 'uams_dhx2_pam.c' || echo '$(srcdir)/'`uams_dhx2_pam.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/uams_dhx2_pam_la-uams_dhx2_pam.Tpo $(DEPDIR)/uams_dhx2_pam_la-uams_dhx2_pam.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uams_dhx2_pam.c' object='uams_dhx2_pam_la-uams_dhx2_pam.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_dhx2_pam_la_CFLAGS) $(CFLAGS) -c -o uams_dhx2_pam_la-uams_dhx2_pam.lo `test -f 'uams_dhx2_pam.c' || echo '$(srcdir)/'`uams_dhx2_pam.c + +uams_dhx_pam_la-uams_dhx_pam.lo: uams_dhx_pam.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_dhx_pam_la_CFLAGS) $(CFLAGS) -MT uams_dhx_pam_la-uams_dhx_pam.lo -MD -MP -MF $(DEPDIR)/uams_dhx_pam_la-uams_dhx_pam.Tpo -c -o uams_dhx_pam_la-uams_dhx_pam.lo `test -f 'uams_dhx_pam.c' || echo '$(srcdir)/'`uams_dhx_pam.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/uams_dhx_pam_la-uams_dhx_pam.Tpo $(DEPDIR)/uams_dhx_pam_la-uams_dhx_pam.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uams_dhx_pam.c' object='uams_dhx_pam_la-uams_dhx_pam.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_dhx_pam_la_CFLAGS) $(CFLAGS) -c -o uams_dhx_pam_la-uams_dhx_pam.lo `test -f 'uams_dhx_pam.c' || echo '$(srcdir)/'`uams_dhx_pam.c + +uams_gss_la-uams_gss.lo: uams_gss.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_gss_la_CFLAGS) $(CFLAGS) -MT uams_gss_la-uams_gss.lo -MD -MP -MF $(DEPDIR)/uams_gss_la-uams_gss.Tpo -c -o uams_gss_la-uams_gss.lo `test -f 'uams_gss.c' || echo '$(srcdir)/'`uams_gss.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/uams_gss_la-uams_gss.Tpo $(DEPDIR)/uams_gss_la-uams_gss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uams_gss.c' object='uams_gss_la-uams_gss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_gss_la_CFLAGS) $(CFLAGS) -c -o uams_gss_la-uams_gss.lo `test -f 'uams_gss.c' || echo '$(srcdir)/'`uams_gss.c + +uams_pam_la-uams_pam.lo: uams_pam.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_pam_la_CFLAGS) $(CFLAGS) -MT uams_pam_la-uams_pam.lo -MD -MP -MF $(DEPDIR)/uams_pam_la-uams_pam.Tpo -c -o uams_pam_la-uams_pam.lo `test -f 'uams_pam.c' || echo '$(srcdir)/'`uams_pam.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/uams_pam_la-uams_pam.Tpo $(DEPDIR)/uams_pam_la-uams_pam.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uams_pam.c' object='uams_pam_la-uams_pam.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uams_pam_la_CFLAGS) $(CFLAGS) -c -o uams_pam_la-uams_pam.lo `test -f 'uams_pam.c' || echo '$(srcdir)/'`uams_pam.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(uamsdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-uamsLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-uamsLTLIBRARIES + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-uamsLTLIBRARIES + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: install-am install-data-am install-strip uninstall-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-uamsLTLIBRARIES cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-data-hook install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip install-uamsLTLIBRARIES \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-hook \ + uninstall-uamsLTLIBRARIES + + +# +# link creation +# + +install-data-hook: + (if [ -d $(DESTDIR)$(uamsdir) ] ; then \ + cd $(DESTDIR)$(uamsdir) && \ + rm -f $(uams_LINKS) && \ + $(LN_S) $(UAMS_CLRTXT_LINK) uams_clrtxt.so && \ + $(dhx_exec_hook) && \ + $(dhx2_exec_hook) ; \ + fi) + +uninstall-hook: + (if [ -d $(DESTDIR)$(uamsdir) ] ; then \ + cd $(DESTDIR)$(uamsdir) && \ + rm -f $(uams_LINKS) ; \ + fi) + +# 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/etc/uams/uams_dhx2_pam.c b/etc/uams/uams_dhx2_pam.c new file mode 100644 index 0000000..8e79b45 --- /dev/null +++ b/etc/uams/uams_dhx2_pam.c @@ -0,0 +1,968 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if defined (USE_PAM) && defined (UAM_DHX2) +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#ifdef HAVE_SECURITY_PAM_APPL_H +#include +#endif +#ifdef HAVE_PAM_PAM_APPL_H +#include +#endif + + +#ifdef HAVE_LIBGCRYPT +#include +#endif /* HAVE_LIBGCRYPT */ + +#include +#include +#include + +/* Number of bits for p which we generate. Everybode out there uses 512, so we beet them */ +#define PRIMEBITS 1024 + +/* hash a number to a 16-bit quantity */ +#define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \ + (unsigned long) (a)) & 0xffff) + +/* Some parameters need be maintained across calls */ +static gcry_mpi_t p, g, Ra; +static gcry_mpi_t serverNonce; +static char *K_MD5hash = NULL; +static int K_hash_len; +static uint16_t ID; + +/* The initialization vectors for CAST128 are fixed by Apple. */ +static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' }; +static unsigned char dhx_s2civ[] = { 'C', 'J', 'a', 'l', 'b', 'e', 'r', 't' }; + +/* Static variables used to communicate between the conversation function + * and the server_login function */ +static pam_handle_t *pamh = NULL; +static char *PAM_username; +static char *PAM_password; +static struct passwd *dhxpwd; + +/********************************************************* + * Crypto helper func to generate p and g for use in DH. + * libgcrypt doesn't provide one directly. + * Algorithm taken from GNUTLS:gnutls_dh_primes.c + *********************************************************/ + +/** + * This function will generate a new pair of prime and generator for use in + * the Diffie-Hellman key exchange. + * The bits value should be one of 768, 1024, 2048, 3072 or 4096. + **/ +static int dh_params_generate (unsigned int bits) { + + int result, times = 0, qbits; + gcry_mpi_t *factors = NULL; + gcry_error_t err; + + /* Version check should be the very first call because it + makes sure that important subsystems are intialized. */ + if (!gcry_check_version (GCRYPT_VERSION)) { + LOG(log_error, logtype_uams, "PAM DHX2: libgcrypt versions mismatch. Need: %s", GCRYPT_VERSION); + result = AFPERR_MISC; + goto error; + } + + if (bits < 256) + qbits = bits / 2; + else + qbits = (bits / 40) + 105; + + if (qbits & 1) /* better have an even number */ + qbits++; + + /* find a prime number of size bits. */ + do { + if (times) { + gcry_mpi_release(p); + gcry_prime_release_factors (factors); + } + err = gcry_prime_generate(&p, bits, qbits, &factors, NULL, NULL, + GCRY_STRONG_RANDOM, GCRY_PRIME_FLAG_SPECIAL_FACTOR); + if (err != 0) { + result = AFPERR_MISC; + goto error; + } + err = gcry_prime_check(p, 0); + times++; + } while (err != 0 && times < 10); + + if (err != 0) { + result = AFPERR_MISC; + goto error; + } + + /* generate the group generator. */ + err = gcry_prime_group_generator(&g, p, factors, NULL); + if (err != 0) { + result = AFPERR_MISC; + goto error; + } + + gcry_prime_release_factors(factors); + + return 0; + +error: + gcry_prime_release_factors(factors); + + return result; +} + + +/* PAM conversation function + * Here we assume (for now, at least) that echo on means login name, and + * echo off means password. + */ +static int PAM_conv (int num_msg, +#ifdef LINUX + const struct pam_message **msg, +#else + struct pam_message **msg, +#endif + struct pam_response **resp, + void *appdata_ptr _U_) { + int count = 0; + struct pam_response *reply; + +#define COPY_STRING(s) (s) ? strdup(s) : NULL + + errno = 0; + + if (num_msg < 1) { + /* Log Entry */ + LOG(log_info, logtype_uams, "PAM DHX2 Conversation Err -- %s", + strerror(errno)); + /* Log Entry */ + return PAM_CONV_ERR; + } + + reply = (struct pam_response *) + calloc(num_msg, sizeof(struct pam_response)); + + if (!reply) { + /* Log Entry */ + LOG(log_info, logtype_uams, "PAM DHX2: Conversation Err -- %s", + strerror(errno)); + /* Log Entry */ + return PAM_CONV_ERR; + } + + for (count = 0; count < num_msg; count++) { + char *string = NULL; + + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + if (!(string = COPY_STRING(PAM_username))) { + /* Log Entry */ + LOG(log_info, logtype_uams, "PAM DHX2: username failure -- %s", + strerror(errno)); + /* Log Entry */ + goto pam_fail_conv; + } + break; + case PAM_PROMPT_ECHO_OFF: + if (!(string = COPY_STRING(PAM_password))) { + /* Log Entry */ + LOG(log_info, logtype_uams, "PAM DHX2: passwd failure: --: %s", + strerror(errno)); + /* Log Entry */ + goto pam_fail_conv; + } + break; + case PAM_TEXT_INFO: +#ifdef PAM_BINARY_PROMPT + case PAM_BINARY_PROMPT: +#endif /* PAM_BINARY_PROMPT */ + /* ignore it... */ + break; + case PAM_ERROR_MSG: + default: + LOG(log_info, logtype_uams, "PAM DHX2: Binary_Prompt -- %s", strerror(errno)); + goto pam_fail_conv; + } + + if (string) { + reply[count].resp_retcode = 0; + reply[count].resp = string; + string = NULL; + } + } + + *resp = reply; + LOG(log_info, logtype_uams, "PAM DHX2: PAM Success"); + return PAM_SUCCESS; + +pam_fail_conv: + for (count = 0; count < num_msg; count++) { + if (!reply[count].resp) + continue; + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + case PAM_PROMPT_ECHO_ON: + free(reply[count].resp); + break; + } + } + free(reply); + /* Log Entry */ + LOG(log_info, logtype_uams, "PAM DHX2: Conversation Err -- %s", + strerror(errno)); + /* Log Entry */ + return PAM_CONV_ERR; +} + +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + + +static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ + int ret; + size_t nwritten; + gcry_mpi_t Ma; + char *Ra_binary = NULL; + uint16_t uint16; + + *rbuflen = 0; + + Ra = gcry_mpi_new(0); + Ma = gcry_mpi_new(0); + + /* Generate our random number Ra. */ + Ra_binary = calloc(1, PRIMEBITS/8); + if (Ra_binary == NULL) { + ret = AFPERR_MISC; + goto error; + } + gcry_randomize(Ra_binary, PRIMEBITS/8, GCRY_STRONG_RANDOM); + gcry_mpi_scan(&Ra, GCRYMPI_FMT_USG, Ra_binary, PRIMEBITS/8, NULL); + free(Ra_binary); + Ra_binary = NULL; + + /* Ma = g^Ra mod p. This is our "public" key */ + gcry_mpi_powm(Ma, g, Ra, p); + + /* ------- DH Init done ------ */ + /* Start building reply packet */ + + /* Session ID first */ + ID = dhxhash(obj); + uint16 = htons(ID); + memcpy(rbuf, &uint16, sizeof(uint16_t)); + rbuf += 2; + *rbuflen += 2; + + /* g is next */ + gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, 4, &nwritten, g); + if (nwritten < 4) { + memmove( rbuf+4-nwritten, rbuf, nwritten); + memset( rbuf, 0, 4-nwritten); + } + rbuf += 4; + *rbuflen += 4; + + /* len = length of p = PRIMEBITS/8 */ + + uint16 = htons((uint16_t) PRIMEBITS/8); + memcpy(rbuf, &uint16, sizeof(uint16_t)); + rbuf += 2; + *rbuflen += 2; + + /* p */ + gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, PRIMEBITS/8, NULL, p); + rbuf += PRIMEBITS/8; + *rbuflen += PRIMEBITS/8; + + /* Ma */ + gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, PRIMEBITS/8, &nwritten, Ma); + if (nwritten < PRIMEBITS/8) { + memmove(rbuf + (PRIMEBITS/8) - nwritten, rbuf, nwritten); + memset(rbuf, 0, (PRIMEBITS/8) - nwritten); + } + rbuf += PRIMEBITS/8; + *rbuflen += PRIMEBITS/8; + + ret = AFPERR_AUTHCONT; + +error: /* We exit here anyway */ + /* We will need Ra later, but mustn't forget to release it ! */ + gcry_mpi_release(Ma); + return ret; +} + +/* -------------------------------- */ +static int login(void *obj, char *username, int ulen, struct passwd **uam_pwd _U_, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + if (( dhxpwd = uam_getname(obj, username, ulen)) == NULL ) { + LOG(log_info, logtype_uams, "DHX2: unknown username"); + return AFPERR_NOTAUTH; + } + + PAM_username = username; + LOG(log_info, logtype_uams, "DHX2 login: %s", username); + return dhx2_setup(obj, ibuf, ibuflen, rbuf, rbuflen); +} + +/* -------------------------------- */ +/* dhx login: things are done in a slightly bizarre order to avoid + * having to clean things up if there's an error. */ +static int pam_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + + *rbuflen = 0; + + /* grab some of the options */ + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) { + LOG(log_info, logtype_uams, "DHX2: uam_afpserver_option didn't meet uam_option_username -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + len = (unsigned char) *ibuf++; + if ( len > ulen ) { + LOG(log_info, logtype_uams, "DHX2: Signature Retieval Failure -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + memcpy(username, ibuf, len ); + ibuf += len; + username[ len ] = '\0'; + + if ((unsigned long) ibuf & 1) /* pad to even boundary */ + ++ibuf; + + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* ----------------------------- */ +static int pam_login_ext(void *obj, char *uname, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + uint16_t temp16; + + *rbuflen = 0; + + /* grab some of the options */ + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) { + LOG(log_info, logtype_uams, "DHX2: uam_afpserver_option didn't meet uam_option_username -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + if (*uname != 3) + return AFPERR_PARAM; + uname++; + memcpy(&temp16, uname, sizeof(temp16)); + len = ntohs(temp16); + + if ( !len || len > ulen ) { + LOG(log_info, logtype_uams, "DHX2: Signature Retrieval Failure -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + memcpy(username, uname +2, len ); + username[ len ] = '\0'; + + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* -------------------------------- */ +static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + int ret; + size_t nwritten; + gcry_mpi_t Mb, K, clientNonce; + unsigned char *K_bin = NULL; + char serverNonce_bin[16]; + gcry_cipher_hd_t ctx; + gcry_error_t ctxerror; + uint16_t uint16; + + *rbuflen = 0; + + Mb = gcry_mpi_new(0); + K = gcry_mpi_new(0); + clientNonce = gcry_mpi_new(0); + serverNonce = gcry_mpi_new(0); + + /* Packet size should be: Session ID + Ma + Encrypted client nonce */ + if (ibuflen != 2 + PRIMEBITS/8 + 16) { + LOG(log_error, logtype_uams, "DHX2: Paket length not correct"); + ret = AFPERR_PARAM; + goto error_noctx; + } + + /* Skip session id */ + ibuf += 2; + + /* Extract Mb, client's "public" key */ + gcry_mpi_scan(&Mb, GCRYMPI_FMT_USG, ibuf, PRIMEBITS/8, NULL); + ibuf += PRIMEBITS/8; + + /* Now finally generate the Key: K = Mb^Ra mod p */ + gcry_mpi_powm(K, Mb, Ra, p); + + /* We need K in binary form in order to ... */ + K_bin = calloc(1, PRIMEBITS/8); + if (K_bin == NULL) { + ret = AFPERR_MISC; + goto error_noctx; + } + gcry_mpi_print(GCRYMPI_FMT_USG, K_bin, PRIMEBITS/8, &nwritten, K); + if (nwritten < PRIMEBITS/8) { + memmove(K_bin + PRIMEBITS/8 - nwritten, K_bin, nwritten); + memset(K_bin, 0, PRIMEBITS/8 - nwritten); + } + + /* ... generate the MD5 hash of K. K_MD5hash is what we actually use ! */ + K_MD5hash = calloc(1, K_hash_len = gcry_md_get_algo_dlen(GCRY_MD_MD5)); + if (K_MD5hash == NULL) { + ret = AFPERR_MISC; + goto error_noctx; + } + gcry_md_hash_buffer(GCRY_MD_MD5, K_MD5hash, K_bin, PRIMEBITS/8); + free(K_bin); + K_bin = NULL; + + /* FIXME: To support the Reconnect UAM, we need to store this key somewhere */ + + /* Set up our encryption context. */ + ctxerror = gcry_cipher_open( &ctx, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set key */ + ctxerror = gcry_cipher_setkey(ctx, K_MD5hash, K_hash_len); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set the initialization vector for client->server transfer. */ + ctxerror = gcry_cipher_setiv(ctx, dhx_c2siv, sizeof(dhx_c2siv)); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Finally: decrypt client's md5_K(client nonce, C2SIV) inplace */ + ctxerror = gcry_cipher_decrypt(ctx, ibuf, 16, NULL, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Pull out clients nonce */ + gcry_mpi_scan(&clientNonce, GCRYMPI_FMT_USG, ibuf, 16, NULL); + /* Increment nonce */ + gcry_mpi_add_ui(clientNonce, clientNonce, 1); + + /* Generate our nonce and remember it for Logincont2 */ + gcry_create_nonce(serverNonce_bin, 16); /* We'll use this here */ + gcry_mpi_scan(&serverNonce, GCRYMPI_FMT_USG, serverNonce_bin, 16, NULL); /* For use in Logincont2 */ + + /* ---- Start building reply packet ---- */ + + /* Session ID + 1 first */ + uint16 = htons(ID+1); + memcpy(rbuf, &uint16, sizeof(uint16_t)); + rbuf += 2; + *rbuflen += 2; + + /* Client nonce + 1 */ + gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char *)rbuf, PRIMEBITS/8, NULL, clientNonce); + /* Server nonce */ + memcpy(rbuf+16, serverNonce_bin, 16); + + /* Set the initialization vector for server->client transfer. */ + ctxerror = gcry_cipher_setiv(ctx, dhx_s2civ, sizeof(dhx_s2civ)); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Encrypt md5_K(clientNonce+1, serverNonce) inplace */ + ctxerror = gcry_cipher_encrypt(ctx, rbuf, 32, NULL, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + rbuf += 32; + *rbuflen += 32; + + ret = AFPERR_AUTHCONT; + goto exit; + +error_ctx: + gcry_cipher_close(ctx); +error_noctx: + gcry_mpi_release(serverNonce); + free(K_MD5hash); + K_MD5hash=NULL; +exit: + gcry_mpi_release(K); + gcry_mpi_release(Mb); + gcry_mpi_release(Ra); + gcry_mpi_release(clientNonce); + return ret; +} + +/** + * Try to authenticate via PAM as "adminauthuser" + **/ +static int loginasroot(const char *adminauthuser, const char **hostname, int status) +{ + int PAM_error; + + if ((PAM_error = pam_end(pamh, status)) != PAM_SUCCESS) + goto exit; + pamh = NULL; + + if ((PAM_error = pam_start("netatalk", adminauthuser, &PAM_conversation, &pamh)) != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error)); + goto exit; + } + + /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */ + pam_set_item(pamh, PAM_TTY, "afpd"); + pam_set_item(pamh, PAM_RHOST, *hostname); + if ((PAM_error = pam_authenticate(pamh, 0)) != PAM_SUCCESS) + goto exit; + + LOG(log_warning, logtype_uams, "DHX2: Authenticated as \"%s\"", adminauthuser); + +exit: + return PAM_error; +} + +static int logincont2(void *obj_in, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf _U_, size_t *rbuflen) +{ + AFPObj *obj = obj_in; + int ret = AFPERR_MISC; + int PAM_error; + const char *hostname = NULL; + gcry_mpi_t retServerNonce; + gcry_cipher_hd_t ctx; + gcry_error_t ctxerror; + char *utfpass = NULL; + + *rbuflen = 0; + + /* Packet size should be: Session ID + ServerNonce + Passwd buffer (evantually +10 extra bytes, see Apples Docs) */ + if ((ibuflen != 2 + 16 + 256) && (ibuflen != 2 + 16 + 256 + 10)) { + LOG(log_error, logtype_uams, "DHX2: Paket length not correct: %u. Should be 274 or 284.", ibuflen); + ret = AFPERR_PARAM; + goto error_noctx; + } + + retServerNonce = gcry_mpi_new(0); + + /* For PAM */ + uam_afpserver_option(obj, UAM_OPTION_CLIENTNAME, (void *) &hostname, NULL); + + /* Set up our encryption context. */ + ctxerror = gcry_cipher_open( &ctx, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set key */ + ctxerror = gcry_cipher_setkey(ctx, K_MD5hash, K_hash_len); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set the initialization vector for client->server transfer. */ + ctxerror = gcry_cipher_setiv(ctx, dhx_c2siv, sizeof(dhx_c2siv)); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + + /* Skip Session ID */ + ibuf += 2; + + /* Finally: decrypt client's md5_K(serverNonce+1, passwor, C2SIV) inplace */ + ctxerror = gcry_cipher_decrypt(ctx, ibuf, 16+256, NULL, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Pull out nonce. Should be serverNonce+1 */ + gcry_mpi_scan(&retServerNonce, GCRYMPI_FMT_USG, ibuf, 16, NULL); + gcry_mpi_sub_ui(retServerNonce, retServerNonce, 1); + if ( gcry_mpi_cmp( serverNonce, retServerNonce) != 0) { + /* We're hacked! */ + ret = AFPERR_NOTAUTH; + goto error_ctx; + } + ibuf += 16; + + /* ---- Start authentication with PAM --- */ + + /* The password is in legacy Mac encoding, convert it to host encoding */ + if (convert_string_allocate(CH_MAC, CH_UNIX, ibuf, -1, &utfpass) == (size_t)-1) { + LOG(log_error, logtype_uams, "DHX2: conversion error"); + goto error_ctx; + } + PAM_password = utfpass; + +#ifdef DEBUG + LOG(log_maxdebug, logtype_default, "DHX2: password: %s", PAM_password); +#endif + + /* Set these things up for the conv function */ + + ret = AFPERR_NOTAUTH; + PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, &pamh); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error)); + goto error_ctx; + } + + /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */ + pam_set_item(pamh, PAM_TTY, "afpd"); + pam_set_item(pamh, PAM_RHOST, hostname); + pam_set_item(pamh, PAM_RUSER, PAM_username); + + PAM_error = pam_authenticate(pamh, 0); + if (PAM_error != PAM_SUCCESS) { + if (PAM_error == PAM_MAXTRIES) + ret = AFPERR_PWDEXPR; + LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh, PAM_error)); + + if (!obj->options.adminauthuser) + goto error_ctx; + if (loginasroot(obj->options.adminauthuser, &hostname, PAM_error) != PAM_SUCCESS) { + goto error_ctx; + } + } + + PAM_error = pam_acct_mgmt(pamh, 0); + if (PAM_error != PAM_SUCCESS ) { + LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", + pam_strerror(pamh, PAM_error)); + if (PAM_error == PAM_NEW_AUTHTOK_REQD) /* password expired */ + ret = AFPERR_PWDEXPR; +#ifdef PAM_AUTHTOKEN_REQD + else if (PAM_error == PAM_AUTHTOKEN_REQD) + ret = AFPERR_PWDCHNG; +#endif + goto error_ctx; + } + +#ifndef PAM_CRED_ESTABLISH +#define PAM_CRED_ESTABLISH PAM_ESTABLISH_CRED +#endif + PAM_error = pam_setcred(pamh, PAM_CRED_ESTABLISH); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", + pam_strerror(pamh, PAM_error)); + goto error_ctx; + } + + PAM_error = pam_open_session(pamh, 0); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", + pam_strerror(pamh, PAM_error)); + goto error_ctx; + } + + memset(ibuf, 0, 256); /* zero out the password */ + if (utfpass) + memset(utfpass, 0, strlen(utfpass)); + *uam_pwd = dhxpwd; + LOG(log_info, logtype_uams, "DHX2: PAM Auth OK!"); + + ret = AFP_OK; + +error_ctx: + gcry_cipher_close(ctx); +error_noctx: + if (utfpass) free(utfpass); + free(K_MD5hash); + K_MD5hash=NULL; + gcry_mpi_release(serverNonce); + gcry_mpi_release(retServerNonce); + return ret; +} + +static int pam_logincont(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + uint16_t retID; + int ret; + + /* check for session id */ + memcpy(&retID, ibuf, sizeof(uint16_t)); + retID = ntohs(retID); + if (retID == ID) + ret = logincont1(obj, ibuf, ibuflen, rbuf, rbuflen); + else if (retID == ID+1) + ret = logincont2(obj, uam_pwd, ibuf,ibuflen, rbuf, rbuflen); + else { + LOG(log_info, logtype_uams, "DHX2: Session ID Mismatch"); + ret = AFPERR_PARAM; + } + return ret; +} + + +/* logout */ +static void pam_logout(void) { + pam_close_session(pamh, 0); + pam_end(pamh, 0); + pamh = NULL; +} + +/**************************** + * --- Change pwd stuff --- */ + +static int changepw_1(void *obj, char *uname, + char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + *rbuflen = 0; + + /* Remember it now, use it in changepw_3 */ + PAM_username = uname; + return( dhx2_setup(obj, ibuf, ibuflen, rbuf, rbuflen) ); +} + +static int changepw_2(void *obj, + char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) +{ + return( logincont1(obj, ibuf, ibuflen, rbuf, rbuflen) ); +} + +static int changepw_3(void *obj _U_, + char *ibuf, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen _U_) +{ + int ret; + int PAM_error; + uid_t uid; + pam_handle_t *lpamh; + const char *hostname = NULL; + gcry_mpi_t retServerNonce; + gcry_cipher_hd_t ctx; + gcry_error_t ctxerror; + + *rbuflen = 0; + + LOG(log_error, logtype_uams, "DHX2 ChangePW: packet 3 processing"); + + /* Packet size should be: Session ID + ServerNonce + 2*Passwd buffer */ + if (ibuflen != 2 + 16 + 2*256) { + LOG(log_error, logtype_uams, "DHX2: Paket length not correct"); + ret = AFPERR_PARAM; + goto error_noctx; + } + + retServerNonce = gcry_mpi_new(0); + + /* For PAM */ + uam_afpserver_option(obj, UAM_OPTION_CLIENTNAME, (void *) &hostname, NULL); + + /* Set up our encryption context. */ + ctxerror = gcry_cipher_open( &ctx, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set key */ + ctxerror = gcry_cipher_setkey(ctx, K_MD5hash, K_hash_len); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + + /* Set the initialization vector for client->server transfer. */ + ctxerror = gcry_cipher_setiv(ctx, dhx_c2siv, sizeof(dhx_c2siv)); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + + /* Skip Session ID */ + ibuf += 2; + + /* Finally: decrypt client's md5_K(serverNonce+1, 2*password, C2SIV) inplace */ + ctxerror = gcry_cipher_decrypt(ctx, ibuf, 16+2*256, NULL, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Pull out nonce. Should be serverNonce+1 */ + gcry_mpi_scan(&retServerNonce, GCRYMPI_FMT_USG, ibuf, 16, NULL); + gcry_mpi_sub_ui(retServerNonce, retServerNonce, 1); + if ( gcry_mpi_cmp( serverNonce, retServerNonce) != 0) { + /* We're hacked! */ + ret = AFPERR_NOTAUTH; + goto error_ctx; + } + ibuf += 16; + + /* ---- Start pwd changing with PAM --- */ + ibuf[255] = '\0'; /* For safety */ + ibuf[511] = '\0'; + + /* check if new and old password are equal */ + if (memcmp(ibuf, ibuf + 256, 255) == 0) { + LOG(log_info, logtype_uams, "DHX2 Chgpwd: new and old password are equal"); + ret = AFPERR_PWDSAME; + goto error_ctx; + } + + /* Set these things up for the conv function. PAM_username was set in changepw_1 */ + PAM_password = ibuf + 256; + PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, &lpamh); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "DHX2 Chgpwd: PAM error in pam_start"); + ret = AFPERR_PARAM; + goto error_ctx; + } + pam_set_item(lpamh, PAM_TTY, "afpd"); + uam_afpserver_option(obj, UAM_OPTION_CLIENTNAME, (void *) &hostname, NULL); + pam_set_item(lpamh, PAM_RHOST, hostname); + uid = geteuid(); + seteuid(0); + PAM_error = pam_authenticate(lpamh,0); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "DHX2 Chgpwd: error authenticating with PAM"); + seteuid(uid); + pam_end(lpamh, PAM_error); + ret = AFPERR_NOTAUTH; + goto error_ctx; + } + PAM_password = ibuf; + PAM_error = pam_chauthtok(lpamh, 0); + seteuid(uid); /* un-root ourselves. */ + memset(ibuf, 0, 512); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "DHX2 Chgpwd: error changing pw with PAM"); + pam_end(lpamh, PAM_error); + ret = AFPERR_ACCESS; + goto error_ctx; + } + pam_end(lpamh, 0); + ret = AFP_OK; + +error_ctx: + gcry_cipher_close(ctx); +error_noctx: + free(K_MD5hash); + K_MD5hash=NULL; + gcry_mpi_release(serverNonce); + gcry_mpi_release(retServerNonce); + return ret; +} + +static int dhx2_changepw(void *obj _U_, char *uname, + struct passwd *pwd _U_, char *ibuf, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen _U_) +{ + /* We use this to serialize the three incoming FPChangePassword calls */ + static int dhx2_changepw_status = 1; + + int ret = AFPERR_NOTAUTH; /* gcc can't figure out it's always initialized */ + + switch (dhx2_changepw_status) { + case 1: + ret = changepw_1( obj, uname, ibuf, ibuflen, rbuf, rbuflen); + if ( ret == AFPERR_AUTHCONT) + dhx2_changepw_status = 2; + break; + case 2: + ret = changepw_2( obj, ibuf, ibuflen, rbuf, rbuflen); + if ( ret == AFPERR_AUTHCONT) + dhx2_changepw_status = 3; + else + dhx2_changepw_status = 1; + break; + case 3: + ret = changepw_3( obj, ibuf, ibuflen, rbuf, rbuflen); + dhx2_changepw_status = 1; /* Whether is was succesfull or not: we + restart anyway !*/ + break; + } + return ret; +} + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "DHX2", pam_login, + pam_logincont, pam_logout, pam_login_ext) < 0) + return -1; + if (uam_register(UAM_SERVER_CHANGEPW, path, "DHX2", dhx2_changepw) < 0) + return -1; + + LOG(log_debug, logtype_uams, "DHX2: generating mersenne primes"); + /* Generate p and g for DH */ + if (dh_params_generate(PRIMEBITS) != 0) { + LOG(log_error, logtype_uams, "DHX2: Couldn't generate p and g"); + return -1; + } + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "DHX2"); + uam_unregister(UAM_SERVER_CHANGEPW, "DHX2"); + + LOG(log_debug, logtype_uams, "DHX2: uam_cleanup"); + + gcry_mpi_release(p); + gcry_mpi_release(g); +} + +UAM_MODULE_EXPORT struct uam_export uams_dhx2 = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + + +UAM_MODULE_EXPORT struct uam_export uams_dhx2_pam = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + +#endif /* USE_PAM && UAM_DHX2 */ diff --git a/etc/uams/uams_dhx2_passwd.c b/etc/uams/uams_dhx2_passwd.c new file mode 100644 index 0000000..b74cc12 --- /dev/null +++ b/etc/uams/uams_dhx2_passwd.c @@ -0,0 +1,634 @@ +/* + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef UAM_DHX2 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CRYPT_H +#include +#endif + +#include +#include + +#ifdef SHADOWPW +#include +#endif + +#ifdef HAVE_LIBGCRYPT +#include +#endif + +#include +#include +#include + +/* Number of bits for p which we generate. Everybode out there uses 512, so we beet them */ +#define PRIMEBITS 1024 + +/* hash a number to a 16-bit quantity */ +#define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \ + (unsigned long) (a)) & 0xffff) + +/* Some parameters need be maintained across calls */ +static gcry_mpi_t p, Ra; +static gcry_mpi_t serverNonce; +static char *K_MD5hash = NULL; +static int K_hash_len; +static uint16_t ID; + +/* The initialization vectors for CAST128 are fixed by Apple. */ +static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' }; +static unsigned char dhx_s2civ[] = { 'C', 'J', 'a', 'l', 'b', 'e', 'r', 't' }; + +/* Static variables used to communicate between the conversation function + * and the server_login function */ +static struct passwd *dhxpwd; + +/********************************************************* + * Crypto helper func to generate p and g for use in DH. + * libgcrypt doesn't provide one directly. + * Algorithm taken from GNUTLS:gnutls_dh_primes.c + *********************************************************/ + +/** + * This function will generate a new pair of prime and generator for use in + * the Diffie-Hellman key exchange. + * The bits value should be one of 768, 1024, 2048, 3072 or 4096. + **/ + +static int +dh_params_generate (gcry_mpi_t *ret_p, gcry_mpi_t *ret_g, unsigned int bits) { + + int result, times = 0, qbits; + + gcry_mpi_t g = NULL, prime = NULL; + gcry_mpi_t *factors = NULL; + gcry_error_t err; + + /* Version check should be the very first call because it + makes sure that important subsystems are intialized. */ + if (!gcry_check_version (GCRYPT_VERSION)) { + LOG(log_info, logtype_uams, "PAM DHX2: libgcrypt versions mismatch. Need: %s", GCRYPT_VERSION); + result = AFPERR_MISC; + goto error; + } + + if (bits < 256) + qbits = bits / 2; + else + qbits = (bits / 40) + 105; + + if (qbits & 1) /* better have an even number */ + qbits++; + + /* find a prime number of size bits. */ + do { + if (times) { + gcry_mpi_release (prime); + gcry_prime_release_factors (factors); + } + err = gcry_prime_generate (&prime, bits, qbits, &factors, NULL, NULL, + GCRY_STRONG_RANDOM, GCRY_PRIME_FLAG_SPECIAL_FACTOR); + if (err != 0) { + result = AFPERR_MISC; + goto error; + } + err = gcry_prime_check (prime, 0); + times++; + } while (err != 0 && times < 10); + + if (err != 0) { + result = AFPERR_MISC; + goto error; + } + + /* generate the group generator. */ + err = gcry_prime_group_generator (&g, prime, factors, NULL); + if (err != 0) { + result = AFPERR_MISC; + goto error; + } + + gcry_prime_release_factors (factors); + factors = NULL; + + if (ret_g) + *ret_g = g; + else + gcry_mpi_release (g); + if (ret_p) + *ret_p = prime; + else + gcry_mpi_release (prime); + + return 0; + +error: + gcry_prime_release_factors (factors); + gcry_mpi_release (g); + gcry_mpi_release (prime); + + return result; +} + +static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ + int ret; + size_t nwritten; + gcry_mpi_t g, Ma; + char *Ra_binary = NULL; +#ifdef SHADOWPW + struct spwd *sp; +#endif /* SHADOWPW */ + uint16_t uint16; + + *rbuflen = 0; + + /* Initialize passwd/shadow */ +#ifdef SHADOWPW + if (( sp = getspnam( dhxpwd->pw_name )) == NULL ) { + LOG(log_info, logtype_uams, "DHX2: no shadow passwd entry for this user"); + return AFPERR_NOTAUTH; + } + dhxpwd->pw_passwd = sp->sp_pwdp; +#endif /* SHADOWPW */ + + if (!dhxpwd->pw_passwd) + return AFPERR_NOTAUTH; + + /* Initialize DH params */ + + p = gcry_mpi_new(0); + g = gcry_mpi_new(0); + Ra = gcry_mpi_new(0); + Ma = gcry_mpi_new(0); + + /* Generate p and g for DH */ + ret = dh_params_generate( &p, &g, PRIMEBITS); + if (ret != 0) { + LOG(log_info, logtype_uams, "DHX2: Couldn't generate p and g"); + ret = AFPERR_MISC; + goto error; + } + + /* Generate our random number Ra. */ + Ra_binary = calloc(1, PRIMEBITS/8); + if (Ra_binary == NULL) { + ret = AFPERR_MISC; + goto error; + } + gcry_randomize(Ra_binary, PRIMEBITS/8, GCRY_STRONG_RANDOM); + gcry_mpi_scan(&Ra, GCRYMPI_FMT_USG, Ra_binary, PRIMEBITS/8, NULL); + free(Ra_binary); + Ra_binary = NULL; + + /* Ma = g^Ra mod p. This is our "public" key */ + gcry_mpi_powm(Ma, g, Ra, p); + + /* ------- DH Init done ------ */ + /* Start building reply packet */ + + /* Session ID first */ + ID = dhxhash(obj); + uint16 = htons(ID); + memcpy(rbuf, &uint16, sizeof(uint16_t)); + rbuf += 2; + *rbuflen += 2; + + /* g is next */ + gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, 4, &nwritten, g); + if (nwritten < 4) { + memmove( rbuf+4-nwritten, rbuf, nwritten); + memset( rbuf, 0, 4-nwritten); + } + rbuf += 4; + *rbuflen += 4; + + /* len = length of p = PRIMEBITS/8 */ + uint16 = htons((uint16_t) PRIMEBITS/8); + memcpy(rbuf, &uint16, sizeof(uint16_t)); + rbuf += 2; + *rbuflen += 2; + + /* p */ + gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, PRIMEBITS/8, NULL, p); + rbuf += PRIMEBITS/8; + *rbuflen += PRIMEBITS/8; + + /* Ma */ + gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, PRIMEBITS/8, &nwritten, Ma); + if (nwritten < PRIMEBITS/8) { + memmove(rbuf + (PRIMEBITS/8) - nwritten, rbuf, nwritten); + memset(rbuf, 0, (PRIMEBITS/8) - nwritten); + } + rbuf += PRIMEBITS/8; + *rbuflen += PRIMEBITS/8; + + ret = AFPERR_AUTHCONT; + +error: /* We exit here anyway */ + /* We will only need p and Ra later, but mustn't forget to release it ! */ + gcry_mpi_release(g); + gcry_mpi_release(Ma); + return ret; +} + +/* -------------------------------- */ +static int login(void *obj, char *username, int ulen, struct passwd **uam_pwd _U_, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + if (( dhxpwd = uam_getname(obj, username, ulen)) == NULL ) { + LOG(log_info, logtype_uams, "DHX2: unknown username"); + return AFPERR_NOTAUTH; + } + + LOG(log_info, logtype_uams, "DHX2 login: %s", username); + return dhx2_setup(obj, ibuf, ibuflen, rbuf, rbuflen); +} + +/* -------------------------------- */ +/* dhx login: things are done in a slightly bizarre order to avoid + * having to clean things up if there's an error. */ +static int passwd_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + + *rbuflen = 0; + + /* grab some of the options */ + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) { + LOG(log_info, logtype_uams, "DHX2: uam_afpserver_option didn't meet uam_option_username -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + len = (unsigned char) *ibuf++; + if ( len > ulen ) { + LOG(log_info, logtype_uams, "DHX2: Signature Retieval Failure -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + memcpy(username, ibuf, len ); + ibuf += len; + username[ len ] = '\0'; + + if ((unsigned long) ibuf & 1) /* pad to even boundary */ + ++ibuf; + + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* ----------------------------- */ +static int passwd_login_ext(void *obj, char *uname, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + uint16_t temp16; + + *rbuflen = 0; + + /* grab some of the options */ + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) { + LOG(log_info, logtype_uams, "DHX2: uam_afpserver_option didn't meet uam_option_username -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + if (*uname != 3) + return AFPERR_PARAM; + uname++; + memcpy(&temp16, uname, sizeof(temp16)); + len = ntohs(temp16); + + if ( !len || len > ulen ) { + LOG(log_info, logtype_uams, "DHX2: Signature Retrieval Failure -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + memcpy(username, uname +2, len ); + username[ len ] = '\0'; + + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* -------------------------------- */ + +static int logincont1(void *obj _U_, struct passwd **uam_pwd _U_, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + size_t nwritten; + int ret; + gcry_mpi_t Mb, K, clientNonce; + unsigned char *K_bin = NULL; + char serverNonce_bin[16]; + gcry_cipher_hd_t ctx; + gcry_error_t ctxerror; + uint16_t uint16; + + *rbuflen = 0; + + Mb = gcry_mpi_new(0); + K = gcry_mpi_new(0); + clientNonce = gcry_mpi_new(0); + serverNonce = gcry_mpi_new(0); + + /* Packet size should be: Session ID + Ma + Encrypted client nonce */ + if (ibuflen != 2 + PRIMEBITS/8 + 16) { + LOG(log_error, logtype_uams, "DHX2: Paket length not correct"); + ret = AFPERR_PARAM; + goto error_noctx; + } + + /* Skip session id */ + ibuf += 2; + + /* Extract Mb, client's "public" key */ + gcry_mpi_scan(&Mb, GCRYMPI_FMT_USG, ibuf, PRIMEBITS/8, NULL); + ibuf += PRIMEBITS/8; + + /* Now finally generate the Key: K = Mb^Ra mod p */ + gcry_mpi_powm(K, Mb, Ra, p); + + /* We need K in binary form in order to ... */ + K_bin = calloc(1, PRIMEBITS/8); + if (K_bin == NULL) { + ret = AFPERR_MISC; + goto error_noctx; + } + gcry_mpi_print(GCRYMPI_FMT_USG, K_bin, PRIMEBITS/8, &nwritten, K); + if (nwritten < PRIMEBITS/8) { + memmove(K_bin + PRIMEBITS/8 - nwritten, K_bin, nwritten); + memset(K_bin, 0, PRIMEBITS/8 - nwritten); + } + + /* ... generate the MD5 hash of K. K_MD5hash is what we actually use ! */ + K_MD5hash = calloc(1, K_hash_len = gcry_md_get_algo_dlen(GCRY_MD_MD5)); + if (K_MD5hash == NULL) { + ret = AFPERR_MISC; + free(K_bin); + K_bin = NULL; + goto error_noctx; + } + gcry_md_hash_buffer(GCRY_MD_MD5, K_MD5hash, K_bin, PRIMEBITS/8); + free(K_bin); + K_bin = NULL; + + /* FIXME: To support the Reconnect UAM, we need to store this key somewhere */ + + /* Set up our encryption context. */ + ctxerror = gcry_cipher_open( &ctx, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set key */ + ctxerror = gcry_cipher_setkey(ctx, K_MD5hash, K_hash_len); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set the initialization vector for client->server transfer. */ + ctxerror = gcry_cipher_setiv(ctx, dhx_c2siv, sizeof(dhx_c2siv)); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Finally: decrypt client's md5_K(client nonce, C2SIV) inplace */ + ctxerror = gcry_cipher_decrypt(ctx, ibuf, 16, NULL, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Pull out clients nonce */ + gcry_mpi_scan(&clientNonce, GCRYMPI_FMT_USG, ibuf, 16, NULL); + /* Increment nonce */ + gcry_mpi_add_ui(clientNonce, clientNonce, 1); + + /* Generate our nonce and remember it for Logincont2 */ + gcry_create_nonce(serverNonce_bin, 16); /* We'll use this here */ + gcry_mpi_scan(&serverNonce, GCRYMPI_FMT_USG, serverNonce_bin, 16, NULL); /* For use in Logincont2 */ + + /* ---- Start building reply packet ---- */ + + /* Session ID + 1 first */ + uint16 = htons(ID+1); + memcpy(rbuf, &uint16, sizeof(uint16_t)); + rbuf += 2; + *rbuflen += 2; + + /* Client nonce + 1 */ + gcry_mpi_print(GCRYMPI_FMT_USG, (unsigned char *)rbuf, PRIMEBITS/8, NULL, clientNonce); + /* Server nonce */ + memcpy(rbuf+16, serverNonce_bin, 16); + + /* Set the initialization vector for server->client transfer. */ + ctxerror = gcry_cipher_setiv(ctx, dhx_s2civ, sizeof(dhx_s2civ)); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Encrypt md5_K(clientNonce+1, serverNonce) inplace */ + ctxerror = gcry_cipher_encrypt(ctx, rbuf, 32, NULL, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + rbuf += 32; + *rbuflen += 32; + + ret = AFPERR_AUTHCONT; + goto exit; + +error_ctx: + gcry_cipher_close(ctx); +error_noctx: + gcry_mpi_release(serverNonce); + free(K_MD5hash); + K_MD5hash=NULL; +exit: + gcry_mpi_release(K); + gcry_mpi_release(Mb); + gcry_mpi_release(Ra); + gcry_mpi_release(p); + gcry_mpi_release(clientNonce); + return ret; +} + +static int logincont2(void *obj _U_, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf _U_, size_t *rbuflen) +{ +#ifdef SHADOWPW + struct spwd *sp; +#endif /* SHADOWPW */ + int ret; + char *p; + gcry_mpi_t retServerNonce; + gcry_cipher_hd_t ctx; + gcry_error_t ctxerror; + + *rbuflen = 0; + retServerNonce = gcry_mpi_new(0); + + /* Packet size should be: Session ID + ServerNonce + Passwd buffer (evantually +10 extra bytes, see Apples Docs)*/ + if ((ibuflen != 2 + 16 + 256) && (ibuflen != 2 + 16 + 256 + 10)) { + LOG(log_error, logtype_uams, "DHX2: Paket length not correct: %d. Should be 274 or 284.", ibuflen); + ret = AFPERR_PARAM; + goto error_noctx; + } + + /* Set up our encryption context. */ + ctxerror = gcry_cipher_open( &ctx, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set key */ + ctxerror = gcry_cipher_setkey(ctx, K_MD5hash, K_hash_len); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Set the initialization vector for client->server transfer. */ + ctxerror = gcry_cipher_setiv(ctx, dhx_c2siv, sizeof(dhx_c2siv)); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + + /* Skip Session ID */ + ibuf += 2; + + /* Finally: decrypt client's md5_K(serverNonce+1, passwor, C2SIV) inplace */ + ctxerror = gcry_cipher_decrypt(ctx, ibuf, 16+256, NULL, 0); + if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) { + ret = AFPERR_MISC; + goto error_ctx; + } + /* Pull out nonce. Should be serverNonce+1 */ + gcry_mpi_scan(&retServerNonce, GCRYMPI_FMT_USG, ibuf, 16, NULL); + gcry_mpi_sub_ui(retServerNonce, retServerNonce, 1); + if ( gcry_mpi_cmp( serverNonce, retServerNonce) != 0) { + /* We're hacked! */ + ret = AFPERR_NOTAUTH; + goto error_ctx; + } + ibuf += 16; /* ibuf now point to passwd in cleartext */ + + /* ---- Start authentication --- */ + ret = AFPERR_NOTAUTH; + + p = crypt( ibuf, dhxpwd->pw_passwd ); + memset(ibuf, 0, 255); + if ( strcmp( p, dhxpwd->pw_passwd ) == 0 ) { + *uam_pwd = dhxpwd; + ret = AFP_OK; + } + +#ifdef SHADOWPW + if (( sp = getspnam( dhxpwd->pw_name )) == NULL ) { + LOG(log_info, logtype_uams, "no shadow passwd entry for %s", dhxpwd->pw_name); + ret = AFPERR_NOTAUTH; + goto exit; + } + + /* check for expired password */ + if (sp && sp->sp_max != -1 && sp->sp_lstchg) { + time_t now = time(NULL) / (60*60*24); + int32_t expire_days = sp->sp_lstchg - now + sp->sp_max; + if ( expire_days < 0 ) { + LOG(log_info, logtype_uams, "password for user %s expired", dhxpwd->pw_name); + ret = AFPERR_PWDEXPR; + goto exit; + } + } +#endif /* SHADOWPW */ + +error_ctx: + gcry_cipher_close(ctx); +error_noctx: +exit: + free(K_MD5hash); + K_MD5hash=NULL; + gcry_mpi_release(serverNonce); + gcry_mpi_release(retServerNonce); + return ret; +} + +static int passwd_logincont(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + uint16_t retID; + int ret; + + /* check for session id */ + memcpy(&retID, ibuf, sizeof(uint16_t)); + retID = ntohs(retID); + if (retID == ID) + ret = logincont1(obj, uam_pwd, ibuf, ibuflen, rbuf, rbuflen); + else if (retID == ID+1) + ret = logincont2(obj, uam_pwd, ibuf,ibuflen, rbuf, rbuflen); + else { + LOG(log_info, logtype_uams, "DHX2: Session ID Mismatch"); + ret = AFPERR_PARAM; + } + return ret; +} + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "DHX2", passwd_login, + passwd_logincont, NULL, passwd_login_ext) < 0) + return -1; + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "DHX2"); +} + + +UAM_MODULE_EXPORT struct uam_export uams_dhx2 = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + + +UAM_MODULE_EXPORT struct uam_export uams_dhx2_passwd = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + +#endif /* UAM_DHX2 */ + diff --git a/etc/uams/uams_dhx_pam.c b/etc/uams/uams_dhx_pam.c new file mode 100644 index 0000000..631f84d --- /dev/null +++ b/etc/uams/uams_dhx_pam.c @@ -0,0 +1,760 @@ +/* + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if defined(USE_PAM) && defined(UAM_DHX) +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#ifdef HAVE_SECURITY_PAM_APPL_H +#include +#endif +#ifdef HAVE_PAM_PAM_APPL_H +#include +#endif +#include + +#if defined(GNUTLS_DHX) +#include +#elif defined(OPENSSL_DHX) +#include +#include +#include +#include +#else /* OPENSSL_DHX */ +#include +#include +#include +#include +#endif /* OPENSSL_DHX */ + +#include +#include + +#define KEYSIZE 16 +#define PASSWDLEN 64 +#define CRYPTBUFLEN (KEYSIZE*2) +#define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN) +#define CHANGEPWBUFLEN (KEYSIZE + 2*PASSWDLEN) + +/* hash a number to a 16-bit quantity */ +#define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \ + (unsigned long) (a)) & 0xffff) + +/* the secret key */ +static CAST_KEY castkey; +static struct passwd *dhxpwd; +static uint8_t randbuf[KEYSIZE]; + +/* diffie-hellman bits */ +static unsigned char msg2_iv[] = "CJalbert"; +static unsigned char msg3_iv[] = "LWallace"; +static const uint8_t p[] = {0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4, + 0x3F, 0x20, 0x24, 0x74, 0x4C, 0xEE, 0xE7, 0x5B}; +static const uint8_t g = 0x07; + + +/* Static variables used to communicate between the conversation function + * and the server_login function + */ +static pam_handle_t *pamh = NULL; +static char *PAM_username; +static char *PAM_password; + +/* PAM conversation function + * Here we assume (for now, at least) that echo on means login name, and + * echo off means password. + */ +static int PAM_conv (int num_msg, +#ifdef LINUX + const struct pam_message **msg, +#else + struct pam_message **msg, +#endif + struct pam_response **resp, + void *appdata_ptr _U_) { + int count = 0; + struct pam_response *reply; + +#define COPY_STRING(s) (s) ? strdup(s) : NULL + + errno = 0; + + if (num_msg < 1) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM DHX Conversation Err -- %s", + strerror(errno)); + /* Log Entry */ + return PAM_CONV_ERR; + } + + reply = (struct pam_response *) + calloc(num_msg, sizeof(struct pam_response)); + + if (!reply) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM DHX Conversation Err -- %s", + strerror(errno)); + /* Log Entry */ + return PAM_CONV_ERR; + } + + for (count = 0; count < num_msg; count++) { + char *string = NULL; + + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + if (!(string = COPY_STRING(PAM_username))) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: username failure -- %s", + strerror(errno)); + /* Log Entry */ + goto pam_fail_conv; + } + break; + case PAM_PROMPT_ECHO_OFF: + if (!(string = COPY_STRING(PAM_password))) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: passwd failure: --: %s", + strerror(errno)); + /* Log Entry */ + goto pam_fail_conv; + } + break; + case PAM_TEXT_INFO: +#ifdef PAM_BINARY_PROMPT + case PAM_BINARY_PROMPT: +#endif /* PAM_BINARY_PROMPT */ + /* ignore it... */ + break; + case PAM_ERROR_MSG: + default: + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Binary_Prompt -- %s", + strerror(errno)); + /* Log Entry */ + goto pam_fail_conv; + } + + if (string) { + reply[count].resp_retcode = 0; + reply[count].resp = string; + string = NULL; + } + } + + *resp = reply; + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: PAM Success"); + /* Log Entry */ + return PAM_SUCCESS; + +pam_fail_conv: + for (count = 0; count < num_msg; count++) { + if (!reply[count].resp) + continue; + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + case PAM_PROMPT_ECHO_ON: + free(reply[count].resp); + break; + } + } + free(reply); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM DHX Conversation Err -- %s", + strerror(errno)); + /* Log Entry */ + return PAM_CONV_ERR; +} + +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + + +static int dhx_setup(void *obj, char *ibuf, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ + uint16_t sessid; + size_t i; + BIGNUM *bn, *gbn, *pbn; + DH *dh; + + /* get the client's public key */ + if (!(bn = BN_bin2bn((unsigned char *)ibuf, KEYSIZE, NULL))) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM No Public Key -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + /* get our primes */ + if (!(gbn = BN_bin2bn(&g, sizeof(g), NULL))) { + BN_clear_free(bn); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM No Primes: GBN -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + if (!(pbn = BN_bin2bn(p, sizeof(p), NULL))) { + BN_free(gbn); + BN_clear_free(bn); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM No Primes: PBN -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + /* okay, we're ready */ + if (!(dh = DH_new())) { + BN_free(pbn); + BN_free(gbn); + BN_clear_free(bn); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM DH was equal to DH_New... Go figure... -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + /* generate key and make sure that we have enough space */ + dh->p = pbn; + dh->g = gbn; + if (DH_generate_key(dh) == 0) { + unsigned long dherror; + char errbuf[256]; + + ERR_load_crypto_strings(); + dherror = ERR_get_error(); + ERR_error_string_n(dherror, errbuf, 256); + + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Err Generating Key (OpenSSL error code: %u, %s)", dherror, errbuf); + + ERR_free_strings(); + goto pam_fail; + } + if (BN_num_bytes(dh->pub_key) > KEYSIZE) { + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Err Generating Key -- Not enough Space? -- %s", strerror(errno)); + goto pam_fail; + } + + /* figure out the key. store the key in rbuf for now. */ + i = DH_compute_key((unsigned char *)rbuf, bn, dh); + + /* set the key */ + CAST_set_key(&castkey, i, (unsigned char *)rbuf); + + /* session id. it's just a hashed version of the object pointer. */ + sessid = dhxhash(obj); + memcpy(rbuf, &sessid, sizeof(sessid)); + rbuf += sizeof(sessid); + *rbuflen += sizeof(sessid); + + /* public key */ + BN_bn2bin(dh->pub_key, (unsigned char *)rbuf); + rbuf += KEYSIZE; + *rbuflen += KEYSIZE; + + /* buffer to be encrypted */ + i = sizeof(randbuf); + if (uam_afpserver_option(obj, UAM_OPTION_RANDNUM, (void *) randbuf, + &i) < 0) { + *rbuflen = 0; + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Buffer Encryption Err. -- %s", + strerror(errno)); + /* Log Entry */ + goto pam_fail; + } + memcpy(rbuf, &randbuf, sizeof(randbuf)); + + /* get the signature. it's always 16 bytes. */ +#if 0 + if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE, + (void *) &buf, NULL) < 0) { + *rbuflen = 0; + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Signature Retieval Failure -- %s", + strerror(errno)); + /* Log Entry */ + goto pam_fail; + } + memcpy(rbuf + KEYSIZE, buf, KEYSIZE); +#else /* 0 */ + memset(rbuf + KEYSIZE, 0, KEYSIZE); +#endif /* 0 */ + + /* encrypt using cast */ + CAST_cbc_encrypt((unsigned char *)rbuf, (unsigned char *)rbuf, CRYPTBUFLEN, &castkey, msg2_iv, + CAST_ENCRYPT); + *rbuflen += CRYPTBUFLEN; + BN_free(bn); + DH_free(dh); + return AFPERR_AUTHCONT; + +pam_fail: + BN_free(bn); + DH_free(dh); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Fail - Cast Encryption -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; +} + +/* -------------------------------- */ +static int login(void *obj, char *username, int ulen, struct passwd **uam_pwd _U_, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + if (( dhxpwd = uam_getname(obj, username, ulen)) == NULL ) { + LOG(log_info, logtype_uams, "uams_dhx_pam.c: unknown username [%s]", username); + return AFPERR_NOTAUTH; + } + + PAM_username = username; + LOG(log_info, logtype_uams, "dhx login: %s", username); + return dhx_setup(obj, ibuf, ibuflen, rbuf, rbuflen); +} + +/* -------------------------------- */ +/* dhx login: things are done in a slightly bizarre order to avoid + * having to clean things up if there's an error. */ +static int pam_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + + *rbuflen = 0; + + /* grab some of the options */ + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) { + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: uam_afpserver_option didn't meet uam_option_username -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + len = (unsigned char) *ibuf++; + if ( len > ulen ) { + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Signature Retieval Failure -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + memcpy(username, ibuf, len ); + ibuf += len; + username[ len ] = '\0'; + + if ((unsigned long) ibuf & 1) /* pad to even boundary */ + ++ibuf; + + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* ----------------------------- */ +static int pam_login_ext(void *obj, char *uname, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + int len; + size_t ulen; + uint16_t temp16; + + *rbuflen = 0; + + /* grab some of the options */ + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) { + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: uam_afpserver_option didn't meet uam_option_username -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + + if (*uname != 3) + return AFPERR_PARAM; + uname++; + memcpy(&temp16, uname, sizeof(temp16)); + len = ntohs(temp16); + + if ( !len || len > ulen ) { + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Signature Retrieval Failure -- %s", + strerror(errno)); + return AFPERR_PARAM; + } + memcpy(username, uname +2, len ); + username[ len ] = '\0'; + + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* -------------------------------- */ + +static int pam_logincont(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ + const char *hostname; + BIGNUM *bn1, *bn2, *bn3; + uint16_t sessid; + int err, PAM_error; + + *rbuflen = 0; + + /* check for session id */ + memcpy(&sessid, ibuf, sizeof(sessid)); + if (sessid != dhxhash(obj)) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM Session ID - DHXHash Mismatch -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + ibuf += sizeof(sessid); + + if (uam_afpserver_option(obj, UAM_OPTION_CLIENTNAME, + (void *) &hostname, NULL) < 0) + { + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: unable to retrieve client hostname"); + hostname = NULL; + } + + CAST_cbc_encrypt((unsigned char *)ibuf, (unsigned char *)rbuf, CRYPT2BUFLEN, &castkey, + msg3_iv, CAST_DECRYPT); + memset(&castkey, 0, sizeof(castkey)); + + /* check to make sure that the random number is the same. we + * get sent back an incremented random number. */ + if (!(bn1 = BN_bin2bn((unsigned char *)rbuf, KEYSIZE, NULL))) + return AFPERR_PARAM; + + if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) { + BN_free(bn1); + return AFPERR_PARAM; + } + + /* zero out the random number */ + memset(rbuf, 0, sizeof(randbuf)); + memset(randbuf, 0, sizeof(randbuf)); + rbuf += KEYSIZE; + + if (!(bn3 = BN_new())) { + BN_free(bn2); + BN_free(bn1); + return AFPERR_PARAM; + } + + BN_sub(bn3, bn1, bn2); + BN_free(bn2); + BN_free(bn1); + + /* okay. is it one more? */ + if (!BN_is_one(bn3)) { + BN_free(bn3); + return AFPERR_PARAM; + } + BN_free(bn3); + + /* Set these things up for the conv function */ + rbuf[PASSWDLEN] = '\0'; + PAM_password = rbuf; + + err = AFPERR_NOTAUTH; + PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, + &pamh); + if (PAM_error != PAM_SUCCESS) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: PAM_Error: %s", + pam_strerror(pamh,PAM_error)); + /* Log Entry */ + goto logincont_err; + } + + /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */ + pam_set_item(pamh, PAM_TTY, "afpd"); + pam_set_item(pamh, PAM_RHOST, hostname); + PAM_error = pam_authenticate(pamh,0); + if (PAM_error != PAM_SUCCESS) { + if (PAM_error == PAM_MAXTRIES) + err = AFPERR_PWDEXPR; + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: PAM_Error: %s", + pam_strerror(pamh, PAM_error)); + /* Log Entry */ + goto logincont_err; + } + + PAM_error = pam_acct_mgmt(pamh, 0); + if (PAM_error != PAM_SUCCESS ) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: PAM_Error: %s", + pam_strerror(pamh, PAM_error)); + /* Log Entry */ + if (PAM_error == PAM_NEW_AUTHTOK_REQD) /* password expired */ + err = AFPERR_PWDEXPR; +#ifdef PAM_AUTHTOKEN_REQD + else if (PAM_error == PAM_AUTHTOKEN_REQD) + err = AFPERR_PWDCHNG; +#endif + else + goto logincont_err; + } + +#ifndef PAM_CRED_ESTABLISH +#define PAM_CRED_ESTABLISH PAM_ESTABLISH_CRED +#endif + PAM_error = pam_setcred(pamh, PAM_CRED_ESTABLISH); + if (PAM_error != PAM_SUCCESS) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: PAM_Error: %s", + pam_strerror(pamh, PAM_error)); + /* Log Entry */ + goto logincont_err; + } + + PAM_error = pam_open_session(pamh, 0); + if (PAM_error != PAM_SUCCESS) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: PAM_Error: %s", + pam_strerror(pamh, PAM_error)); + /* Log Entry */ + goto logincont_err; + } + + memset(rbuf, 0, PASSWDLEN); /* zero out the password */ + *uam_pwd = dhxpwd; + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: PAM Auth OK!"); + /* Log Entry */ + if ( err == AFPERR_PWDEXPR) + return err; + return AFP_OK; + +logincont_err: + pam_end(pamh, PAM_error); + pamh = NULL; + memset(rbuf, 0, CRYPT2BUFLEN); + return err; +} + +/* logout */ +static void pam_logout(void) { + pam_close_session(pamh, 0); + pam_end(pamh, 0); + pamh = NULL; +} + + +/* change pw for dhx needs a couple passes to get everything all + * right. basically, it's like the login/logincont sequence */ +static int pam_changepw(void *obj, char *username, + struct passwd *pwd _U_, char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + BIGNUM *bn1, *bn2, *bn3; + + char *hostname; + pam_handle_t *lpamh; + uid_t uid; + uint16_t sessid; + int PAM_error; + + if (ibuflen < sizeof(sessid)) { + return AFPERR_PARAM; + } + + /* grab the id */ + memcpy(&sessid, ibuf, sizeof(sessid)); + ibuf += sizeof(sessid); + + if (!sessid) { /* no sessid -> initialization phase */ + PAM_username = username; + ibuflen -= sizeof(sessid); + return dhx_setup(obj, ibuf, ibuflen, rbuf, rbuflen); + } + + + /* otherwise, it's like logincont but different. */ + + /* check out the session id */ + if (sessid != dhxhash(obj)) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Session ID not Equal to DHX Hash -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + /* we need this for pam */ + if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, + (void *) &hostname, NULL) < 0) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Hostname Null?? -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_MISC; + } + + /* grab the client's nonce, old password, and new password. */ + CAST_cbc_encrypt((unsigned char *)ibuf, (unsigned char *)ibuf, CHANGEPWBUFLEN, &castkey, + msg3_iv, CAST_DECRYPT); + memset(&castkey, 0, sizeof(castkey)); + + /* check to make sure that the random number is the same. we + * get sent back an incremented random number. */ + if (!(bn1 = BN_bin2bn((unsigned char *)ibuf, KEYSIZE, NULL))) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Random Number Not the same or not incremented-- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) { + BN_free(bn1); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Random Number Not the same or not incremented -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + /* zero out the random number */ + memset(rbuf, 0, sizeof(randbuf)); + memset(randbuf, 0, sizeof(randbuf)); + + if (!(bn3 = BN_new())) { + BN_free(bn2); + BN_free(bn1); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Random Number did not Zero -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + + BN_sub(bn3, bn1, bn2); + BN_free(bn2); + BN_free(bn1); + + /* okay. is it one more? */ +#if 0 + if (!BN_is_one(bn3)) { + BN_free(bn3); + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: After Random Number not Zero, is it one more? -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } +#endif + BN_free(bn3); + + /* Set these things up for the conv function. the old password + * is at the end. */ + ibuf += KEYSIZE; + ibuf[PASSWDLEN + PASSWDLEN] = '\0'; + PAM_password = ibuf + PASSWDLEN; + + PAM_error = pam_start("netatalk", username, &PAM_conversation, + &lpamh); + if (PAM_error != PAM_SUCCESS) { + /* Log Entry */ + LOG(log_info, logtype_uams, "uams_dhx_pam.c :PAM: Needless to say, PAM_error is != to PAM_SUCCESS -- %s", + strerror(errno)); + /* Log Entry */ + return AFPERR_PARAM; + } + pam_set_item(lpamh, PAM_TTY, "afpd"); + pam_set_item(lpamh, PAM_RHOST, hostname); + + /* we might need to do this as root */ + uid = geteuid(); + seteuid(0); + PAM_error = pam_authenticate(lpamh, 0); + if (PAM_error != PAM_SUCCESS) { + seteuid(uid); + pam_end(lpamh, PAM_error); + return AFPERR_NOTAUTH; + } + + /* clear out old passwd */ + memset(ibuf + PASSWDLEN, 0, PASSWDLEN); + + /* new password */ + PAM_password = ibuf; + ibuf[PASSWDLEN] = '\0'; + + /* this really does need to be done as root */ + PAM_error = pam_chauthtok(lpamh, 0); + seteuid(uid); /* un-root ourselves. */ + memset(ibuf, 0, PASSWDLEN); + if (PAM_error != PAM_SUCCESS) { + pam_end(lpamh, PAM_error); + return AFPERR_ACCESS; + } + + pam_end(lpamh, 0); + return AFP_OK; +} + + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "DHCAST128", pam_login, + pam_logincont, pam_logout, pam_login_ext) < 0) + return -1; + + if (uam_register(UAM_SERVER_CHANGEPW, path, "DHCAST128", + pam_changepw) < 0) { + uam_unregister(UAM_SERVER_LOGIN, "DHCAST128"); + return -1; + } + + /*uam_register(UAM_SERVER_PRINTAUTH, path, "DHCAST128", + pam_printer);*/ + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "DHCAST128"); + uam_unregister(UAM_SERVER_CHANGEPW, "DHCAST128"); + /*uam_unregister(UAM_SERVER_PRINTAUTH, "DHCAST128"); */ +} + +UAM_MODULE_EXPORT struct uam_export uams_dhx = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + +UAM_MODULE_EXPORT struct uam_export uams_dhx_pam = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + +#endif /* USE_PAM && UAM_DHX */ + diff --git a/etc/uams/uams_dhx_passwd.c b/etc/uams/uams_dhx_passwd.c new file mode 100644 index 0000000..e407d9d --- /dev/null +++ b/etc/uams/uams_dhx_passwd.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include +#include +#include +#include +#ifdef HAVE_CRYPT_H +#include +#endif /* ! HAVE_CRYPT_H */ +#include +#include +#include +#include + +#ifdef SHADOWPW +#include +#endif /* SHADOWPW */ + +#if defined(GNUTLS_DHX) +#include +#elif defined(OPENSSL_DHX) +#include +#include +#include +#else /* OPENSSL_DHX */ +#include +#include +#include +#endif /* OPENSSL_DHX */ + +#include +#include +#include + +#define KEYSIZE 16 +#define PASSWDLEN 64 +#define CRYPTBUFLEN (KEYSIZE*2) +#define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN) + +/* hash a number to a 16-bit quantity */ +#define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \ + (unsigned long) (a)) & 0xffff) + +/* the secret key */ +static CAST_KEY castkey; +static struct passwd *dhxpwd; +static uint8_t randbuf[16]; + +#ifdef TRU64 +#include +#include + +static const char *clientname; +#endif /* TRU64 */ + +/* dhx passwd */ +static int pwd_login(void *obj, char *username, int ulen, struct passwd **uam_pwd _U_, + char *ibuf, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ + unsigned char iv[] = "CJalbert"; + uint8_t p[] = {0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4, + 0x3F, 0x20, 0x24, 0x74, 0x4C, 0xEE, 0xE7, 0x5B }; + uint8_t g = 0x07; +#ifdef SHADOWPW + struct spwd *sp; +#endif /* SHADOWPW */ + BIGNUM *bn, *gbn, *pbn; + uint16_t sessid; + size_t i; + DH *dh; + +#ifdef TRU64 + int rnd_seed[256]; + for (i = 0; i < 256; i++) + rnd_seed[i] = random(); + RAND_seed(rnd_seed, sizeof(rnd_seed)); +#endif /* TRU64 */ + + *rbuflen = 0; + +#ifdef TRU64 + if( uam_afpserver_option( obj, UAM_OPTION_CLIENTNAME, + (void *) &clientname, NULL ) < 0 ) + return AFPERR_PARAM; +#endif /* TRU64 */ + + if (( dhxpwd = uam_getname(obj, username, ulen)) == NULL ) { + return AFPERR_NOTAUTH; + } + + LOG(log_info, logtype_uams, "dhx login: %s", username); + if (uam_checkuser(dhxpwd) < 0) + return AFPERR_NOTAUTH; + +#ifdef SHADOWPW + if (( sp = getspnam( dhxpwd->pw_name )) == NULL ) { + LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username); + return AFPERR_NOTAUTH; + } + dhxpwd->pw_passwd = sp->sp_pwdp; +#endif /* SHADOWPW */ + + if (!dhxpwd->pw_passwd) + return AFPERR_NOTAUTH; + + /* get the client's public key */ + if (!(bn = BN_bin2bn((unsigned char *)ibuf, KEYSIZE, NULL))) { + return AFPERR_PARAM; + } + + /* get our primes */ + if (!(gbn = BN_bin2bn(&g, sizeof(g), NULL))) { + BN_free(bn); + return AFPERR_PARAM; + } + + if (!(pbn = BN_bin2bn(p, sizeof(p), NULL))) { + BN_free(gbn); + BN_free(bn); + return AFPERR_PARAM; + } + + /* okay, we're ready */ + if (!(dh = DH_new())) { + BN_free(pbn); + BN_free(gbn); + BN_free(bn); + return AFPERR_PARAM; + } + + /* generate key and make sure we have enough space */ + dh->p = pbn; + dh->g = gbn; + if (!DH_generate_key(dh) || (BN_num_bytes(dh->pub_key) > KEYSIZE)) { + goto passwd_fail; + } + + /* figure out the key. use rbuf as a temporary buffer. */ + i = DH_compute_key((unsigned char *)rbuf, bn, dh); + + /* set the key */ + CAST_set_key(&castkey, i, (unsigned char *)rbuf); + + /* session id. it's just a hashed version of the object pointer. */ + sessid = dhxhash(obj); + memcpy(rbuf, &sessid, sizeof(sessid)); + rbuf += sizeof(sessid); + *rbuflen += sizeof(sessid); + + /* send our public key */ + BN_bn2bin(dh->pub_key, (unsigned char *)rbuf); + rbuf += KEYSIZE; + *rbuflen += KEYSIZE; + + /* buffer to be encrypted */ + i = sizeof(randbuf); + if (uam_afpserver_option(obj, UAM_OPTION_RANDNUM, (void *) randbuf, + &i) < 0) { + *rbuflen = 0; + goto passwd_fail; + } + memcpy(rbuf, &randbuf, sizeof(randbuf)); + +#if 0 + /* get the signature. it's always 16 bytes. */ + if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE, + (void *) &name, NULL) < 0) { + *rbuflen = 0; + goto passwd_fail; + } + memcpy(rbuf + KEYSIZE, name, KEYSIZE); +#else /* 0 */ + memset(rbuf + KEYSIZE, 0, KEYSIZE); +#endif /* 0 */ + + /* encrypt using cast */ + CAST_cbc_encrypt((unsigned char *)rbuf, (unsigned char *)rbuf, CRYPTBUFLEN, &castkey, iv, CAST_ENCRYPT); + *rbuflen += CRYPTBUFLEN; + BN_free(bn); + DH_free(dh); + return AFPERR_AUTHCONT; + +passwd_fail: + BN_free(bn); + DH_free(dh); + return AFPERR_PARAM; +} + +/* cleartxt login */ +static int passwd_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, + (void *) &username, &ulen) < 0) + return AFPERR_MISC; + + if (ibuflen < 2) { + return( AFPERR_PARAM ); + } + + len = (unsigned char) *ibuf++; + ibuflen--; + if (!len || len > ibuflen || len > ulen ) { + return( AFPERR_PARAM ); + } + memcpy(username, ibuf, len ); + ibuf += len; + ibuflen -=len; + username[ len ] = '\0'; + + if ((unsigned long) ibuf & 1) { /* pad character */ + ++ibuf; + ibuflen--; + } + return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); + +} + +/* cleartxt login ext + * uname format : + byte 3 + 2 bytes len (network order) + len bytes utf8 name +*/ +static int passwd_login_ext(void *obj, char *uname, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + uint16_t temp16; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, + (void *) &username, &ulen) < 0) + return AFPERR_MISC; + + if (*uname != 3) + return AFPERR_PARAM; + uname++; + memcpy(&temp16, uname, sizeof(temp16)); + len = ntohs(temp16); + if (!len || len > ulen ) { + return( AFPERR_PARAM ); + } + memcpy(username, uname +2, len ); + username[ len ] = '\0'; + return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +static int passwd_logincont(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ +#ifdef SHADOWPW + struct spwd *sp; +#endif /* SHADOWPW */ + unsigned char iv[] = "LWallace"; + BIGNUM *bn1, *bn2, *bn3; + uint16_t sessid; + char *p; + int err = AFPERR_NOTAUTH; + + *rbuflen = 0; + + /* check for session id */ + memcpy(&sessid, ibuf, sizeof(sessid)); + if (sessid != dhxhash(obj)) + return AFPERR_PARAM; + ibuf += sizeof(sessid); + + /* use rbuf as scratch space */ + CAST_cbc_encrypt((unsigned char *)ibuf, (unsigned char *)rbuf, CRYPT2BUFLEN, &castkey, + iv, CAST_DECRYPT); + + /* check to make sure that the random number is the same. we + * get sent back an incremented random number. */ + if (!(bn1 = BN_bin2bn((unsigned char *)rbuf, KEYSIZE, NULL))) + return AFPERR_PARAM; + + if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) { + BN_free(bn1); + return AFPERR_PARAM; + } + + /* zero out the random number */ + memset(rbuf, 0, sizeof(randbuf)); + memset(randbuf, 0, sizeof(randbuf)); + rbuf += KEYSIZE; + + if (!(bn3 = BN_new())) { + BN_free(bn2); + BN_free(bn1); + return AFPERR_PARAM; + } + + BN_sub(bn3, bn1, bn2); + BN_free(bn2); + BN_free(bn1); + + /* okay. is it one more? */ + if (!BN_is_one(bn3)) { + BN_free(bn3); + return AFPERR_PARAM; + } + BN_free(bn3); + + rbuf[PASSWDLEN] = '\0'; +#ifdef TRU64 + { + int ac; + char **av; + char hostname[256]; + + uam_afp_getcmdline( &ac, &av ); + sprintf( hostname, "%s@%s", dhxpwd->pw_name, clientname ); + + if( uam_sia_validate_user( NULL, ac, av, hostname, dhxpwd->pw_name, + NULL, FALSE, NULL, rbuf ) != SIASUCCESS ) + return AFPERR_NOTAUTH; + + memset( rbuf, 0, PASSWDLEN ); + *uam_pwd = dhxpwd; + return AFP_OK; + } +#else /* TRU64 */ + p = crypt( rbuf, dhxpwd->pw_passwd ); + memset(rbuf, 0, PASSWDLEN); + if ( strcmp( p, dhxpwd->pw_passwd ) == 0 ) { + *uam_pwd = dhxpwd; + err = AFP_OK; + } +#ifdef SHADOWPW + if (( sp = getspnam( dhxpwd->pw_name )) == NULL ) { + LOG(log_info, logtype_uams, "no shadow passwd entry for %s", dhxpwd->pw_name); + return (AFPERR_NOTAUTH); + } + + /* check for expired password */ + if (sp && sp->sp_max != -1 && sp->sp_lstchg) { + time_t now = time(NULL) / (60*60*24); + int32_t expire_days = sp->sp_lstchg - now + sp->sp_max; + if ( expire_days < 0 ) { + LOG(log_info, logtype_uams, "password for user %s expired", dhxpwd->pw_name); + err = AFPERR_PWDEXPR; + } + } +#endif /* SHADOWPW */ + return err; +#endif /* TRU64 */ + + return AFPERR_NOTAUTH; +} + + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "DHCAST128", + passwd_login, passwd_logincont, NULL, passwd_login_ext) < 0) + return -1; + /*uam_register(UAM_SERVER_PRINTAUTH, path, "DHCAST128", + passwd_printer);*/ + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "DHCAST128"); + /*uam_unregister(UAM_SERVER_PRINTAUTH, "DHCAST128"); */ +} + +UAM_MODULE_EXPORT struct uam_export uams_dhx = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + +UAM_MODULE_EXPORT struct uam_export uams_dhx_passwd = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; diff --git a/etc/uams/uams_gss.c b/etc/uams/uams_gss.c new file mode 100644 index 0000000..325d1c1 --- /dev/null +++ b/etc/uams/uams_gss.c @@ -0,0 +1,638 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * Copyright (c) 2003 The Reed Institute + * Copyright (c) 2004 Bjoern Fernhomberg + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Kerberos includes */ +#ifdef HAVE_GSSAPI_GSSAPI_H +#include +#else +#include +#endif // HAVE_GSSAPI_GSSAPI_H + +#ifdef HAVE_KERBEROS +#ifdef HAVE_KRB5_KRB5_H +#include +#else +#include +#endif /* HAVE_KRB5_KRB5_H */ +#endif /* HAVE_KERBEROS */ + +#define LOG_UAMS(log_level, ...) \ + LOG(log_level, logtype_uams, __VA_ARGS__) + +#define LOG_LOGINCONT(log_level, ...) \ + LOG_UAMS(log_level, "FPLoginCont: " __VA_ARGS__) + +static void log_status(char *s, + OM_uint32 major_status, + OM_uint32 minor_status) +{ + gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; + OM_uint32 min_status, maj_status; + OM_uint32 maj_ctx = 0, min_ctx = 0; + + while (1) { + maj_status = gss_display_status( &min_status, major_status, + GSS_C_GSS_CODE, GSS_C_NULL_OID, + &maj_ctx, &msg ); + LOG_UAMS(log_error, "%s %.*s (error %s)", + s, msg.length, msg.value, strerror(errno)); + gss_release_buffer(&min_status, &msg); + + if (!maj_ctx) + break; + } + + while (1) { + maj_status = gss_display_status( &min_status, minor_status, + GSS_C_MECH_CODE, GSS_C_NULL_OID, + &min_ctx, &msg ); + LOG_UAMS(log_error, "%s %.*s (error %s)", + s, msg.length, msg.value, strerror(errno)); + gss_release_buffer(&min_status, &msg); + + if (!min_ctx) + break; + } +} + +static void log_ctx_flags(OM_uint32 flags) +{ + if (flags & GSS_C_DELEG_FLAG) + LOG_LOGINCONT(log_debug, "context flag: GSS_C_DELEG_FLAG"); + if (flags & GSS_C_MUTUAL_FLAG) + LOG_LOGINCONT(log_debug, "context flag: GSS_C_MUTUAL_FLAG"); + if (flags & GSS_C_REPLAY_FLAG) + LOG_LOGINCONT(log_debug, "context flag: GSS_C_REPLAY_FLAG"); + if (flags & GSS_C_SEQUENCE_FLAG) + LOG_LOGINCONT(log_debug, "context flag: GSS_C_SEQUENCE_FLAG"); + if (flags & GSS_C_CONF_FLAG) + LOG_LOGINCONT(log_debug, "context flag: GSS_C_CONF_FLAG"); + if (flags & GSS_C_INTEG_FLAG) + LOG_LOGINCONT(log_debug, "context flag: GSS_C_INTEG_FLAG"); +} + +static void log_service_name(gss_ctx_id_t context) +{ + OM_uint32 major_status = 0, minor_status = 0; + gss_name_t service_name; + gss_buffer_desc service_name_buffer; + + major_status = gss_inquire_context(&minor_status, + context, + NULL, + &service_name, + NULL, + NULL, + NULL, + NULL, + NULL); + if (major_status != GSS_S_COMPLETE) { + log_status("gss_inquire_context", major_status, minor_status); + return; + } + + major_status = gss_display_name(&minor_status, + service_name, + &service_name_buffer, + NULL); + if (major_status == GSS_S_COMPLETE) { + LOG_LOGINCONT(log_debug, + "service principal is `%s'", + service_name_buffer.value); + + gss_release_buffer(&minor_status, &service_name_buffer); + } else + log_status("gss_display_name", major_status, minor_status); + + gss_release_name(&minor_status, &service_name); +} + +static int get_client_username(char *username, + int ulen, + gss_name_t *client_name) +{ + OM_uint32 major_status = 0, minor_status = 0; + gss_buffer_desc client_name_buffer; + char *p; + int ret = 0; + + /* + * To extract the unix username, use gss_display_name on client_name. + * We do rely on gss_display_name returning a zero terminated string. + * The username returned contains the realm and possibly an instance. + * We only want the username for afpd, so we have to strip those from + * the username before copying it to afpd's buffer. + */ + + major_status = gss_display_name(&minor_status, + *client_name, + &client_name_buffer, + NULL); + if (major_status != GSS_S_COMPLETE) { + log_status("gss_display_name", major_status, minor_status); + return 1; + } + + LOG_LOGINCONT(log_debug, + "user principal is `%s'", + client_name_buffer.value); + + /* chop off realm */ + p = strchr(client_name_buffer.value, '@'); + if (p) + *p = 0; + /* FIXME: chop off instance? */ + p = strchr(client_name_buffer.value, '/'); + if (p) + *p = 0; + + /* check if this username fits into afpd's username buffer */ + size_t cnblen = strlen(client_name_buffer.value); + if (cnblen >= ulen) { + /* The username is too long for afpd's buffer, bail out */ + LOG_LOGINCONT(log_info, + "username `%s' too long (%d)", + client_name_buffer.value, cnblen); + ret = 1; + } else { + /* copy stripped username to afpd's buffer */ + strlcpy(username, client_name_buffer.value, ulen); + } + + gss_release_buffer(&minor_status, &client_name_buffer); + + return ret; +} + +/* wrap afpd's sessionkey */ +static int wrap_sessionkey(gss_ctx_id_t context, struct session_info *sinfo) +{ + OM_uint32 major_status = 0, minor_status = 0; + gss_buffer_desc sesskey_buff, wrap_buff; + int ret = 0; + + /* + * gss_wrap afpd's session_key. + * This is needed fo OS X 10.3 clients. They request this information + * with type 8 (kGetKerberosSessionKey) on FPGetSession. + * See AFP 3.1 specs, page 77. + */ + sesskey_buff.value = sinfo->sessionkey; + sesskey_buff.length = sinfo->sessionkey_len; + + /* gss_wrap the session key with the default mechanism. + Require both confidentiality and integrity services */ + major_status = gss_wrap(&minor_status, + context, + true, + GSS_C_QOP_DEFAULT, + &sesskey_buff, + NULL, + &wrap_buff); + + if (major_status != GSS_S_COMPLETE) { + log_status("gss_wrap", major_status, minor_status); + return 1; + } + + /* store the wrapped session key in afpd's session_info struct */ + if (NULL == (sinfo->cryptedkey = malloc(wrap_buff.length))) { + LOG_UAMS(log_error, + "wrap_sessionkey: out of memory tyring to allocate %u bytes", + wrap_buff.length); + ret = 1; + } else { + /* cryptedkey is binary data */ + memcpy(sinfo->cryptedkey, wrap_buff.value, wrap_buff.length); + sinfo->cryptedkey_len = wrap_buff.length; + } + + /* we're done with buffer, release */ + gss_release_buffer(&minor_status, &wrap_buff); + + return ret; +} + +static int accept_sec_context(gss_ctx_id_t *context, + gss_buffer_desc *ticket_buffer, + gss_name_t *client_name, + gss_buffer_desc *authenticator_buff) +{ + OM_uint32 major_status = 0, minor_status = 0, flags = 0; + + /* Initialize autheticator buffer. */ + authenticator_buff->length = 0; + authenticator_buff->value = NULL; + + LOG_LOGINCONT(log_debug, + "accepting context (ticketlen: %u)", + ticket_buffer->length); + + /* + * Try to accept the secondary context using the token in ticket_buffer. + * We don't care about the principals or mechanisms used, nor for the time. + * We don't act as a proxy either. + */ + major_status = gss_accept_sec_context(&minor_status, + context, + GSS_C_NO_CREDENTIAL, + ticket_buffer, + GSS_C_NO_CHANNEL_BINDINGS, + client_name, + NULL, + authenticator_buff, + &flags, + NULL, + NULL); + + if (major_status != GSS_S_COMPLETE) { + log_status("gss_accept_sec_context", major_status, minor_status); + return 1; + } + + log_ctx_flags(flags); + return 0; +} + +static int do_gss_auth(void *obj, + char *ibuf, size_t ibuflen, + char *rbuf, int *rbuflen, + char *username, size_t ulen, + struct session_info *sinfo ) +{ + OM_uint32 status = 0; + gss_name_t client_name; + gss_ctx_id_t context = GSS_C_NO_CONTEXT; + gss_buffer_desc ticket_buffer, authenticator_buff; + int ret = 0; + + /* + * Try to accept the secondary context, using the ticket/token the + * client sent us. Ticket is stored at current ibuf position. + * Don't try to release ticket_buffer later, it points into ibuf! + */ + ticket_buffer.length = ibuflen; + ticket_buffer.value = ibuf; + + if ((ret = accept_sec_context(&context, + &ticket_buffer, + &client_name, + &authenticator_buff))) + return ret; + log_service_name(context); + + /* We succesfully acquired the secondary context, now get the + username for afpd and gss_wrap the sessionkey */ + if ((ret = get_client_username(username, ulen, &client_name))) + goto cleanup_client_name; + + if ((ret = wrap_sessionkey(context, sinfo))) + goto cleanup_client_name; + + /* Authenticated, construct the reply using: + * authenticator length (uint16_t) + * authenticator + */ + /* copy the authenticator length into the reply buffer */ + uint16_t auth_len = htons(authenticator_buff.length); + memcpy(rbuf, &auth_len, sizeof(auth_len)); + *rbuflen += sizeof(auth_len); + rbuf += sizeof(auth_len); + + /* copy the authenticator value into the reply buffer */ + memcpy(rbuf, authenticator_buff.value, authenticator_buff.length); + *rbuflen += authenticator_buff.length; + +cleanup_client_name: + gss_release_name(&status, &client_name); + gss_release_buffer(&status, &authenticator_buff); + gss_delete_sec_context(&status, &context, NULL); + + return ret; +} + +/* -------------------------- */ + +/* + * For the gss uam, this function only needs to return a two-byte + * login-session id. None of the data provided by the client up to this + * point is trustworthy as we'll have a signed ticket to parse in logincont. + */ +static int gss_login(void *obj, + struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + *rbuflen = 0; + + /* The reply contains a two-byte ID value - note + * that Apple's implementation seems to always return 1 as well + */ + uint16_t temp16 = htons(1); + memcpy(rbuf, &temp16, sizeof(temp16)); + *rbuflen += sizeof(temp16); + + return AFPERR_AUTHCONT; +} + +static int gss_logincont(void *obj, + struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + struct passwd *pwd = NULL; + uint16_t login_id; + char *username; + uint16_t ticket_len; + char *p; + int rblen; + size_t userlen; + struct session_info *sinfo; + + /* Apple's AFP 3.1 documentation specifies that this command + * takes the following format: + * pad (byte) + * id returned in LoginExt response (uint16_t) + * username (format unspecified) + * padded, when necessary, to end on an even boundary + * ticket length (uint16_t) + * ticket + */ + + /* Observation of AFP clients in the wild indicate that the actual + * format of this request is as follows: + * pad (byte) [consumed before login_ext is called] + * ?? (byte) - always observed to be 0 + * id returned in LoginExt response (uint16_t) + * username, encoding unspecified, null terminated C string, + * padded when the terminating null is an even numbered byte. + * The packet is formated such that the username begins on an + * odd numbered byte. Eg if the username is 3 characters and the + * terminating null makes 4, expect to pad the the result. + * The encoding of this string is unknown. + * ticket length (uint16_t) + * ticket + */ + + rblen = *rbuflen = 0; + + if (ibuflen < 1 +sizeof(login_id)) { + LOG_LOGINCONT(log_info, "received incomplete packet"); + return AFPERR_PARAM; + } + ibuf++, ibuflen--; /* ?? */ + + /* 2 byte ID from LoginExt -- always '00 01' in this implementation */ + memcpy(&login_id, ibuf, sizeof(login_id)); + ibuf += sizeof(login_id), ibuflen -= sizeof(login_id); + login_id = ntohs(login_id); + + /* get the username buffer from apfd */ + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &userlen) < 0) + return AFPERR_MISC; + + /* get the session_info structure from afpd. We need the session key */ + if (uam_afpserver_option(obj, UAM_OPTION_SESSIONINFO, &sinfo, NULL) < 0) + return AFPERR_MISC; + + if (sinfo->sessionkey == NULL || sinfo->sessionkey_len == 0) { + /* Should never happen. Most likely way too old afpd version */ + LOG_LOGINCONT(log_error, "internal error: afpd's sessionkey not set"); + return AFPERR_MISC; + } + + /* We skip past the 'username' parameter because all that matters is the ticket */ + p = ibuf; + while ( *ibuf && ibuflen ) { ibuf++, ibuflen--; } + if (ibuflen < 4) { + LOG_LOGINCONT(log_info, "user is %s, no ticket", p); + return AFPERR_PARAM; + } + + ibuf++, ibuflen--; /* null termination */ + + if ((ibuf - p + 1) % 2) ibuf++, ibuflen--; /* deal with potential padding */ + + LOG_LOGINCONT(log_debug, "client thinks user is %s", p); + + /* get the length of the ticket the client sends us */ + memcpy(&ticket_len, ibuf, sizeof(ticket_len)); + ibuf += sizeof(ticket_len); ibuflen -= sizeof(ticket_len); + ticket_len = ntohs(ticket_len); + + /* a little bounds checking */ + if (ticket_len > ibuflen) { + LOG_LOGINCONT(log_info, + "invalid ticket length (%u > %u)", + ticket_len, ibuflen); + return AFPERR_PARAM; + } + + /* now try to authenticate */ + if (do_gss_auth(obj, ibuf, ticket_len, rbuf, &rblen, username, userlen, sinfo)) { + LOG_LOGINCONT(log_info, "do_gss_auth() failed" ); + *rbuflen = 0; + return AFPERR_MISC; + } + + /* We use the username we got back from the gssapi client_name. + Should we compare this to the username the client sent in the clear? + We know the character encoding of the cleartext username (UTF8), what + encoding is the gssapi name in? */ + if ((pwd = uam_getname( obj, username, userlen )) == NULL) { + LOG_LOGINCONT(log_info, "uam_getname() failed for %s", username); + return AFPERR_NOTAUTH; + } + if (uam_checkuser(pwd) < 0) { + LOG_LOGINCONT(log_info, "`%s'' not a valid user", username); + return AFPERR_NOTAUTH; + } + + *rbuflen = rblen; + *uam_pwd = pwd; + return AFP_OK; +} + +/* logout */ +static void gss_logout() { +} + +static int gss_login_ext(void *obj, + char *uname, + struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + return gss_login(obj, uam_pwd, ibuf, ibuflen, rbuf, rbuflen); +} + +static int set_principal(AFPObj *obj, char *principal) +{ + size_t len = strlen(principal); + + if (len > 255) { + LOG(log_error, logtype_afpd, "set_principal: principal '%s' too long (max=255)", principal, len); + return -1; + } + + /* We store: 1 byte number principals (1) + 1 byte principal name length + zero terminated principal */ + if ((obj->options.k5principal = malloc(len + 3)) == NULL) { + LOG(log_error, logtype_afpd, "set_principal: OOM"); + return -1; + } + + LOG(log_info, logtype_afpd, "Using AFP Kerberos service principal name: %s", principal); + + obj->options.k5principal[0] = 1; + obj->options.k5principal[1] = (unsigned char)len; + obj->options.k5principal_buflen = len + 2; + strncpy(obj->options.k5principal + 2, principal, len); + + return 0; +} + +static int gss_create_principal(AFPObj *obj) +{ + int rv = -1; +#ifdef HAVE_KERBEROS + krb5_context context; + krb5_error_code ret; + const char *error_msg; + krb5_keytab keytab; + krb5_keytab_entry entry; + krb5_principal service_principal; + char *principal; + krb5_kt_cursor cursor; + + if (krb5_init_context(&context)) { + LOG(log_error, logtype_afpd, "gss_create_principal: failed to intialize a krb5_context"); + goto exit; + } + if ((ret = krb5_kt_default(context, &keytab))) + goto krb5_error; + + if (obj->options.k5service && obj->options.fqdn && obj->options.k5realm) { + LOG(log_debug, logtype_afpd, "gss_create_principal: using service principal specified in options"); + + if ((ret = krb5_build_principal(context, + &service_principal, + strlen(obj->options.k5realm), + obj->options.k5realm, + obj->options.k5service, + obj->options.fqdn, + NULL))) + goto krb5_error; + + if ((ret = krb5_kt_get_entry(context, + keytab, + service_principal, + 0, // kvno - wildcard + 0, // enctype - wildcard + &entry)) == KRB5_KT_NOTFOUND) { + krb5_unparse_name(context, service_principal, &principal); + LOG(log_error, logtype_afpd, "gss_create_principal: specified service principal '%s' not found in keytab", principal); +#ifdef HAVE_KRB5_FREE_UNPARSED_NAME + krb5_free_unparsed_name(context, principal); +#else + krb5_xfree(principal); +#endif + goto krb5_cleanup; + } + krb5_free_principal(context, service_principal); + if (ret) + goto krb5_error; + } else { + LOG(log_debug, logtype_afpd, "gss_create_principal: using first entry from keytab as service principal"); + if ((ret = krb5_kt_start_seq_get(context, keytab, &cursor))) + goto krb5_error; + ret = krb5_kt_next_entry(context, keytab, &entry, &cursor); + krb5_kt_end_seq_get(context, keytab, &cursor); + if (ret) + goto krb5_error; + } + + krb5_unparse_name(context, entry.principal, &principal); +#ifdef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS + krb5_free_keytab_entry_contents(context, &entry); +#elif defined(HAVE_KRB5_KT_FREE_ENTRY) + krb5_kt_free_entry(context, &entry); +#endif + set_principal(obj, principal); + free(principal); + rv = 0; + goto krb5_cleanup; + +krb5_error: + if (ret) { + error_msg = krb5_get_error_message(context, ret); + LOG(log_note, logtype_afpd, "Can't get principal from default keytab: %s", + (char *)error_msg); +#ifdef HAVE_KRB5_FREE_ERROR_MESSAGE + krb5_free_error_message(context, error_msg); +#else + krb5_xfree(error_msg); +#endif + } + +krb5_cleanup: + krb5_kt_close(context, keytab); + krb5_free_context(context); + +#else /* ! HAVE_KERBEROS */ + if (!obj->options.k5service || !obj->options.fqdn || !obj->options.k5realm) + goto exit; + + char principal[255]; + size_t len = snprintf(principal, sizeof(principal), "%s/%s@%s", + obj->options.k5service, obj->options.fqdn, obj->options.k5realm); + (void)set_principal(obj, principal); + rv = 0; +#endif /* HAVE_KERBEROS */ + +exit: + return rv; +} + +static int uam_setup(void *handle, const char *path) +{ + AFPObj *obj = (AFPObj *)handle; + if (gss_create_principal(obj) != 0) + return -1; + + return uam_register(UAM_SERVER_LOGIN_EXT, path, "Client Krb v2", + gss_login, gss_logincont, gss_logout, gss_login_ext); +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN_EXT, "Client Krb v2"); +} + +UAM_MODULE_EXPORT struct uam_export uams_gss = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, + uam_cleanup +}; diff --git a/etc/uams/uams_guest.c b/etc/uams/uams_guest.c new file mode 100644 index 0000000..baaf9eb --- /dev/null +++ b/etc/uams/uams_guest.c @@ -0,0 +1,147 @@ +/* + * + * (c) 2001 (see COPYING) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +/*XXX in etc/papd/file.h */ +struct papfile; +extern UAM_MODULE_EXPORT void append(struct papfile *, const char *, int); + +/* login and login_ext are almost the same */ +static int noauth_login(void *obj, struct passwd **uam_pwd, + char *ibuf _U_, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen) +{ + struct passwd *pwent; + char *guest, *username; + + *rbuflen = 0; + LOG(log_info, logtype_uams, "login noauth" ); + + if (uam_afpserver_option(obj, UAM_OPTION_GUEST, (void *) &guest, + NULL) < 0) + return AFPERR_MISC; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, + (void *) &username, NULL) < 0) + return AFPERR_MISC; + + strcpy(username, guest); + if ((pwent = getpwnam(guest)) == NULL) { + LOG(log_error, logtype_uams, "noauth_login: getpwnam( %s ): %s", + guest, strerror(errno) ); + return( AFPERR_BADUAM ); + } + +#ifdef AFS + if ( setpag() < 0 ) { + LOG(log_error, logtype_uams, "noauth_login: setpag: %s", strerror(errno) ); + return( AFPERR_BADUAM ); + } +#endif /* AFS */ + + *uam_pwd = pwent; + return( AFP_OK ); +} + +static int noauth_login_ext(void *obj, char *uname _U_, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + return ( noauth_login (obj, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + + +/* Printer NoAuthUAM Login */ +static int noauth_printer(char *start, char *stop, char *username, struct papfile *out) +{ + char *data, *p, *q; + static const char *loginok = "0\r"; + + data = (char *)malloc(stop - start + 1); + if (!data) { + LOG(log_info, logtype_uams,"Bad Login NoAuthUAM: malloc"); + return(-1); + } + + strlcpy(data, start, stop - start + 1); + + /* We are looking for the following format in data: + * (username) + * + * Hopefully username doesn't contain a ")" + */ + + if ((p = strchr(data, '(' )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login NoAuthUAM: username not found in string"); + free(data); + return(-1); + } + p++; + if ((q = strchr(p, ')' )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login NoAuthUAM: username not found in string"); + free(data); + return(-1); + } + memcpy(username, p, MIN( UAM_USERNAMELEN, q - p )); + + /* Done copying username, clean up */ + free(data); + + if (getpwnam(username) == NULL) { + LOG(log_info, logtype_uams, "Bad Login NoAuthUAM: %s: %s", + username, strerror(errno) ); + return(-1); + } + + /* Login successful */ + append(out, loginok, strlen(loginok)); + LOG(log_info, logtype_uams, "Login NoAuthUAM: %s", username); + return(0); +} + + +static int uam_setup(void *handle, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "No User Authent", + noauth_login, NULL, NULL, noauth_login_ext) < 0) + return -1; + + if (uam_register(UAM_SERVER_PRINTAUTH, path, "NoAuthUAM", + noauth_printer) < 0) + return -1; + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "No User Authent"); + uam_unregister(UAM_SERVER_PRINTAUTH, "NoAuthUAM"); +} + +UAM_MODULE_EXPORT struct uam_export uams_guest = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; diff --git a/etc/uams/uams_pam.c b/etc/uams/uams_pam.c new file mode 100644 index 0000000..da5be62 --- /dev/null +++ b/etc/uams/uams_pam.c @@ -0,0 +1,485 @@ +/* + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#ifdef HAVE_SECURITY_PAM_APPL_H +#include +#endif +#ifdef HAVE_PAM_PAM_APPL_H +#include +#endif +#include + +#include +#include +#include +#include +#include + +#define PASSWDLEN 8 + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + + +/* Static variables used to communicate between the conversation function + * and the server_login function + */ +static pam_handle_t *pamh = NULL; +static const char *hostname; +static char *PAM_username; +static char *PAM_password; + +/*XXX in etc/papd/file.h */ +struct papfile; +extern UAM_MODULE_EXPORT void append(struct papfile *, const char *, int); + +/* PAM conversation function + * Here we assume (for now, at least) that echo on means login name, and + * echo off means password. + */ +static int PAM_conv (int num_msg, +#ifdef LINUX + const struct pam_message **msg, +#else + struct pam_message **msg, +#endif + struct pam_response **resp, + void *appdata_ptr _U_) +{ + struct pam_response *reply; + int count; + +#define COPY_STRING(s) (s) ? strdup(s) : NULL + + if (num_msg < 1) + return PAM_CONV_ERR; + + reply = (struct pam_response *) + calloc(num_msg, sizeof(struct pam_response)); + + if (!reply) + return PAM_CONV_ERR; + + for (count = 0; count < num_msg; count++) { + char *string = NULL; + + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + if (!(string = COPY_STRING(PAM_username))) + goto pam_fail_conv; + break; + case PAM_PROMPT_ECHO_OFF: + if (!(string = COPY_STRING(PAM_password))) + goto pam_fail_conv; + break; + case PAM_TEXT_INFO: +#ifdef PAM_BINARY_PROMPT + case PAM_BINARY_PROMPT: +#endif /* PAM_BINARY_PROMPT */ + /* ignore it... */ + break; + case PAM_ERROR_MSG: + default: + goto pam_fail_conv; + } + + if (string) { + reply[count].resp_retcode = 0; + reply[count].resp = string; + string = NULL; + } + } + + *resp = reply; + return PAM_SUCCESS; + +pam_fail_conv: + for (count = 0; count < num_msg; count++) { + if (!reply[count].resp) + continue; + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + case PAM_PROMPT_ECHO_ON: + free(reply[count].resp); + break; + } + } + free(reply); + return PAM_CONV_ERR; +} + +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + +static int login(void *obj, char *username, int ulen, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen _U_) +{ + struct passwd *pwd; + int err, PAM_error; + + if (uam_afpserver_option(obj, UAM_OPTION_CLIENTNAME, + (void *) &hostname, NULL) < 0) + { + LOG(log_info, logtype_uams, "uams_pam.c :PAM: unable to retrieve client hostname"); + hostname = NULL; + } + + ibuf[ PASSWDLEN ] = '\0'; + + if (( pwd = uam_getname(obj, username, ulen)) == NULL ) { + return AFPERR_NOTAUTH; + } + + LOG(log_info, logtype_uams, "cleartext login: %s", username); + PAM_username = username; + PAM_password = ibuf; /* Set these things up for the conv function */ + + err = AFPERR_NOTAUTH; + PAM_error = pam_start("netatalk", username, &PAM_conversation, + &pamh); + if (PAM_error != PAM_SUCCESS) + goto login_err; + + pam_set_item(pamh, PAM_TTY, "afpd"); + pam_set_item(pamh, PAM_RHOST, hostname); + /* use PAM_DISALLOW_NULL_AUTHTOK if passwdminlen > 0 */ + PAM_error = pam_authenticate(pamh,0); + if (PAM_error != PAM_SUCCESS) { + if (PAM_error == PAM_MAXTRIES) + err = AFPERR_PWDEXPR; + goto login_err; + } + + PAM_error = pam_acct_mgmt(pamh, 0); + if (PAM_error != PAM_SUCCESS) { + if (PAM_error == PAM_NEW_AUTHTOK_REQD) /* Password change required */ + err = AFPERR_PWDEXPR; +#ifdef PAM_AUTHTOKEN_REQD + else if (PAM_error == PAM_AUTHTOKEN_REQD) + err = AFPERR_PWDCHNG; +#endif /* PAM_AUTHTOKEN_REQD */ + else + goto login_err; + } + +#ifndef PAM_CRED_ESTABLISH +#define PAM_CRED_ESTABLISH PAM_ESTABLISH_CRED +#endif /* PAM_CRED_ESTABLISH */ + PAM_error = pam_setcred(pamh, PAM_CRED_ESTABLISH); + if (PAM_error != PAM_SUCCESS) + goto login_err; + + PAM_error = pam_open_session(pamh, 0); + if (PAM_error != PAM_SUCCESS) + goto login_err; + + *uam_pwd = pwd; + + if (err == AFPERR_PWDEXPR) + return err; + + return AFP_OK; + +login_err: + pam_end(pamh, PAM_error); + pamh = NULL; + return err; +} + +/* -------------------------- + cleartxt login +*/ +static int pam_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) { + return AFPERR_MISC; + } + + len = (unsigned char) *ibuf++; + if ( len > ulen ) { + return( AFPERR_PARAM ); + } + + memcpy(username, ibuf, len ); + ibuf += len; + + username[ len ] = '\0'; + + if ((unsigned long) ibuf & 1) /* pad character */ + ++ibuf; + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* ----------------------------- */ +static int pam_login_ext(void *obj, char *uname, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + uint16_t temp16; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &ulen) < 0) + return AFPERR_MISC; + + if (*uname != 3) + return AFPERR_PARAM; + uname++; + memcpy(&temp16, uname, sizeof(temp16)); + len = ntohs(temp16); + + if (!len || len > ulen ) { + return( AFPERR_PARAM ); + } + memcpy(username, uname +2, len ); + username[ len ] = '\0'; + + return (login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* logout */ +static void pam_logout(void) { + pam_close_session(pamh, 0); + pam_end(pamh, 0); + pamh = NULL; +} + +/* change passwd */ +static int pam_changepw(void *obj _U_, char *username, + struct passwd *pwd _U_, char *ibuf, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen _U_) +{ + char pw[PASSWDLEN + 1]; + pam_handle_t *lpamh; + uid_t uid; + int PAM_error; + + /* old password */ + memcpy(pw, ibuf, PASSWDLEN); + memset(ibuf, 0, PASSWDLEN); + pw[PASSWDLEN] = '\0'; + + /* let's do a quick check for the same password */ + if (memcmp(pw, ibuf + PASSWDLEN, PASSWDLEN) == 0) + return AFPERR_PWDSAME; + + /* Set these things up for the conv function */ + PAM_username = username; + PAM_password = pw; + + PAM_error = pam_start("netatalk", username, &PAM_conversation, + &lpamh); + if (PAM_error != PAM_SUCCESS) + return AFPERR_PARAM; + pam_set_item(lpamh, PAM_TTY, "afpd"); + pam_set_item(lpamh, PAM_RHOST, hostname); + + /* we might need to do this as root */ + uid = geteuid(); + seteuid(0); + PAM_error = pam_authenticate(lpamh,0); + if (PAM_error != PAM_SUCCESS) { + seteuid(uid); + pam_end(lpamh, PAM_error); + return AFPERR_NOTAUTH; + } + + /* new password */ + ibuf += PASSWDLEN; + PAM_password = ibuf; + ibuf[PASSWDLEN] = '\0'; + + /* this really does need to be done as root */ + PAM_error = pam_chauthtok(lpamh, 0); + seteuid(uid); /* un-root ourselves. */ + memset(pw, 0, PASSWDLEN); + memset(ibuf, 0, PASSWDLEN); + if (PAM_error != PAM_SUCCESS) { + pam_end(lpamh, PAM_error); + return AFPERR_ACCESS; + } + + pam_end(lpamh, 0); + return AFP_OK; +} + + +/* Printer ClearTxtUAM login */ +static int pam_printer(char *start, char *stop, char *username, struct papfile *out) +{ + int PAM_error; + char *data, *p, *q; + char password[PASSWDLEN + 1] = "\0"; + static const char *loginok = "0\r"; + struct passwd *pwd; + + data = (char *)malloc(stop - start + 1); + if (!data) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: malloc"); + return(-1); + } + + strlcpy(data, start, stop - start + 1); + + /* We are looking for the following format in data: + * (username) (password) + * + * Let's hope username doesn't contain ") ("! + */ + + /* Parse input for username in () */ + if ((p = strchr(data, '(' )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string"); + free(data); + return(-1); + } + p++; + if ((q = strstr(p, ") (" )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string"); + free(data); + return(-1); + } + memcpy(username, p, MIN(UAM_USERNAMELEN, q - p) ); + + /* Parse input for password in next () */ + p = q + 3; + if ((q = strrchr(p, ')' )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: password not found in string"); + free(data); + return(-1); + } + memcpy(password, p, MIN(PASSWDLEN, (q - p)) ); + + /* Done copying username and password, clean up */ + free(data); + + if (( pwd = uam_getname(NULL, username, strlen(username))) == NULL ) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: ( %s ) not found ", + username); + return(-1); + } + + if (uam_checkuser(pwd) < 0) { + /* syslog of error happens in uam_checkuser */ + return(-1); + } + + PAM_username = username; + PAM_password = password; + + PAM_error = pam_start("netatalk", username, &PAM_conversation, + &pamh); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: %s", + username, pam_strerror(pamh, PAM_error)); + pam_end(pamh, PAM_error); + pamh = NULL; + return(-1); + } + + pam_set_item(pamh, PAM_TTY, "papd"); + pam_set_item(pamh, PAM_RHOST, hostname); + PAM_error = pam_authenticate(pamh,0); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: %s", + username, pam_strerror(pamh, PAM_error)); + pam_end(pamh, PAM_error); + pamh = NULL; + return(-1); + } + + PAM_error = pam_acct_mgmt(pamh, 0); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: %s", + username, pam_strerror(pamh, PAM_error)); + pam_end(pamh, PAM_error); + pamh = NULL; + return(-1); + } + + PAM_error = pam_open_session(pamh, 0); + if (PAM_error != PAM_SUCCESS) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: %s", + username, pam_strerror(pamh, PAM_error)); + pam_end(pamh, PAM_error); + pamh = NULL; + return(-1); + } + + /* Login successful, but no need to hang onto it, + so logout immediately */ + append(out, loginok, strlen(loginok)); + LOG(log_info, logtype_uams, "Login ClearTxtUAM: %s", username); + pam_close_session(pamh, 0); + pam_end(pamh, 0); + pamh = NULL; + + return(0); +} + + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Cleartxt Passwrd", + pam_login, NULL, pam_logout, pam_login_ext) < 0) + return -1; + + if (uam_register(UAM_SERVER_CHANGEPW, path, "Cleartxt Passwrd", + pam_changepw) < 0) { + uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd"); + return -1; + } + + if (uam_register(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM", + pam_printer) < 0) { + return -1; + } + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd"); + uam_unregister(UAM_SERVER_CHANGEPW, "Cleartxt Passwrd"); + uam_unregister(UAM_SERVER_PRINTAUTH, "ClearTxtUAM"); +} + +UAM_MODULE_EXPORT struct uam_export uams_clrtxt = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + +UAM_MODULE_EXPORT struct uam_export uams_pam = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; diff --git a/etc/uams/uams_passwd.c b/etc/uams/uams_passwd.c new file mode 100644 index 0000000..9cd738c --- /dev/null +++ b/etc/uams/uams_passwd.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include + +#include +#include +#include +#include +#include +#ifdef HAVE_CRYPT_H +#include +#endif /* ! HAVE_CRYPT_H */ +#include +#include +#include +#ifdef SHADOWPW +#include +#endif /* SHADOWPW */ +#include + +#include +#include +#include +#include +#include + +#define PASSWDLEN 8 + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + + +#ifdef TRU64 +#include +#include + +static const char *clientname; +#endif /* TRU64 */ + +/*XXX in etc/papd/file.h */ +struct papfile; +extern UAM_MODULE_EXPORT void append(struct papfile *, const char *, int); + +static int pwd_login(void *obj, char *username, int ulen, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf _U_, size_t *rbuflen _U_) +{ + char *p; + struct passwd *pwd; + int err = AFP_OK; +#ifdef SHADOWPW + struct spwd *sp; +#endif /* SHADOWPW */ + +#ifdef TRU64 + if( uam_afpserver_option( obj, UAM_OPTION_CLIENTNAME, + (void *) &clientname, NULL ) < 0 ) + return AFPERR_MISC; +#endif /* TRU64 */ + + if (ibuflen < PASSWDLEN) { + return( AFPERR_PARAM ); + } + ibuf[ PASSWDLEN ] = '\0'; + + if (( pwd = uam_getname(obj, username, ulen)) == NULL ) { + return AFPERR_NOTAUTH; + } + + LOG(log_info, logtype_uams, "cleartext login: %s", username); + + if (uam_checkuser(pwd) < 0) { + LOG(log_info, logtype_uams, "not a valid user"); + return AFPERR_NOTAUTH; + } + +#ifdef SHADOWPW + if (( sp = getspnam( pwd->pw_name )) == NULL ) { + LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username); + return AFPERR_NOTAUTH; + } + pwd->pw_passwd = sp->sp_pwdp; + + if (sp->sp_max != -1 && sp->sp_lstchg) { + time_t now = time(NULL) / (60*60*24); + int32_t expire_days = sp->sp_lstchg - now + sp->sp_max; + if ( expire_days < 0 ) { + LOG(log_info, logtype_uams, "Password for user %s expired", username); + err = AFPERR_PWDEXPR; + } + } +#endif /* SHADOWPW */ + + if (!pwd->pw_passwd) { + return AFPERR_NOTAUTH; + } + + *uam_pwd = pwd; + +#ifdef TRU64 + { + int ac; + char **av; + char hostname[256]; + + uam_afp_getcmdline( &ac, &av ); + sprintf( hostname, "%s@%s", username, clientname ); + + if( uam_sia_validate_user( NULL, ac, av, hostname, username, + NULL, FALSE, NULL, ibuf ) != SIASUCCESS ) + return AFPERR_NOTAUTH; + + return err; + } +#else /* TRU64 */ + p = crypt( ibuf, pwd->pw_passwd ); + if ( strcmp( p, pwd->pw_passwd ) == 0 ) + return err; +#endif /* TRU64 */ + + return AFPERR_NOTAUTH; + +} + +/* cleartxt login */ +static int passwd_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, + (void *) &username, &ulen) < 0) + return AFPERR_MISC; + + if (ibuflen < 2) { + return( AFPERR_PARAM ); + } + + len = (unsigned char) *ibuf++; + ibuflen--; + if (!len || len > ibuflen || len > ulen ) { + return( AFPERR_PARAM ); + } + memcpy(username, ibuf, len ); + ibuf += len; + ibuflen -=len; + username[ len ] = '\0'; + + if ((unsigned long) ibuf & 1) { /* pad character */ + ++ibuf; + ibuflen--; + } + return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); + +} + +/* cleartxt login ext + * uname format : + byte 3 + 2 bytes len (network order) + len bytes unicode name +*/ +static int passwd_login_ext(void *obj, char *uname, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + uint16_t temp16; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, + (void *) &username, &ulen) < 0) + return AFPERR_MISC; + + if (*uname != 3) + return AFPERR_PARAM; + uname++; + memcpy(&temp16, uname, sizeof(temp16)); + len = ntohs(temp16); + if (!len || len > ulen ) { + return( AFPERR_PARAM ); + } + memcpy(username, uname +2, len ); + username[ len ] = '\0'; + return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + + +#if 0 +/* change passwd */ +static int passwd_changepw(void *obj, char *username, + struct passwd *pwd, char *ibuf, + size_t ibuflen, char *rbuf, size_t *rbuflen) +{ +#ifdef SHADOWPW + struct spwd *sp; +#endif /* SHADOWPW */ + char pw[PASSWDLEN + 1], *p; + uid_t uid = geteuid(); + + if (uam_checkuser(pwd) < 0) + return AFPERR_ACCESS; + + /* old password */ + memcpy(pw, ibuf, PASSWDLEN); + memset(ibuf, 0, PASSWDLEN); + pw[PASSWDLEN] = '\0'; + +#ifdef SHADOWPW + if (( sp = getspnam( pwd->pw_name )) == NULL ) { + LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username); + return AFPERR_PARAM; + } + pwd->pw_passwd = sp->sp_pwdp; +#endif /* SHADOWPW */ + + p = crypt(pw, pwd->pw_passwd ); + if (strcmp( p, pwd->pw_passwd )) { + memset(pw, 0, sizeof(pw)); + return AFPERR_NOTAUTH; + } + + /* new password */ + ibuf += PASSWDLEN; + ibuf[PASSWDLEN] = '\0'; + +#ifdef SHADOWPW +#else /* SHADOWPW */ +#endif /* SHADOWPW */ + return AFP_OK; +} +#endif /* 0 */ + + +/* Printer ClearTxtUAM login */ +static int passwd_printer(char *start, char *stop, char *username, struct papfile *out) +{ + struct passwd *pwd; +#ifdef SHADOWPW + struct spwd *sp; +#endif /* SHADOWPW */ + char *data, *p, *q; + char password[PASSWDLEN + 1] = "\0"; + static const char *loginok = "0\r"; + int ulen; + + data = (char *)malloc(stop - start + 1); + if (!data) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: malloc"); + return(-1); + } + strlcpy(data, start, stop - start + 1); + + /* We are looking for the following format in data: + * (username) (password) + * + * Let's hope username doesn't contain ") ("! + */ + + /* Parse input for username in () */ + if ((p = strchr(data, '(' )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string"); + free(data); + return(-1); + } + p++; + if ((q = strstr(p, ") (" )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string"); + free(data); + return(-1); + } + memcpy(username, p, MIN( UAM_USERNAMELEN, q - p )); + + /* Parse input for password in next () */ + p = q + 3; + if ((q = strrchr(p , ')' )) == NULL) { + LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: password not found in string"); + free(data); + return(-1); + } + memcpy(password, p, MIN(PASSWDLEN, q - p) ); + + /* Done copying username and password, clean up */ + free(data); + + ulen = strlen(username); + + if (( pwd = uam_getname(NULL, username, ulen)) == NULL ) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: ( %s ) not found ", + username); + return(-1); + } + + if (uam_checkuser(pwd) < 0) { + /* syslog of error happens in uam_checkuser */ + return(-1); + } + +#ifdef SHADOWPW + if (( sp = getspnam( pwd->pw_name )) == NULL ) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no shadow passwd entry for %s", + username); + return(-1); + } + pwd->pw_passwd = sp->sp_pwdp; + + if (sp->sp_max != -1 && sp->sp_lstchg) { + time_t now = time(NULL) / (60*60*24); + int32_t expire_days = sp->sp_lstchg - now + sp->sp_max; + if ( expire_days < 0 ) { + LOG(log_info, logtype_uams, "Password for user %s expired", username); + return (-1); + } + } + +#endif /* SHADOWPW */ + + if (!pwd->pw_passwd) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no password for %s", + username); + return(-1); + } + +#ifdef AFS + if ( kcheckuser( pwd, password) == 0) + return(0); +#endif /* AFS */ + + p = crypt(password, pwd->pw_passwd); + if (strcmp(p, pwd->pw_passwd) != 0) { + LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: bad password", username); + return(-1); + } + + /* Login successful */ + append(out, loginok, strlen(loginok)); + LOG(log_info, logtype_uams, "Login ClearTxtUAM: %s", username); + return(0); +} + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Cleartxt Passwrd", + passwd_login, NULL, NULL, passwd_login_ext) < 0) + return -1; + if (uam_register(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM", + passwd_printer) < 0) + return -1; + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd"); + uam_unregister(UAM_SERVER_PRINTAUTH, "ClearTxtUAM"); +} + +UAM_MODULE_EXPORT struct uam_export uams_clrtxt = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup + }; + +UAM_MODULE_EXPORT struct uam_export uams_passwd = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup + }; diff --git a/etc/uams/uams_pgp.c b/etc/uams/uams_pgp.c new file mode 100644 index 0000000..679a160 --- /dev/null +++ b/etc/uams/uams_pgp.c @@ -0,0 +1,197 @@ +/* + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef UAM_PGP + +#include + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_CRYPT_H +#include +#endif /* HAVE_CRYPT_H */ +#include +#include + +#if defined(GNUTLS_DHX) +#include +#elif defined(OPENSSL_DHX) +#include +#include +#include +#else /* OPENSSL_DHX */ +#include +#include +#include +#endif /* OPENSSL_DHX */ + +#include +#include + +#define KEYSIZE 16 +#define PASSWDLEN 64 +#define CRYPTBUFLEN (KEYSIZE*2) +#define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN) + +/* hash a number to a 16-bit quantity */ +#define pgphash(a) ((((unsigned long) (a) >> 8) ^ \ + (unsigned long) (a)) & 0xffff) + +/* the secret key */ +static struct passwd *pgppwd; +static CAST_KEY castkey; +static uint8_t randbuf[16]; + +/* pgp passwd */ +static int pgp_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + size_t len, i; + char *name; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &name, &i) < 0) + return AFPERR_PARAM; + + len = (unsigned char) *ibuf++; + if ( len > i ) { + return( AFPERR_PARAM ); + } + + memcpy(name, ibuf, len ); + ibuf += len; + name[ len ] = '\0'; + if ((unsigned long) ibuf & 1) /* padding */ + ++ibuf; + + if (( pgppwd = uam_getname(obj, name, i)) == NULL ) { + return AFPERR_PARAM; + } + + LOG(log_info, logtype_uams, "pgp login: %s", name); + if (uam_checkuser(pgppwd) < 0) + return AFPERR_NOTAUTH; + + /* get the challenge */ + len = (unsigned char) *ibuf++; + /* challenge */ + + /* get the signature. it's always 16 bytes. */ + if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE, + (void *) &name, NULL) < 0) { + *rbuflen = 0; + goto pgp_fail; + } + memcpy(rbuf + KEYSIZE, name, KEYSIZE); + +pgp_fail: + return AFPERR_PARAM; +} + +static int pgp_logincont(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + unsigned char iv[] = "RJscorat"; + BIGNUM *bn1, *bn2, *bn3; + uint16_t sessid; + char *p; + + *rbuflen = 0; + + /* check for session id */ + memcpy(&sessid, ibuf, sizeof(sessid)); + if (sessid != pgphash(obj)) + return AFPERR_PARAM; + ibuf += sizeof(sessid); + + /* use rbuf as scratch space */ + CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey, + iv, CAST_DECRYPT); + + /* check to make sure that the random number is the same. we + * get sent back an incremented random number. */ + if (!(bn1 = BN_bin2bn(rbuf, KEYSIZE, NULL))) + return AFPERR_PARAM; + + if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) { + BN_free(bn1); + return AFPERR_PARAM; + } + + /* zero out the random number */ + memset(rbuf, 0, sizeof(randbuf)); + memset(randbuf, 0, sizeof(randbuf)); + rbuf += KEYSIZE; + + if (!(bn3 = BN_new())) { + BN_free(bn2); + BN_free(bn1); + return AFPERR_PARAM; + } + + BN_sub(bn3, bn1, bn2); + BN_free(bn2); + BN_free(bn1); + + /* okay. is it one more? */ + if (!BN_is_one(bn3)) { + BN_free(bn3); + return AFPERR_PARAM; + } + BN_free(bn3); + +#ifdef AFS + if ( kcheckuser(*uam_pwd, rbuf) == 0) { + *uam_pwd = pgppwd; + return AFP_OK; + } +#endif /* AFS */ + + rbuf[PASSWDLEN] = '\0'; + p = crypt( rbuf, pgppwd->pw_passwd ); + memset(rbuf, 0, PASSWDLEN); + if ( strcmp( p, pgppwd->pw_passwd ) == 0 ) { + *uam_pwd = pgppwd; + return AFP_OK; + } + + return AFPERR_NOTAUTH; +} + + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN, path, "PGPuam 1.0", + pgp_login, pgp_logincont, NULL) < 0) + return -1; + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "PGPuam 1.0"); +} + +UAM_MODULE_EXPORT struct uam_export uams_pgp = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; + +#endif /* UAM_PGP */ diff --git a/etc/uams/uams_randnum.c b/etc/uams/uams_randnum.c new file mode 100644 index 0000000..50ce6ce --- /dev/null +++ b/etc/uams/uams_randnum.c @@ -0,0 +1,570 @@ +/* + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include + +#ifdef USE_CRACKLIB +#include +#endif /* USE_CRACKLIB */ + +#define PASSWDLEN 8 + +static C_Block seskey; +static Key_schedule seskeysched; +static struct passwd *randpwd; +static uint8_t randbuf[8]; + +/* hash to a 16-bit number. this will generate completely harmless + * warnings on 64-bit machines. */ +#define randhash(a) (((((unsigned long) a) >> 8) ^ \ + ((unsigned long)a)) & 0xffff) + + +/* handle ~/.passwd. courtesy of shirsch@ibm.net. */ +static int home_passwd(const struct passwd *pwd, + const char *path, const int pathlen _U_, + unsigned char *passwd, const int len, + const int set) +{ + struct stat st; + int fd, i; + + if ( (fd = open(path, (set) ? O_WRONLY : O_RDONLY)) < 0 ) { + LOG(log_error, logtype_uams, "Failed to open %s", path); + return AFPERR_ACCESS; + } + + if ( fstat( fd, &st ) < 0 ) + goto home_passwd_fail; + + /* If any of these are true, disallow login: + * - not a regular file + * - gid or uid don't match user + * - anyone else has permissions of any sort + */ + if (!S_ISREG(st.st_mode) || (pwd->pw_uid != st.st_uid) || + (pwd->pw_gid != st.st_gid) || + (st.st_mode & ( S_IRWXG | S_IRWXO )) ) { + LOG(log_info, logtype_uams, "Insecure permissions found for %s.", path); + goto home_passwd_fail; + } + + /* get the password */ + if (set) { + if (write(fd, passwd, len) < 0) { + LOG(log_error, logtype_uams, "Failed to write to %s", path ); + goto home_passwd_fail; + } + } else { + if (read(fd, passwd, len) < 0) { + LOG(log_error, logtype_uams, "Failed to read from %s", path ); + goto home_passwd_fail; + } + + /* get rid of pesky characters */ + for (i = 0; i < len; i++) + if ((passwd[i] != ' ') && isspace(passwd[i])) + passwd[i] = '\0'; + } + + close(fd); + return AFP_OK; + +home_passwd_fail: + close(fd); + return AFPERR_ACCESS; +} + + + +/* + * handle /path/afppasswd with an optional key file. we're a lot more + * trusting of this file. NOTE: we use our own password entry writing + * bits as we want to avoid tromping over global variables. in addition, + * we look for a key file and use that if it's there. here are the + * formats: + * password file: + * username:password:last login date:failedcount + * + * password is just the hex equivalent of either the ASCII password + * (if the key file doesn't exist) or the des encrypted password. + * + * key file: + * key (in hex) */ +#define PASSWD_ILLEGAL '*' +#define unhex(x) (isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A') +static int afppasswd(const struct passwd *pwd, + const char *path, const int pathlen, + unsigned char *passwd, int len, + const int set) +{ + uint8_t key[DES_KEY_SZ*2]; + char buf[MAXPATHLEN + 1], *p; + Key_schedule schedule; + FILE *fp; + unsigned int i, j; + int keyfd = -1, err = 0; + off_t pos; + + if ((fp = fopen(path, (set) ? "r+" : "r")) == NULL) { + LOG(log_error, logtype_uams, "Failed to open %s", path); + return AFPERR_ACCESS; + } + + /* open the key file if it exists */ + strcpy(buf, path); + if (pathlen < (int) sizeof(buf) - 5) { + strcat(buf, ".key"); + keyfd = open(buf, O_RDONLY); + } + + pos = ftell(fp); + memset(buf, 0, sizeof(buf)); + while (fgets(buf, sizeof(buf), fp)) { + if ((p = strchr(buf, ':'))) { + if ( strlen(pwd->pw_name) == (p - buf) && + strncmp(buf, pwd->pw_name, p - buf) == 0) { + p++; + if (*p == PASSWD_ILLEGAL) { + LOG(log_info, logtype_uams, "invalid password entry for %s", pwd->pw_name); + err = AFPERR_ACCESS; + goto afppasswd_done; + } + goto afppasswd_found; + } + } + pos = ftell(fp); + memset(buf, 0, sizeof(buf)); + } + err = AFPERR_PARAM; + goto afppasswd_done; + +afppasswd_found: + if (!set) { + /* convert to binary. */ + for (i = j = 0; i < sizeof(key); i += 2, j++) + p[j] = (unhex(p[i]) << 4) | unhex(p[i + 1]); + if (j <= DES_KEY_SZ) + memset(p + j, 0, sizeof(key) - j); + } + + if (keyfd > -1) { + /* read in the hex representation of an 8-byte key */ + read(keyfd, key, sizeof(key)); + + /* convert to binary key */ + for (i = j = 0; i < strlen((char *) key); i += 2, j++) + key[j] = (unhex(key[i]) << 4) | unhex(key[i + 1]); + if (j <= DES_KEY_SZ) + memset(key + j, 0, sizeof(key) - j); + key_sched((C_Block *) key, schedule); + memset(key, 0, sizeof(key)); + + if (set) { + /* NOTE: this takes advantage of the fact that passwd doesn't + * get used after this call if it's being set. */ + ecb_encrypt((C_Block *) passwd, (C_Block *) passwd, schedule, + DES_ENCRYPT); + } else { + /* decrypt the password */ + ecb_encrypt((C_Block *) p, (C_Block *) p, schedule, DES_DECRYPT); + } + memset(&schedule, 0, sizeof(schedule)); + } + + if (set) { + const unsigned char hextable[] = "0123456789ABCDEF"; + struct flock lock; + int fd = fileno(fp); + + /* convert to hex password */ + for (i = j = 0; i < DES_KEY_SZ; i++, j += 2) { + key[j] = hextable[(passwd[i] & 0xF0) >> 4]; + key[j + 1] = hextable[passwd[i] & 0x0F]; + } + memcpy(p, key, sizeof(key)); + + /* get exclusive access to the user's password entry. we don't + * worry so much on reads. in the worse possible case there, the + * user will just need to re-enter their password. */ + lock.l_type = F_WRLCK; + lock.l_start = pos; + lock.l_len = 1; + lock.l_whence = SEEK_SET; + + fseek(fp, pos, SEEK_SET); + fcntl(fd, F_SETLKW, &lock); + fwrite(buf, p - buf + sizeof(key), 1, fp); + lock.l_type = F_UNLCK; + fcntl(fd, F_SETLK, &lock); + } else + memcpy(passwd, p, len); + + memset(buf, 0, sizeof(buf)); + +afppasswd_done: + if (keyfd > -1) + close(keyfd); + fclose(fp); + return err; +} + + +/* this sets the uid. it needs to do slightly different things + * depending upon whether or not the password is in ~/.passwd + * or in a global location */ +static int randpass(const struct passwd *pwd, const char *file, + unsigned char *passwd, const int len, const int set) +{ + int i; + uid_t uid = geteuid(); + + /* Build pathname to user's '.passwd' file */ + i = strlen(file); + if (*file == '~') { + char path[MAXPATHLEN + 1]; + + if ( (strlen(pwd->pw_dir) + i - 1) > MAXPATHLEN) + return AFPERR_PARAM; + + strcpy(path, pwd->pw_dir ); + strcat(path, "/" ); + strcat(path, file + 2); + if (!uid) + seteuid(pwd->pw_uid); /* change ourselves to the user */ + i = home_passwd(pwd, path, i, passwd, len, set); + if (!uid) + seteuid(0); /* change ourselves back to root */ + return i; + } + + if (i > MAXPATHLEN) + return AFPERR_PARAM; + + /* handle afppasswd file. we need to make sure that we're root + * when we do this. */ + if (uid) + seteuid(0); + i = afppasswd(pwd, file, i, passwd, len, set); + if (uid) + seteuid(uid); + return i; +} + +/* randnum sends an 8-byte number and uses the user's password to + * check against the encrypted reply. */ +static int rand_login(void *obj, char *username, int ulen, struct passwd **uam_pwd _U_, + char *ibuf _U_, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ + + char *passwdfile; + uint16_t sessid; + size_t len; + int err; + + if (( randpwd = uam_getname(obj, username, ulen)) == NULL ) + return AFPERR_NOTAUTH; /* unknown user */ + + LOG(log_info, logtype_uams, "randnum/rand2num login: %s", username); + if (uam_checkuser(randpwd) < 0) + return AFPERR_NOTAUTH; + + len = UAM_PASSWD_FILENAME; + if (uam_afpserver_option(obj, UAM_OPTION_PASSWDOPT, + (void *) &passwdfile, &len) < 0) + return AFPERR_PARAM; + + if ((err = randpass(randpwd, passwdfile, seskey, + sizeof(seskey), 0)) != AFP_OK) + return err; + + /* get a random number */ + len = sizeof(randbuf); + if (uam_afpserver_option(obj, UAM_OPTION_RANDNUM, + (void *) randbuf, &len) < 0) + return AFPERR_PARAM; + + /* session id is a hashed version of the obj pointer */ + sessid = randhash(obj); + memcpy(rbuf, &sessid, sizeof(sessid)); + rbuf += sizeof(sessid); + *rbuflen = sizeof(sessid); + + /* send the random number off */ + memcpy(rbuf, randbuf, sizeof(randbuf)); + *rbuflen += sizeof(randbuf); + return AFPERR_AUTHCONT; +} + + +/* check encrypted reply. we actually setup the encryption stuff + * here as the first part of randnum and rand2num are identical. */ +static int randnum_logincont(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen _U_, + char *rbuf _U_, size_t *rbuflen) +{ + uint16_t sessid; + + *rbuflen = 0; + + memcpy(&sessid, ibuf, sizeof(sessid)); + if (sessid != randhash(obj)) + return AFPERR_PARAM; + + ibuf += sizeof(sessid); + + /* encrypt. this saves a little space by using the fact that + * des can encrypt in-place without side-effects. */ + key_sched((C_Block *) seskey, seskeysched); + memset(seskey, 0, sizeof(seskey)); + ecb_encrypt((C_Block *) randbuf, (C_Block *) randbuf, + seskeysched, DES_ENCRYPT); + memset(&seskeysched, 0, sizeof(seskeysched)); + + /* test against what the client sent */ + if (memcmp( randbuf, ibuf, sizeof(randbuf) )) { /* != */ + memset(randbuf, 0, sizeof(randbuf)); + return AFPERR_NOTAUTH; + } + + memset(randbuf, 0, sizeof(randbuf)); + *uam_pwd = randpwd; + return AFP_OK; +} + + +/* differences from randnum: + * 1) each byte of the key is shifted left one bit + * 2) client sends the server a 64-bit number. the server encrypts it + * and sends it back as part of the reply. + */ +static int rand2num_logincont(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen) +{ + uint16_t sessid; + unsigned int i; + + *rbuflen = 0; + + /* compare session id */ + memcpy(&sessid, ibuf, sizeof(sessid)); + if (sessid != randhash(obj)) + return AFPERR_PARAM; + + ibuf += sizeof(sessid); + + /* shift key elements left one bit */ + for (i = 0; i < sizeof(seskey); i++) + seskey[i] <<= 1; + + /* encrypt randbuf */ + key_sched((C_Block *) seskey, seskeysched); + memset(seskey, 0, sizeof(seskey)); + ecb_encrypt( (C_Block *) randbuf, (C_Block *) randbuf, + seskeysched, DES_ENCRYPT); + + /* test against client's reply */ + if (memcmp(randbuf, ibuf, sizeof(randbuf))) { /* != */ + memset(randbuf, 0, sizeof(randbuf)); + memset(&seskeysched, 0, sizeof(seskeysched)); + return AFPERR_NOTAUTH; + } + ibuf += sizeof(randbuf); + memset(randbuf, 0, sizeof(randbuf)); + + /* encrypt client's challenge and send back */ + ecb_encrypt( (C_Block *) ibuf, (C_Block *) rbuf, + seskeysched, DES_ENCRYPT); + memset(&seskeysched, 0, sizeof(seskeysched)); + *rbuflen = sizeof(randbuf); + + *uam_pwd = randpwd; + return AFP_OK; +} + +/* change password -- + * NOTE: an FPLogin must already have completed successfully for this + * to work. + */ +static int randnum_changepw(void *obj, const char *username _U_, + struct passwd *pwd, char *ibuf, + size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen _U_) +{ + char *passwdfile; + int err; + size_t len; + + if (uam_checkuser(pwd) < 0) + return AFPERR_ACCESS; + + len = UAM_PASSWD_FILENAME; + if (uam_afpserver_option(obj, UAM_OPTION_PASSWDOPT, + (void *) &passwdfile, &len) < 0) + return AFPERR_PARAM; + + /* old password is encrypted with new password and new password is + * encrypted with old. */ + if ((err = randpass(pwd, passwdfile, seskey, + sizeof(seskey), 0)) != AFP_OK) + return err; + + /* use old passwd to decrypt new passwd */ + key_sched((C_Block *) seskey, seskeysched); + ibuf += PASSWDLEN; /* new passwd */ + ibuf[PASSWDLEN] = '\0'; + ecb_encrypt( (C_Block *) ibuf, (C_Block *) ibuf, seskeysched, DES_DECRYPT); + + /* now use new passwd to decrypt old passwd */ + key_sched((C_Block *) ibuf, seskeysched); + ibuf -= PASSWDLEN; /* old passwd */ + ecb_encrypt((C_Block *) ibuf, (C_Block *) ibuf, seskeysched, DES_DECRYPT); + if (memcmp(seskey, ibuf, sizeof(seskey))) + err = AFPERR_NOTAUTH; + else if (memcmp(seskey, ibuf + PASSWDLEN, sizeof(seskey)) == 0) + err = AFPERR_PWDSAME; +#ifdef USE_CRACKLIB + else if (FascistCheck(ibuf + PASSWDLEN, _PATH_CRACKLIB)) + err = AFPERR_PWDPOLCY; +#endif /* USE_CRACKLIB */ + + if (!err) + err = randpass(pwd, passwdfile, (unsigned char *)ibuf + PASSWDLEN, sizeof(seskey), 1); + + /* zero out some fields */ + memset(&seskeysched, 0, sizeof(seskeysched)); + memset(seskey, 0, sizeof(seskey)); + memset(ibuf, 0, sizeof(seskey)); /* old passwd */ + memset(ibuf + PASSWDLEN, 0, sizeof(seskey)); /* new passwd */ + + if (err) + return err; + + return( AFP_OK ); +} + +/* randnum login */ +static int randnum_login(void *obj, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, + (void *) &username, &ulen) < 0) + return AFPERR_MISC; + + if (ibuflen < 2) { + return( AFPERR_PARAM ); + } + + len = (unsigned char) *ibuf++; + ibuflen--; + if (!len || len > ibuflen || len > ulen ) { + return( AFPERR_PARAM ); + } + memcpy(username, ibuf, len ); + ibuf += len; + ibuflen -=len; + username[ len ] = '\0'; + + if ((unsigned long) ibuf & 1) { /* pad character */ + ++ibuf; + ibuflen--; + } + return (rand_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +/* randnum login ext */ +static int randnum_login_ext(void *obj, char *uname, struct passwd **uam_pwd, + char *ibuf, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + char *username; + size_t len, ulen; + uint16_t temp16; + + *rbuflen = 0; + + if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, + (void *) &username, &ulen) < 0) + return AFPERR_MISC; + + if (*uname != 3) + return AFPERR_PARAM; + uname++; + memcpy(&temp16, uname, sizeof(temp16)); + len = ntohs(temp16); + if (!len || len > ulen ) { + return( AFPERR_PARAM ); + } + memcpy(username, uname +2, len ); + username[ len ] = '\0'; + return (rand_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); +} + +static int uam_setup(void *obj, const char *path) +{ + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Randnum exchange", + randnum_login, randnum_logincont, NULL, randnum_login_ext) < 0) + return -1; + + if (uam_register(UAM_SERVER_LOGIN_EXT, path, "2-Way Randnum exchange", + randnum_login, rand2num_logincont, NULL, randnum_login_ext) < 0) { + uam_unregister(UAM_SERVER_LOGIN, "Randnum exchange"); + return -1; + } + + if (uam_register(UAM_SERVER_CHANGEPW, path, "Randnum Exchange", + randnum_changepw) < 0) { + uam_unregister(UAM_SERVER_LOGIN, "Randnum exchange"); + uam_unregister(UAM_SERVER_LOGIN, "2-Way Randnum exchange"); + return -1; + } + /*uam_register(UAM_SERVER_PRINTAUTH, path, "Randnum Exchange", + pam_printer);*/ + + return 0; +} + +static void uam_cleanup(void) +{ + uam_unregister(UAM_SERVER_LOGIN, "Randnum exchange"); + uam_unregister(UAM_SERVER_LOGIN, "2-Way Randnum exchange"); + uam_unregister(UAM_SERVER_CHANGEPW, "Randnum Exchange"); + /*uam_unregister(UAM_SERVER_PRINTAUTH, "Randnum Exchange");*/ +} + +UAM_MODULE_EXPORT struct uam_export uams_randnum = { + UAM_MODULE_SERVER, + UAM_MODULE_VERSION, + uam_setup, uam_cleanup +}; diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..88e75d2 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,3 @@ +# Makefile.am for include/ + +SUBDIRS = atalk diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 0000000..7aad789 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,706 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for include/ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = include +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = atalk +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + cscopelist cscopelist-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# 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/include/atalk/Makefile.am b/include/atalk/Makefile.am new file mode 100644 index 0000000..550741d --- /dev/null +++ b/include/atalk/Makefile.am @@ -0,0 +1,59 @@ +# Makefile.am for include/atalk/ + +atalkincludedir = $(includedir)/atalk +BUILT_SOURCES = +CLEANFILES = + +atalkinclude_HEADERS = \ + adouble.h \ + afp.h \ + vfs.h \ + cnid.h \ + logger.h \ + netatalk_conf.h \ + paths.h \ + unicode.h \ + util.h \ + ea.h \ + acl.h \ + unix.h \ + volume.h \ + standards.h \ + bstrlib.h \ + list.h \ + globals.h \ + compat.h \ + uam.h \ + iniparser.h \ + dictionary.h \ + hash.h + +noinst_HEADERS = \ + directory.h \ + uuid.h \ + queue.h \ + server_child.h \ + server_ipc.h \ + tdb.h \ + cnid_bdb_private.h \ + cnid_mysql_private.h \ + cnid_private.h \ + bstradd.h \ + errchk.h \ + ftw.h \ + dsi.h \ + ldapconfig.h \ + talloc.h \ + dalloc.h \ + byteorder.h \ + fce_api.h \ + spotlight.h + +EXTRA_DIST = afp_dtrace.d + +if WITH_DTRACE +BUILT_SOURCES += afp_dtrace.h +CLEANFILES += afp_dtrace.h +afp_dtrace.h: $(top_srcdir)/include/atalk/afp_dtrace.d + $(LIBTOOL) --mode=execute dtrace -o afp_dtrace.h -h -s $(top_srcdir)/include/atalk/afp_dtrace.d +endif diff --git a/include/atalk/Makefile.in b/include/atalk/Makefile.in new file mode 100644 index 0000000..62b45c2 --- /dev/null +++ b/include/atalk/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for include/atalk/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@WITH_DTRACE_TRUE@am__append_1 = afp_dtrace.h +@WITH_DTRACE_TRUE@am__append_2 = afp_dtrace.h +subdir = include/atalk +DIST_COMMON = $(atalkinclude_HEADERS) $(noinst_HEADERS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(atalkincludedir)" +HEADERS = $(atalkinclude_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +atalkincludedir = $(includedir)/atalk +BUILT_SOURCES = $(am__append_1) +CLEANFILES = $(am__append_2) +atalkinclude_HEADERS = \ + adouble.h \ + afp.h \ + vfs.h \ + cnid.h \ + logger.h \ + netatalk_conf.h \ + paths.h \ + unicode.h \ + util.h \ + ea.h \ + acl.h \ + unix.h \ + volume.h \ + standards.h \ + bstrlib.h \ + list.h \ + globals.h \ + compat.h \ + uam.h \ + iniparser.h \ + dictionary.h \ + hash.h + +noinst_HEADERS = \ + directory.h \ + uuid.h \ + queue.h \ + server_child.h \ + server_ipc.h \ + tdb.h \ + cnid_bdb_private.h \ + cnid_mysql_private.h \ + cnid_private.h \ + bstradd.h \ + errchk.h \ + ftw.h \ + dsi.h \ + ldapconfig.h \ + talloc.h \ + dalloc.h \ + byteorder.h \ + fce_api.h \ + spotlight.h + +EXTRA_DIST = afp_dtrace.d +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/atalk/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/atalk/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-atalkincludeHEADERS: $(atalkinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(atalkinclude_HEADERS)'; test -n "$(atalkincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(atalkincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(atalkincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(atalkincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(atalkincludedir)" || exit $$?; \ + done + +uninstall-atalkincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(atalkinclude_HEADERS)'; test -n "$(atalkincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(atalkincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(atalkincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-atalkincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-atalkincludeHEADERS + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool cscopelist ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am \ + install-atalkincludeHEADERS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags uninstall uninstall-am \ + uninstall-atalkincludeHEADERS + +@WITH_DTRACE_TRUE@afp_dtrace.h: $(top_srcdir)/include/atalk/afp_dtrace.d +@WITH_DTRACE_TRUE@ $(LIBTOOL) --mode=execute dtrace -o afp_dtrace.h -h -s $(top_srcdir)/include/atalk/afp_dtrace.d + +# 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/include/atalk/acl.h b/include/atalk/acl.h new file mode 100644 index 0000000..c7343a9 --- /dev/null +++ b/include/atalk/acl.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifndef ATALK_ACL_H +#define ATALK_ACL_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_ACLS + +#define O_NETATALK_ACL (O_NOFOLLOW << 1) +#define O_IGNORE (O_NOFOLLOW << 2) + +#ifdef HAVE_SOLARIS_ACLS +#include +#endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif + +#ifdef HAVE_NFSV4_ACLS + +#define chmod_acl nfsv4_chmod + +extern int get_nfsv4_acl(const char *name, ace_t **retAces); +extern int strip_trivial_aces(ace_t **saces, int sacecount); +extern int strip_nontrivial_aces(ace_t **saces, int sacecount); +extern ace_t *concat_aces(ace_t *aces1, int ace1count, ace_t *aces2, int ace2count); +extern int nfsv4_chmod(char *name, mode_t mode); + +#endif /* HAVE_NFSV4_ACLS */ + +#ifdef HAVE_POSIX_ACLS +#include +#include +#include + +#define chmod_acl posix_chmod +#define fchmod_acl posix_fchmod + +extern int posix_chmod(const char *name, mode_t mode); +extern int posix_fchmod(int fd, mode_t mode); + +#endif /* HAVE_POSIX_ACLS */ + +extern int remove_acl_vfs(const char *name); + +#else /* HAVE_ACLS=no */ + +#define O_NETATALK_ACL 0 +#define chmod_acl chmod + +#endif /* HAVE_ACLS */ + +#endif /* ATALK_ACL_H */ diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h new file mode 100644 index 0000000..40c92a1 --- /dev/null +++ b/include/atalk/adouble.h @@ -0,0 +1,465 @@ + /* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +/*! + * @file + * @brief Part of Netatalk's AppleDouble implementatation + */ + +#ifndef _ATALK_ADOUBLE_H +#define _ATALK_ADOUBLE_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +/* version info */ +#define AD_VERSION2 0x00020000 +#define AD_VERSION_EA 0x00020002 + +/* default */ +#define AD_VERSION AD_VERSION_EA + +/* + * AppleDouble entry IDs. + */ +#define ADEID_DFORK 1 +#define ADEID_RFORK 2 +#define ADEID_NAME 3 +#define ADEID_COMMENT 4 +#define ADEID_ICONBW 5 +#define ADEID_ICONCOL 6 +#define ADEID_FILEI 7 /* v1, replaced by: */ +#define ADEID_FILEDATESI 8 /* this */ +#define ADEID_FINDERI 9 +#define ADEID_MACFILEI 10 /* we don't use this */ +#define ADEID_PRODOSFILEI 11 /* we store prodos info here */ +#define ADEID_MSDOSFILEI 12 /* we don't use this */ +#define ADEID_SHORTNAME 13 +#define ADEID_AFPFILEI 14 /* where the rest of the FILEI info goes */ +#define ADEID_DID 15 + +/* netatalk private note fileid reused DID */ +#define ADEID_PRIVDEV 16 +#define ADEID_PRIVINO 17 +#define ADEID_PRIVSYN 18 /* in synch with database */ +#define ADEID_PRIVID 19 +#define ADEID_MAX (ADEID_PRIVID + 1) + +/* These are the real ids for these entries, as stored in the adouble file */ +#define AD_DEV 0x80444556 +#define AD_INO 0x80494E4F +#define AD_SYN 0x8053594E +#define AD_ID 0x8053567E + +/* magic */ +#define AD_APPLESINGLE_MAGIC 0x00051600 +#define AD_APPLEDOUBLE_MAGIC 0x00051607 +#define AD_MAGIC AD_APPLEDOUBLE_MAGIC + +/* sizes of relevant entry bits */ +#define ADEDLEN_MAGIC 4 +#define ADEDLEN_VERSION 4 +#define ADEDLEN_FILLER 16 +#define ADEDLEN_NENTRIES 2 +#define AD_HEADER_LEN (ADEDLEN_MAGIC + ADEDLEN_VERSION + ADEDLEN_FILLER + ADEDLEN_NENTRIES) /* 26 */ +#define AD_ENTRY_LEN 12 /* size of a single entry header */ + +/* field widths */ +#define ADEDLEN_NAME 255 +#define ADEDLEN_COMMENT 200 +#define ADEDLEN_FILEI 16 +#define ADEDLEN_FINDERI 32 +#define ADEDLEN_FILEDATESI 16 +#define ADEDLEN_SHORTNAME 12 /* length up to 8.3 */ +#define ADEDLEN_AFPFILEI 4 +#define ADEDLEN_MACFILEI 4 +#define ADEDLEN_PRODOSFILEI 8 +#define ADEDLEN_MSDOSFILEI 2 +#define ADEDLEN_DID 4 +#define ADEDLEN_PRIVDEV 8 +#define ADEDLEN_PRIVINO 8 +#define ADEDLEN_PRIVSYN 8 +#define ADEDLEN_PRIVID 4 + +#define ADEID_NUM_V2 13 +#define ADEID_NUM_EA 8 +#define ADEID_NUM_OSX 2 + +#define AD_DATASZ2 (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT + ADEDLEN_FILEI + \ + ADEDLEN_FINDERI + ADEDLEN_DID + ADEDLEN_AFPFILEI + ADEDLEN_SHORTNAME + \ + ADEDLEN_PRODOSFILEI + ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + \ + ADEDLEN_PRIVSYN + ADEDLEN_PRIVID + (ADEID_NUM_V2 * AD_ENTRY_LEN)) +#if AD_DATASZ2 != 741 +#error bad size for AD_DATASZ2 +#endif + +#define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + \ + ADEDLEN_FINDERI + ADEDLEN_COMMENT + ADEDLEN_FILEDATESI + ADEDLEN_AFPFILEI + \ + ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + ADEDLEN_PRIVSYN + ADEDLEN_PRIVID) + +#if AD_DATASZ_EA != 402 +#error bad size for AD_DATASZ_EA +#endif + +#define AD_DATASZ_OSX (AD_HEADER_LEN + (ADEID_NUM_OSX * AD_ENTRY_LEN) + ADEDLEN_FINDERI) + +#if AD_DATASZ_OSX != 82 +#error bad size for AD_DATASZ_OSX +#endif + +#define AD_DATASZ_MAX 1024 + +#if AD_VERSION == AD_VERSION2 +#define AD_DATASZ AD_DATASZ2 +#elif AD_VERSION == AD_VERSION_EA +#define AD_DATASZ AD_DATASZ_EA +#endif + +/* fallback for ad:ea on filesystems without fds for EAs, like old adouble:osx */ +#define ADEDOFF_FINDERI_OSX (AD_HEADER_LEN + ADEID_NUM_OSX*AD_ENTRY_LEN) +#define ADEDOFF_RFORK_OSX (ADEDOFF_FINDERI_OSX + ADEDLEN_FINDERI) + +/* special fd value used to indicate an open fork file is a (not open) symlink */ +#define AD_SYMLINK -2 + +typedef uint32_t cnid_t; + +struct ad_entry { + off_t ade_off; + ssize_t ade_len; +}; + +typedef struct adf_lock_t { + struct flock lock; + int user; + int *refcount; /* handle read locks with multiple users */ +} adf_lock_t; + +struct ad_fd { + int adf_fd; /* -1: invalid, AD_SYMLINK: symlink */ + char *adf_syml; + int adf_flags; + adf_lock_t *adf_lock; + int adf_refcount, adf_lockcount, adf_lockmax; +}; + +/* some header protection */ +#define AD_INITED 0xad494e54 /* ad"INT" */ +#define AD_CLOSED 0xadc10ced + +struct adouble; + +struct adouble_fops { + const char *(*ad_path)(const char *, int); + int (*ad_mkrf)(const char *); + int (*ad_rebuild_header)(struct adouble *); + int (*ad_header_read)(const char *, struct adouble *, const struct stat *); + int (*ad_header_upgrade)(struct adouble *, const char *); +}; + +struct adouble { + uint32_t ad_magic; /* Official adouble magic */ + uint32_t ad_version; /* Official adouble version number */ + char ad_filler[16]; + struct ad_entry ad_eid[ADEID_MAX]; + + struct ad_fd ad_data_fork; /* the data fork */ + + struct ad_fd ad_resource_fork; /* adouble:v2 -> the adouble file * + * adouble:ea -> the EA fd */ + + struct ad_fd *ad_rfp; /* adouble:v2 -> ad_resource_fork * + * adouble:ea -> ad_resource_fork */ + + struct ad_fd *ad_mdp; /* adouble:v2 -> ad_resource_fork * + * adouble:ea -> ad_data_fork */ + + int ad_vers; /* Our adouble version info (AD_VERSION*) */ + int ad_adflags; /* ad_open flags adflags like ADFLAGS_DIR */ + uint32_t ad_inited; + int ad_options; + int ad_refcount; /* multiple forks may open one adouble */ + int ad_data_refcount; + int ad_meta_refcount; + int ad_reso_refcount; + off_t ad_rlen; /* ressource fork len with AFP 3.0 * + * the header parameter size is too small. */ + char *ad_name; /* mac name (maccharset or UTF8-MAC) */ + struct adouble_fops *ad_ops; + uint16_t ad_open_forks; /* open forks (by others) */ + char ad_data[AD_DATASZ_MAX]; +}; + +#define ADFLAGS_DF (1<<0) +#define ADFLAGS_RF (1<<1) +#define ADFLAGS_HF (1<<2) +#define ADFLAGS_DIR (1<<3) +#define ADFLAGS_NOHF (1<<4) /* not an error if no metadata fork */ +#define ADFLAGS_NORF (1<<5) /* not an error if no ressource fork */ +#define ADFLAGS_CHECK_OF (1<<6) /* check for open forks from us and other afpd's */ +#define ADFLAGS_SETSHRMD (1<<7) /* setting share mode must be done with excl fcnt lock, + which implies that the file must be openend rw. + If it can't be opened rw (eg EPERM or EROFS) it will + be opened ro and the fcntl locks will be shared, that + at least prevent other users who have rw access to the + file from placing excl locks. */ +#define ADFLAGS_RDWR (1<<8) /* open read/write */ +#define ADFLAGS_RDONLY (1<<9) /* open read only */ +#define ADFLAGS_CREATE (1<<10) /* create file, open called with O_CREAT */ +#define ADFLAGS_EXCL (1<<11) /* exclusive open, open called with O_EXCL */ +#define ADFLAGS_TRUNC (1<<12) /* truncate, open called with O_TRUNC */ + +#define ADVOL_NODEV (1 << 0) +#define ADVOL_RO (1 << 1) +#define ADVOL_UNIXPRIV (1 << 2) /* adouble unix priv */ +#define ADVOL_INVDOTS (1 << 3) /* dot files (.DS_Store) are invisible) */ +#define ADVOL_FOLLO_SYML (1 << 4) +#define ADVOL_FORCE_STICKY_XATTR (1 << 5) + +/* lock flags */ +#define ADLOCK_CLR (0) +#define ADLOCK_RD (1<<0) +#define ADLOCK_WR (1<<1) +#define ADLOCK_MASK (ADLOCK_RD | ADLOCK_WR) +#define ADLOCK_UPGRADE (1<<2) +#define ADLOCK_FILELOCK (1<<3) + +/* we use this so that we can use the same mechanism for both byte + * locks and file synchronization locks. */ +#if _FILE_OFFSET_BITS == 64 +#define AD_FILELOCK_BASE (UINT64_C(0x7FFFFFFFFFFFFFFF) - 9) +#else +#define AD_FILELOCK_BASE (UINT32_C(0x7FFFFFFF) - 9) +#endif + +#define BYTELOCK_MAX (AD_FILELOCK_BASE - 1) + +/* datafork and rsrcfork sharemode locks */ +#define AD_FILELOCK_OPEN_WR (AD_FILELOCK_BASE + 0) +#define AD_FILELOCK_OPEN_RD (AD_FILELOCK_BASE + 1) +#define AD_FILELOCK_RSRC_OPEN_WR (AD_FILELOCK_BASE + 2) +#define AD_FILELOCK_RSRC_OPEN_RD (AD_FILELOCK_BASE + 3) + +#define AD_FILELOCK_DENY_WR (AD_FILELOCK_BASE + 4) +#define AD_FILELOCK_DENY_RD (AD_FILELOCK_BASE + 5) +#define AD_FILELOCK_RSRC_DENY_WR (AD_FILELOCK_BASE + 6) +#define AD_FILELOCK_RSRC_DENY_RD (AD_FILELOCK_BASE + 7) + +#define AD_FILELOCK_OPEN_NONE (AD_FILELOCK_BASE + 8) +#define AD_FILELOCK_RSRC_OPEN_NONE (AD_FILELOCK_BASE + 9) + +/* time stuff. we overload the bits a little. */ +#define AD_DATE_CREATE 0 +#define AD_DATE_MODIFY 4 +#define AD_DATE_BACKUP 8 +#define AD_DATE_ACCESS 12 +#define AD_DATE_MASK (AD_DATE_CREATE | AD_DATE_MODIFY | \ + AD_DATE_BACKUP | AD_DATE_ACCESS) +#define AD_DATE_UNIX (1 << 10) +#define AD_DATE_START htonl(0x80000000) +#define AD_DATE_DELTA 946684800 +#define AD_DATE_FROM_UNIX(x) htonl((x) - AD_DATE_DELTA) +#define AD_DATE_TO_UNIX(x) (ntohl(x) + AD_DATE_DELTA) + +/* various finder offset and info bits */ +#define FINDERINFO_FRTYPEOFF 0 +#define FINDERINFO_FRCREATOFF 4 +#define FINDERINFO_FRFLAGOFF 8 + +/* FinderInfo Flags, char in `ad ls`, valid for files|dirs */ +#define FINDERINFO_ISONDESK (1) /* "d", fd */ +#define FINDERINFO_COLOR (0x0e) +#define FINDERINFO_HIDEEXT (1<<4) /* "e", fd */ +#define FINDERINFO_ISHARED (1<<6) /* "m", f */ +#define FINDERINFO_HASNOINITS (1<<7) /* "n", f */ +#define FINDERINFO_HASBEENINITED (1<<8) /* "i", fd */ +#define FINDERINFO_HASCUSTOMICON (1<<10) /* "c", fd */ +#define FINDERINFO_ISSTATIONNERY (1<<11) /* "t", f */ +#define FINDERINFO_NAMELOCKED (1<<12) /* "s", fd */ +#define FINDERINFO_HASBUNDLE (1<<13) /* "b", fd */ +#define FINDERINFO_INVISIBLE (1<<14) /* "v", fd */ +#define FINDERINFO_ISALIAS (1<<15) /* "a", fd */ + +#define FINDERINFO_FRVIEWOFF 14 +#define FINDERINFO_CUSTOMICON 0x4 +#define FINDERINFO_CLOSEDVIEW 0x100 + +/* + The "shared" and "invisible" attributes are opaque and stored and + retrieved from the FinderFlags. This fixes Bug #2802236: + +*/ + +/* AFP attributes, char in `ad ls`, valid for files|dirs */ +#define ATTRBIT_INVISIBLE (1<<0) /* opaque from FinderInfo */ +#define ATTRBIT_MULTIUSER (1<<1) /* file: opaque, dir: see below */ +#define ATTRBIT_SYSTEM (1<<2) /* "y", fd */ +#define ATTRBIT_DOPEN (1<<3) /* data fork already open. Not stored, computed on the fly */ +#define ATTRBIT_ROPEN (1<<4) /* resource fork already open. Not stored, computed on the fly */ +#define ATTRBIT_NOWRITE (1<<5) /* "w", f, write inhibit(v2)/read-only(v1) bit */ +#define ATTRBIT_BACKUP (1<<6) /* "p", fd */ +#define ATTRBIT_NORENAME (1<<7) /* "r", fd */ +#define ATTRBIT_NODELETE (1<<8) /* "l", fd */ +#define ATTRBIT_NOCOPY (1<<10) /* "o", f */ +#define ATTRBIT_SETCLR (1<<15) /* set/clear bit (d) */ + +/* AFP attributes for dirs. These should probably be computed on the fly. + * We don't do that, nor does e.g. OS S X 10.5 Server */ +#define ATTRBIT_EXPFLDR (1<<1) /* Folder is a sharepoint */ +#define ATTRBIT_MOUNTED (1<<3) /* Directory is mounted by a user */ +#define ATTRBIT_SHARED (1<<4) /* Shared area, called IsExpFolder in spec */ + +/* private AFPFileInfo bits */ +#define AD_AFPFILEI_OWNER (1 << 0) /* any owner */ +#define AD_AFPFILEI_GROUP (1 << 1) /* ignore group */ +#define AD_AFPFILEI_BLANKACCESS (1 << 2) /* blank access permissions */ + +/* + * String identifiers for the 16 AppleDouble filler bytes + */ +#define AD_FILLER_NETATALK "Netatalk " +#define AD_FILLER_OSX "Mac OS X" + +#define ad_data_fileno(ad) ((ad)->ad_data_fork.adf_fd) +#define ad_reso_fileno(ad) ((ad)->ad_rfp->adf_fd) +#define ad_meta_fileno(ad) ((ad)->ad_mdp->adf_fd) + +/* -1: not open, AD_SYMLINK (-2): it's a symlink */ +#define AD_DATA_OPEN(ad) (((ad)->ad_data_refcount) && (ad_data_fileno(ad) >= 0)) +#define AD_META_OPEN(ad) (((ad)->ad_meta_refcount) && (ad_meta_fileno(ad) >= 0)) +#define AD_RSRC_OPEN(ad) (((ad)->ad_reso_refcount) && (ad_reso_fileno(ad) >= 0)) + +#define ad_getversion(ad) ((ad)->ad_version) + +#define ad_getentrylen(ad,eid) ((ad)->ad_eid[(eid)].ade_len) +#define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len)) +#define ad_setentryoff(ad,eid,off) ((ad)->ad_eid[(eid)].ade_off = (off)) +#define ad_entry(ad,eid) ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off) + +#define ad_get_RF_flags(ad) ((ad)->ad_rfp->adf_flags) +#define ad_get_MD_flags(ad) ((ad)->ad_mdp->adf_flags) + +/* Refcounting open forks using one struct adouble */ +#define ad_ref(ad) (ad)->ad_refcount++ +#define ad_unref(ad) --((ad)->ad_refcount) + +#define ad_get_syml_opt(ad) (((ad)->ad_options & ADVOL_FOLLO_SYML) ? 0 : O_NOFOLLOW) + +/* ad_flush.c */ +extern int ad_rebuild_adouble_header_v2(struct adouble *); +extern int ad_rebuild_adouble_header_ea(struct adouble *); +extern int ad_rebuild_adouble_header_osx(struct adouble *ad, char *adbuf); +extern int ad_copy_header (struct adouble *, struct adouble *); +extern int ad_flush (struct adouble *); +extern int ad_close (struct adouble *, int); +extern int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags); + +/* ad_lock.c */ +extern int ad_testlock (struct adouble *adp, int eid, off_t off); +extern uint16_t ad_openforks(struct adouble *adp, uint16_t); +extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int fork); +extern void ad_unlock(struct adouble *, int fork, int unlckbrl); +extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int fork); + +/* ad_open.c */ +extern off_t ad_getentryoff(const struct adouble *ad, int eid); +extern const char *adflags2logstr(int adflags); +extern int ad_setfuid (const uid_t ); +extern uid_t ad_getfuid (void ); +extern char *ad_dir (const char *); +extern const char *ad_path (const char *, int); +extern const char *ad_path_ea (const char *, int); +extern const char *ad_path_osx (const char *path, int adflags); +extern int ad_mode (const char *, mode_t); +extern int ad_mkdir (const char *, mode_t); +struct vol; +extern void ad_init (struct adouble *, const struct vol * restrict); +extern void ad_init_old (struct adouble *ad, int flags, int options); +extern int ad_init_offsets(struct adouble *ad); +extern int ad_open (struct adouble *ad, const char *path, int adflags, ...); +extern int ad_openat (struct adouble *, int dirfd, const char *path, int adflags, ...); +extern int ad_refresh (const char *path, struct adouble *); +extern int ad_stat (const char *, struct stat *); +extern int ad_metadata (const char *, int, struct adouble *); +extern int ad_metadataat (int, const char *, int, struct adouble *); +extern mode_t ad_hf_mode(mode_t mode); +extern int ad_valid_header_osx(const char *path); +extern off_t ad_reso_size(const char *path, int adflags, struct adouble *ad); + +/* ad_conv.c */ +extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath); + +/* ad_read.c/ad_write.c */ +extern int sys_ftruncate(int fd, off_t length); +extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t); +extern ssize_t ad_pread(struct ad_fd *, void *, size_t, off_t); +extern ssize_t ad_write(struct adouble *, uint32_t, off_t, int, const char *, size_t); +extern ssize_t adf_pread(struct ad_fd *, void *, size_t, off_t); +extern ssize_t adf_pwrite(struct ad_fd *, const void *, size_t, off_t); +extern int ad_dtruncate(struct adouble *, off_t); +extern int ad_rtruncate(struct adouble *, const char *, off_t); +extern int copy_fork(int eid, struct adouble *add, struct adouble *ads); + +/* ad_size.c */ +extern off_t ad_size (const struct adouble *, uint32_t ); + +/* ad_mmap.c */ +extern void *ad_mmapread(struct adouble *, uint32_t, off_t, size_t); +extern void *ad_mmapwrite(struct adouble *, uint32_t, off_t, int, size_t); +#define ad_munmap(buf, len) (munmap((buf), (len))) + +/* ad_date.c */ +extern int ad_setdate(struct adouble *, unsigned int, uint32_t); +extern int ad_getdate(const struct adouble *, unsigned int, uint32_t *); + +/* ad_attr.c */ +extern int ad_setattr(const struct adouble *, const uint16_t); +extern int ad_getattr(const struct adouble *, uint16_t *); +extern int ad_setname(struct adouble *, const char *); +extern int ad_setid(struct adouble *, dev_t dev, ino_t ino, uint32_t, uint32_t, const void *); +extern uint32_t ad_getid(struct adouble *, dev_t, ino_t, cnid_t, const void *); +extern uint32_t ad_forcegetid(struct adouble *adp); + +#ifdef WITH_SENDFILE +extern int ad_readfile_init(const struct adouble *ad, int eid, off_t *off, int end); +#endif +#ifdef WITH_RECVFILE +extern ssize_t ad_recvfile(struct adouble *ad, int eid, int sock, off_t off, size_t len, int); +#endif + +#endif /* _ATALK_ADOUBLE_H */ diff --git a/include/atalk/afp.h b/include/atalk/afp.h new file mode 100644 index 0000000..0c2489e --- /dev/null +++ b/include/atalk/afp.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifndef _ATALK_AFP_H +#define _ATALK_AFP_H 1 + +#include +#include + +typedef uint16_t AFPUserBytes; + +/* protocols */ +#define AFPPROTO_ASP 1 +#define AFPPROTO_DSI 2 + +/* server flags */ +#define AFPSRVRINFO_COPY (1<<0) /* supports copyfile */ +#define AFPSRVRINFO_PASSWD (1<<1) /* supports change password */ +#define AFPSRVRINFO_NOSAVEPASSWD (1<<2) /* don't allow save password */ +#define AFPSRVRINFO_SRVMSGS (1<<3) /* supports server messages */ +#define AFPSRVRINFO_SRVSIGNATURE (1<<4) /* supports server signature */ +#define AFPSRVRINFO_TCPIP (1<<5) /* supports tcpip */ +#define AFPSRVRINFO_SRVNOTIFY (1<<6) /* supports server notifications */ +#define AFPSRVRINFO_SRVRECONNECT (1<<7) /* supports server reconnect */ +#define AFPSRVRINFO_SRVRDIR (1<<8) /* supports directories service */ +#define AFPSRVRINFO_SRVUTF8 (1<<9) /* supports UTF8 names AFP 3.1 */ +#define AFPSRVRINFO_UUID (1<<10) /* supports UUIDs */ +#define AFPSRVRINFO_EXTSLEEP (1<<11) /* supports extended sleep */ +#define AFPSRVRINFO_FASTBOZO (1<<15) /* fast copying */ + +#define AFP_OK 0 +#define AFPERR_MAXSESS -1068 /* maximum number of allowed sessions reached */ +#define AFPERR_DID1 -4000 /* not an afp error DID is 1*/ +#define AFPERR_ACCESS -5000 /* permission denied */ +#define AFPERR_AUTHCONT -5001 /* logincont */ +#define AFPERR_BADUAM -5002 /* uam doesn't exist */ +#define AFPERR_BADVERS -5003 /* bad afp version number */ +#define AFPERR_BITMAP -5004 /* invalid bitmap */ +#define AFPERR_CANTMOVE -5005 /* can't move file */ +#define AFPERR_DENYCONF -5006 /* file synchronization locks conflict */ +#define AFPERR_DIRNEMPT -5007 /* directory not empty */ +#define AFPERR_DFULL -5008 /* disk full */ +#define AFPERR_EOF -5009 /* end of file -- catsearch and afp_read */ +#define AFPERR_BUSY -5010 /* FileBusy */ +#define AFPERR_FLATVOL -5011 /* volume doesn't support directories */ +#define AFPERR_NOITEM -5012 /* ItemNotFound */ +#define AFPERR_LOCK -5013 /* LockErr */ +#define AFPERR_MISC -5014 /* misc. err */ +#define AFPERR_NLOCK -5015 /* no more locks */ +#define AFPERR_NOSRVR -5016 /* no response by server at that address */ +#define AFPERR_EXIST -5017 /* object already exists */ +#define AFPERR_NOOBJ -5018 /* object not found */ +#define AFPERR_PARAM -5019 /* parameter error */ +#define AFPERR_NORANGE -5020 /* no range lock */ +#define AFPERR_RANGEOVR -5021 /* range overlap */ +#define AFPERR_SESSCLOS -5022 /* session closed */ +#define AFPERR_NOTAUTH -5023 /* user not authenticated */ +#define AFPERR_NOOP -5024 /* command not supported */ +#define AFPERR_BADTYPE -5025 /* object is the wrong type */ +#define AFPERR_NFILE -5026 /* too many files open */ +#define AFPERR_SHUTDOWN -5027 /* server is going down */ +#define AFPERR_NORENAME -5028 /* can't rename */ +#define AFPERR_NODIR -5029 /* couldn't find directory */ +#define AFPERR_ITYPE -5030 /* wrong icon type */ +#define AFPERR_VLOCK -5031 /* volume locked */ +#define AFPERR_OLOCK -5032 /* object locked */ +#define AFPERR_CTNSHRD -5033 /* share point contains a share point */ +#define AFPERR_NOID -5034 /* file thread not found */ +#define AFPERR_EXISTID -5035 /* file already has an id */ +#define AFPERR_DIFFVOL -5036 /* different volume */ +#define AFPERR_CATCHNG -5037 /* catalog has changed */ +#define AFPERR_SAMEOBJ -5038 /* source file == destination file */ +#define AFPERR_BADID -5039 /* non-existent file id */ +#define AFPERR_PWDSAME -5040 /* same password/can't change password */ +#define AFPERR_PWDSHORT -5041 /* password too short */ +#define AFPERR_PWDEXPR -5042 /* password expired */ +#define AFPERR_INSHRD -5043 /* folder being shared is inside a + shared folder. may be returned by + afpMoveAndRename. */ +#define AFPERR_INTRASH -5044 /* shared folder in trash. */ +#define AFPERR_PWDCHNG -5045 /* password needs to be changed */ +#define AFPERR_PWDPOLCY -5046 /* password fails policy check */ +#define AFPERR_USRLOGIN -5047 /* user already logged on */ + +/* AFP Attention Codes -- 4 bits */ +#define AFPATTN_SHUTDOWN (1 << 15) /* shutdown/disconnect */ +#define AFPATTN_CRASH (1 << 14) /* server crashed */ +#define AFPATTN_MESG (1 << 13) /* server has message */ +#define AFPATTN_NORECONNECT (1 << 12) /* don't reconnect */ +/* server notification */ +#define AFPATTN_NOTIFY (AFPATTN_MESG | AFPATTN_NORECONNECT) + +/* extended bitmap -- 12 bits. volchanged is only useful w/ a server + * notification, and time is only useful for shutdown. */ +#define AFPATTN_VOLCHANGED (1 << 0) /* volume has changed */ +#define AFPATTN_TIME(x) ((x) & 0xfff) /* time in minutes */ + +typedef enum { + AFPMESG_LOGIN = 0, + AFPMESG_SERVER = 1 +} afpmessage_t; + +/* extended sleep flag */ +#define AFPZZZ_EXT_SLEEP 1 +#define AFPZZZ_EXT_WAKEUP 2 + + +/* AFP functions */ +#define AFP_BYTELOCK 1 +#define AFP_CLOSEVOL 2 +#define AFP_CLOSEDIR 3 +#define AFP_CLOSEFORK 4 +#define AFP_COPYFILE 5 +#define AFP_CREATEDIR 6 +#define AFP_CREATEFILE 7 +#define AFP_DELETE 8 +#define AFP_ENUMERATE 9 +#define AFP_FLUSH 10 +#define AFP_FLUSHFORK 11 + +#define AFP_GETFORKPARAM 14 +#define AFP_GETSRVINFO 15 +#define AFP_GETSRVPARAM 16 +#define AFP_GETVOLPARAM 17 +#define AFP_LOGIN 18 +#define AFP_LOGINCONT 19 +#define AFP_LOGOUT 20 +#define AFP_MAPID 21 +#define AFP_MAPNAME 22 +#define AFP_MOVE 23 +#define AFP_OPENVOL 24 +#define AFP_OPENDIR 25 +#define AFP_OPENFORK 26 +#define AFP_READ 27 +#define AFP_RENAME 28 +#define AFP_SETDIRPARAM 29 +#define AFP_SETFILEPARAM 30 +#define AFP_SETFORKPARAM 31 +#define AFP_SETVOLPARAM 32 +#define AFP_WRITE 33 +#define AFP_GETFLDRPARAM 34 +#define AFP_SETFLDRPARAM 35 +#define AFP_CHANGEPW 36 +#define AFP_GETUSERINFO 37 +#define AFP_GETSRVRMSG 38 +#define AFP_CREATEID 39 +#define AFP_DELETEID 40 +#define AFP_RESOLVEID 41 +#define AFP_EXCHANGEFILE 42 +#define AFP_CATSEARCH 43 + +#define AFP_OPENDT 48 +#define AFP_CLOSEDT 49 + +#define AFP_GETICON 51 +#define AFP_GTICNINFO 52 +#define AFP_ADDAPPL 53 +#define AFP_RMVAPPL 54 + +#define AFP_GETAPPL 55 +#define AFP_ADDCMT 56 +#define AFP_RMVCMT 57 +#define AFP_GETCMT 58 +#define AFP_ADDICON 192 + +/* version 3.0 */ +#define AFP_BYTELOCK_EXT 59 +#define AFP_CATSEARCH_EXT 67 +#define AFP_ENUMERATE_EXT 66 +#define AFP_READ_EXT 60 +#define AFP_WRITE_EXT 61 +#define AFP_LOGIN_EXT 63 +#define AFP_GETSESSTOKEN 64 +#define AFP_DISCTOLDSESS 65 + +/* version 3.1 */ +#define AFP_ENUMERATE_EXT2 68 +#define AFP_SPOTLIGHT_PRIVATE 76 +#define AFP_SYNCDIR 78 +#define AFP_SYNCFORK 79 +#define AFP_ZZZ 122 + +/* version 3.2 */ +#define AFP_GETEXTATTR 69 +#define AFP_SETEXTATTR 70 +#define AFP_REMOVEATTR 71 +#define AFP_LISTEXTATTR 72 +#define AFP_GETACL 73 +#define AFP_SETACL 74 +#define AFP_ACCESS 75 + +/* more defines */ +#define REPLAYCACHE_SIZE 128 + +#endif diff --git a/include/atalk/afp_dtrace.d b/include/atalk/afp_dtrace.d new file mode 100644 index 0000000..e9ee989 --- /dev/null +++ b/include/atalk/afp_dtrace.d @@ -0,0 +1,10 @@ +provider afp { + probe afpfunc__start(int func, char *funcname); + probe afpfunc__done(int func, char *funcname); + probe read__start(long size); + probe read__done(); + probe write__start(long size); + probe write__done(); + probe cnid__start(char *cnidfunc); + probe cnid__done(); +}; diff --git a/include/atalk/bstradd.h b/include/atalk/bstradd.h new file mode 100644 index 0000000..310349b --- /dev/null +++ b/include/atalk/bstradd.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. +*/ + +/*! + * @file + * Additional functions for bstrlib. + */ + +#ifndef ATALK_BSTRADD_H +#define ATALK_BSTRADD_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#define cfrombstr(b) ((char *)((b)->data)) + +/* strip slashes from end of a bstring */ +#define BSTRING_STRIP_SLASH(a) \ + do { \ + while (bchar((a), blength(a) - 1) == '/') \ + bdelete((a), blength(a) - 1, 1); \ + } while (0); + +typedef struct tagbstring static_bstring; + +extern bstring brefcstr(const char *str); +extern int bunrefcstr(bstring b); + +extern struct bstrList *bstrListCreateMin(int min); +extern int bstrListPush(struct bstrList *sl, bstring bs); +extern bstring bstrListPop(struct bstrList *sl); +extern bstring bjoinInv(const struct bstrList * bl, const_bstring sep); +#endif /* ATALK_BSTRADD_H */ diff --git a/include/atalk/bstrlib.h b/include/atalk/bstrlib.h new file mode 100644 index 0000000..0cd3719 --- /dev/null +++ b/include/atalk/bstrlib.h @@ -0,0 +1,300 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2008, and is covered by the BSD open source + * license and the GPL. Refer to the accompanying documentation for details + * on usage and license. + */ + +/*! + * @file + * This file is the core module for implementing the bstring functions. + */ + +#ifndef BSTRLIB_INCLUDE +#define BSTRLIB_INCLUDE + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) +# if defined (__TURBOC__) && !defined (__BORLANDC__) +# define BSTRLIB_NOVSNP +# endif +#endif + +#define BSTR_ERR (-1) +#define BSTR_OK (0) +#define BSTR_BS_BUFF_LENGTH_GET (0) + +typedef struct tagbstring * bstring; +typedef const struct tagbstring * const_bstring; + +/* Copy functions */ +#define cstr2bstr bfromcstr +extern bstring bfromcstr (const char * str); +extern bstring bfromcstralloc (int mlen, const char * str); +extern bstring blk2bstr (const void * blk, int len); +extern char * bstr2cstr (const_bstring s, char z); +extern int bcstrfree (char * s); +extern bstring bstrcpy (const_bstring b1); +extern int bassign (bstring a, const_bstring b); +extern int bassignmidstr (bstring a, const_bstring b, int left, int len); +extern int bassigncstr (bstring a, const char * str); +extern int bassignblk (bstring a, const void * s, int len); + +/* Destroy function */ +extern int bdestroy (bstring b); + +/* Space allocation hinting functions */ +extern int balloc (bstring s, int len); +extern int ballocmin (bstring b, int len); + +/* Substring extraction */ +extern bstring bmidstr (const_bstring b, int left, int len); + +/* Various standard manipulations */ +extern int bconcat (bstring b0, const_bstring b1); +extern int bconchar (bstring b0, char c); +extern int bcatcstr (bstring b, const char * s); +extern int bcatblk (bstring b, const void * s, int len); +extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); +extern int binsertch (bstring s1, int pos, int len, unsigned char fill); +extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill); +extern int bdelete (bstring s1, int pos, int len); +extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); +extern int btrunc (bstring b, int n); + +/* Scan/search functions */ +extern int bstricmp (const_bstring b0, const_bstring b1); +extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); +extern int biseqcaseless (const_bstring b0, const_bstring b1); +extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); +extern int biseq (const_bstring b0, const_bstring b1); +extern int bisstemeqblk (const_bstring b0, const void * blk, int len); +extern int biseqcstr (const_bstring b, const char * s); +extern int biseqcstrcaseless (const_bstring b, const char * s); +extern int bstrcmp (const_bstring b0, const_bstring b1); +extern int bstrncmp (const_bstring b0, const_bstring b1, int n); +extern int binstr (const_bstring s1, int pos, const_bstring s2); +extern int binstrr (const_bstring s1, int pos, const_bstring s2); +extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); +extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); +extern int bstrchrp (const_bstring b, int c, int pos); +extern int bstrrchrp (const_bstring b, int c, int pos); +#define bstrchr(b,c) bstrchrp ((b), (c), 0) +#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1) +extern int binchr (const_bstring b0, int pos, const_bstring b1); +extern int binchrr (const_bstring b0, int pos, const_bstring b1); +extern int bninchr (const_bstring b0, int pos, const_bstring b1); +extern int bninchrr (const_bstring b0, int pos, const_bstring b1); +extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos); +extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos); + +/* List of string container functions */ +struct bstrList { + int qty, mlen; + bstring * entry; +}; +extern struct bstrList * bstrListCreate (void); +extern int bstrListDestroy (struct bstrList * sl); +extern int bstrListAlloc (struct bstrList * sl, int msz); +extern int bstrListAllocMin (struct bstrList * sl, int msz); + +/* String split and join functions */ +extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar); +extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr); +extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr); +extern bstring bjoin (const struct bstrList * bl, const_bstring sep); +extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); +extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); +extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + +/* Miscellaneous functions */ +extern int bpattern (bstring b, int len); +extern int btoupper (bstring b); +extern int btolower (bstring b); +extern int bltrimws (bstring b); +extern int brtrimws (bstring b); +extern int btrimws (bstring b); + +#if !defined (BSTRLIB_NOVSNP) +extern bstring bformat (const char * fmt, ...); +extern int bformata (bstring b, const char * fmt, ...); +extern int bassignformat (bstring b, const char * fmt, ...); +extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); + +#define bvformata(ret, b, fmt, lastarg) { \ +bstring bstrtmp_b = (b); \ +const char * bstrtmp_fmt = (fmt); \ +int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ + for (;;) { \ + va_list bstrtmp_arglist; \ + va_start (bstrtmp_arglist, lastarg); \ + bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ + va_end (bstrtmp_arglist); \ + if (bstrtmp_r >= 0) { /* Everything went ok */ \ + bstrtmp_r = BSTR_OK; \ + break; \ + } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ + bstrtmp_r = BSTR_ERR; \ + break; \ + } \ + bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ + } \ + ret = bstrtmp_r; \ +} + +#endif + +typedef int (*bNgetc) (void *parm); +typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm); + +/* Input functions */ +extern bstring bgetstream (bNgetc getcPtr, void * parm, char terminator); +extern bstring bread (bNread readPtr, void * parm); +extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); +extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); +extern int breada (bstring b, bNread readPtr, void * parm); + +/* Stream functions */ +extern struct bStream * bsopen (bNread readPtr, void * parm); +extern void * bsclose (struct bStream * s); +extern int bsbufflength (struct bStream * s, int sz); +extern int bsreadln (bstring b, struct bStream * s, char terminator); +extern int bsreadlns (bstring r, struct bStream * s, const_bstring term); +extern int bsread (bstring b, struct bStream * s, int n); +extern int bsreadlna (bstring b, struct bStream * s, char terminator); +extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term); +extern int bsreada (bstring b, struct bStream * s, int n); +extern int bsunread (struct bStream * s, const_bstring b); +extern int bspeek (bstring r, const struct bStream * s); +extern int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); +extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); +extern int bseof (const struct bStream * s); + +struct tagbstring { + int mlen; + int slen; + unsigned char * data; +}; + +/* Accessor macros */ +#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) +#define blength(b) (blengthe ((b), 0)) +#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o)) +#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0)) +#define bdatae(b, e) (bdataofse (b, 0, e)) +#define bdata(b) (bdataofs (b, 0)) +#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) +#define bchar(b, p) bchare ((b), (p), '\0') + +/* Static constant string initialization macro */ +#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")} +#if defined(_MSC_VER) +# define bsStatic(q) bsStaticMlen(q,-32) +#endif +#ifndef bsStatic +# define bsStatic(q) bsStaticMlen(q,-__LINE__) +#endif + +/* Static constant block parameter pair */ +#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) + +/* Reference building macros */ +#define cstr2tbstr btfromcstr +#define btfromcstr(t,s) { \ + (t).data = (unsigned char *) (s); \ + (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \ + (t).mlen = -1; \ +} +#define blk2tbstr(t,s,l) { \ + (t).data = (unsigned char *) (s); \ + (t).slen = l; \ + (t).mlen = -1; \ +} +#define btfromblk(t,s,l) blk2tbstr(t,s,l) +#define bmid2tbstr(t,b,p,l) { \ + const_bstring bstrtmp_s = (b); \ + if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ + int bstrtmp_left = (p); \ + int bstrtmp_len = (l); \ + if (bstrtmp_left < 0) { \ + bstrtmp_len += bstrtmp_left; \ + bstrtmp_left = 0; \ + } \ + if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ + bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ + if (bstrtmp_len <= 0) { \ + (t).data = (unsigned char *)""; \ + (t).slen = 0; \ + } else { \ + (t).data = bstrtmp_s->data + bstrtmp_left; \ + (t).slen = bstrtmp_len; \ + } \ + } else { \ + (t).data = (unsigned char *)""; \ + (t).slen = 0; \ + } \ + (t).mlen = -__LINE__; \ +} +#define btfromblkltrimws(t,s,l) { \ + int bstrtmp_idx = 0, bstrtmp_len = (l); \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} +#define btfromblkrtrimws(t,s,l) { \ + int bstrtmp_len = (l) - 1; \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_len >= 0; bstrtmp_len--) { \ + if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ + } \ + } \ + (t).data = bstrtmp_s; \ + (t).slen = bstrtmp_len + 1; \ + (t).mlen = -__LINE__; \ +} +#define btfromblktrimws(t,s,l) { \ + int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ + } \ + for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ + if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} + +/* Write protection macros */ +#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; } +#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); } +#define biswriteprotected(t) ((t).mlen <= 0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/atalk/byteorder.h b/include/atalk/byteorder.h new file mode 100644 index 0000000..0ea3972 --- /dev/null +++ b/include/atalk/byteorder.h @@ -0,0 +1,217 @@ +/* + Unix SMB/CIFS implementation. + SMB Byte handling + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BYTEORDER_H +#define _BYTEORDER_H +#include + +/* + This file implements macros for machine independent short and + int manipulation + +Here is a description of this file that I emailed to the samba list once: + +> I am confused about the way that byteorder.h works in Samba. I have +> looked at it, and I would have thought that you might make a distinction +> between LE and BE machines, but you only seem to distinguish between 386 +> and all other architectures. +> +> Can you give me a clue? + +sure. + +The distinction between 386 and other architectures is only there as +an optimisation. You can take it out completely and it will make no +difference. The routines (macros) in byteorder.h are totally byteorder +independent. The 386 optimsation just takes advantage of the fact that +the x86 processors don't care about alignment, so we don't have to +align ints on int boundaries etc. If there are other processors out +there that aren't alignment sensitive then you could also define +CAREFUL_ALIGNMENT=0 on those processors as well. + +Ok, now to the macros themselves. I'll take a simple example, say we +want to extract a 2 byte integer from a SMB packet and put it into a +type called uint16 that is in the local machines byte order, and you +want to do it with only the assumption that uint16 is _at_least_ 16 +bits long (this last condition is very important for architectures +that don't have any int types that are 2 bytes long) + +You do this: + +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) + +then to extract a uint16 value at offset 25 in a buffer you do this: + +char *buffer = foo_bar(); +uint16 xx = SVAL(buffer,25); + +We are using the byteoder independence of the ANSI C bitshifts to do +the work. A good optimising compiler should turn this into efficient +code, especially if it happens to have the right byteorder :-) + +I know these macros can be made a bit tidier by removing some of the +casts, but you need to look at byteorder.h as a whole to see the +reasoning behind them. byteorder.h defines the following macros: + +SVAL(buf,pos) - extract a 2 byte SMB value +IVAL(buf,pos) - extract a 4 byte SMB value +LVAL(buf,pos) - extract a 8 byte SMB value +SVALS(buf,pos) signed version of SVAL() +IVALS(buf,pos) signed version of IVAL() + +SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer +SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer +SSVALS(buf,pos,val) - signed version of SSVAL() +SIVALS(buf,pos,val) - signed version of SIVAL() + +RSVAL(buf,pos) - like SVAL() but for NMB byte ordering +RSVALS(buf,pos) - like SVALS() but for NMB byte ordering +RIVAL(buf,pos) - like IVAL() but for NMB byte ordering +RIVALS(buf,pos) - like IVALS() but for NMB byte ordering +RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering +RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering +RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering + +it also defines lots of intermediate macros, just ignore those :-) + +*/ + +#undef CAREFUL_ALIGNMENT + +/* we know that the 386 can handle misalignment and has the "right" + byteorder */ +#ifdef __i386__ +#define CAREFUL_ALIGNMENT 0 +#endif + +#ifndef CAREFUL_ALIGNMENT +#define CAREFUL_ALIGNMENT 1 +#endif + +#define CVAL(buf,pos) ((unsigned)(((const unsigned char *)(buf))[pos])) +#define CVAL_NC(buf,pos) (((unsigned char *)(buf))[pos]) /* Non-const version of CVAL */ +#define PVAL(buf,pos) (CVAL(buf,pos)) +#define SCVAL(buf,pos,val) (CVAL_NC(buf,pos) = (val)) + + +#if CAREFUL_ALIGNMENT + +#ifdef WORDS_BIGENDIAN + +#define SVAL(buf,pos) (PVAL(buf,(pos)+1)|PVAL(buf,pos)<<8) +#define SVALS(buf,pos) ((int16)SVAL(buf,pos)) +#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) +#define IVALS(buf,pos) ((int32_t)IVAL(buf,pos)) +#define LVAL(buf,pos) (IVAL(buf,pos)|IVAL(buf,(pos)+4)<<32) +#define LVALS(buf,pos) ((int64_t)LVAL(buf,pos)) + +#define SSVALX(buf,pos,val) (CVAL_NC(buf,pos+1)=(unsigned char)((val)&0xFF),CVAL_NC(buf,pos)=(unsigned char)((val)>>8)) +#define SIVALX(buf,pos,val) (SSVALX(buf,pos,((val)&0xFFFF)),SSVALX(buf,pos+2,(val)>>16)) +#define SLVALX(buf,pos,val) (SIVALX(buf,pos,((val)&0xFFFFFFFF)),SIVALX(buf,pos+4,(val)>>32)) + +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16_t)(val))) +#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) +#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32_t)(val))) +#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32_t)(val))) +#define SLVAL(buf,pos,val) SLVALX((buf),(pos),((uint64_t)(val))) +#define SLVALS(buf,pos,val) SLVALX((buf),(pos),((int64_t)(val))) + +#else + +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) +#define SVALS(buf,pos) ((int16)SVAL(buf,pos)) +#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) +#define IVALS(buf,pos) ((int32_t)IVAL(buf,pos)) +#define LVAL(buf,pos) (IVAL(buf,pos)|((uint64_t)IVAL(buf,(pos)+4))<<32) +#define LVALS(buf,pos) ((int64_t)LVAL(buf,pos)) + +#define SSVALX(buf,pos,val) (CVAL_NC(buf,pos)=(unsigned char)((val)&0xFF),CVAL_NC(buf,pos+1)=(unsigned char)((val)>>8)) +#define SIVALX(buf,pos,val) (SSVALX(buf,pos,((val)&0xFFFF)),SSVALX(buf,pos+2,(val)>>16)) +#define SLVALX(buf,pos,val) (SIVALX(buf,pos,((val)&0xFFFFFFFF)),SIVALX(buf,pos+4,(val)>>32)) + +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16_t)(val))) +#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) +#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32_t)(val))) +#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32_t)(val))) +#define SLVAL(buf,pos,val) SLVALX((buf),(pos),((uint64_t)(val))) +#define SLVALS(buf,pos,val) SLVALX((buf),(pos),((int64_t)(val))) + +#endif + +#else /* CAREFUL_ALIGNMENT */ + +/* this handles things for architectures like the 386 that can handle + alignment errors */ +/* + WARNING: This section is dependent on the length of int16 and int32 + being correct +*/ + +/* get single value from an SMB buffer */ +#define SVAL(buf,pos) (*(const uint16_t *)((const char *)(buf) + (pos))) +#define SVAL_NC(buf,pos) (*(uint16_t *)((char *)(buf) + (pos))) /* Non const version of above. */ +#define IVAL(buf,pos) (*(const uint32_t *)((const char *)(buf) + (pos))) +#define IVAL_NC(buf,pos) (*(uint32_t *)((char *)(buf) + (pos))) /* Non const version of above. */ +#define LVAL(buf,pos) (*(const uint64_t *)((const char *)(buf) + (pos))) +#define LVAL_NC(buf,pos) (*(uint64_t *)((char *)(buf) + (pos))) +#define SVALS(buf,pos) (*(const int16_t *)((const char *)(buf) + (pos))) +#define SVALS_NC(buf,pos) (*(int16 *)((char *)(buf) + (pos))) /* Non const version of above. */ +#define IVALS(buf,pos) (*(const int32_t *)((const char *)(buf) + (pos))) +#define IVALS_NC(buf,pos) (*(int32_t *)((char *)(buf) + (pos))) /* Non const version of above. */ +#define LVALS(buf,pos) (*(const int64_t *)((const char *)(buf) + (pos))) +#define LVALS_NC(buf,pos) (*(int64_t *)((char *)(buf) + (pos))) + +/* store single value in an SMB buffer */ +#define SSVAL(buf,pos,val) SVAL_NC(buf,pos)=((uint16_t)(val)) +#define SIVAL(buf,pos,val) IVAL_NC(buf,pos)=((uint32_t)(val)) +#define SLVAL(buf,pos,val) LVAL_NC(buf,pos)=((uint64_t)(val)) +#define SSVALS(buf,pos,val) SVALS_NC(buf,pos)=((int16)(val)) +#define SIVALS(buf,pos,val) IVALS_NC(buf,pos)=((int32_t)(val)) +#define SLVALS(buf,pos,val) LVALS_NC(buf,pos)=((int64_t)(val)) + +#endif /* CAREFUL_ALIGNMENT */ + +/* now the reverse routines - these are used in nmb packets (mostly) */ +#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) +#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) +#define LREV(x) ((IREV(x)<<32) | (IREV((x)>>32))) + +#define RSVAL(buf,pos) SREV(SVAL(buf,pos)) +#define RSVALS(buf,pos) SREV(SVALS(buf,pos)) +#define RIVAL(buf,pos) IREV(IVAL(buf,pos)) +#define RIVALS(buf,pos) IREV(IVALS(buf,pos)) +#define RLVAL(buf,pos) LREV(LVAL(buf,pos)) +#define RLVALS(buf,pos) LREV(LVALS(buf,pos)) + +#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) +#define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val)) +#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) +#define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val)) + +#define RSLVAL(buf,pos,val) SLVAL(buf,pos,LREV(val)) +#define RSLVALS(buf,pos,val) SLVALS(buf,pos,LREV(val)) + +/* Alignment macros. */ +#define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3)) +#define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1)) + +#endif /* _BYTEORDER_H */ diff --git a/include/atalk/cnid.h b/include/atalk/cnid.h new file mode 100644 index 0000000..4fefcd0 --- /dev/null +++ b/include/atalk/cnid.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2003 the Netatalk Team + * Copyright (c) 2003 Rafal Lewczuk + * Copyright (c) 2010 Frank Lahm + * + * This program is free software; you can redistribute 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 or later + * version if explicitly stated by any of above copyright holders. + * + */ + +/* + * This file contains all generic CNID related stuff + * declarations. Included: + * - CNID factory, which retrieves (eventually instantiates) + * CNID objects on demand + * - selection of CNID backends (default, detected by volume) + * - full set of CNID operations needed by server core. + */ + +#ifndef _ATALK_CNID__H +#define _ATALK_CNID__H 1 + +#include +#include +#include + +/* CNID object flags */ +#define CNID_FLAG_PERSISTENT 0x01 /* This backend implements DID persistence */ +#define CNID_FLAG_MANGLING 0x02 /* This backend has name mangling feature. */ +#define CNID_FLAG_SETUID 0x04 /* Set db owner to parent folder owner. */ +#define CNID_FLAG_BLOCK 0x08 /* block signals in update. */ +#define CNID_FLAG_NODEV 0x10 /* don't use device number only inode */ +#define CNID_FLAG_LAZY_INIT 0x20 /* */ +#define CNID_FLAG_MEMORY 0x40 /* this is a memory only db */ +#define CNID_FLAG_INODE 0x80 /* in cnid_add the inode is authoritative */ + +#define CNID_INVALID 0 +/* first valid ID */ +#define CNID_START 17 + +#define CNID_ERR_PARAM 0x80000001 +#define CNID_ERR_PATH 0x80000002 +#define CNID_ERR_DB 0x80000003 +#define CNID_ERR_CLOSE 0x80000004 /* the db was not open */ +#define CNID_ERR_MAX 0x80000005 + +/* + * This is instance of CNID database object. + */ +typedef struct _cnid_db { + uint32_t cnid_db_flags; /* Flags describing some CNID backend aspects. */ + struct vol *cnid_db_vol; + void *cnid_db_private; /* back-end speficic data */ + + cnid_t (*cnid_add) (struct _cnid_db *cdb, const struct stat *st, cnid_t did, + const char *name, size_t, cnid_t hint); + int (*cnid_delete) (struct _cnid_db *cdb, cnid_t id); + cnid_t (*cnid_get) (struct _cnid_db *cdb, cnid_t did, const char *name, size_t); + cnid_t (*cnid_lookup) (struct _cnid_db *cdb, const struct stat *st, cnid_t did, + const char *name, size_t); + cnid_t (*cnid_nextid) (struct _cnid_db *cdb); + char * (*cnid_resolve) (struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len); + int (*cnid_update) (struct _cnid_db *cdb, cnid_t id, const struct stat *st, + cnid_t did, const char *name, size_t len); + void (*cnid_close) (struct _cnid_db *cdb); + int (*cnid_getstamp) (struct _cnid_db *cdb, void *buffer, const size_t len); + cnid_t (*cnid_rebuild_add) (struct _cnid_db *, const struct stat *, cnid_t, + const char *, size_t, cnid_t); + int (*cnid_find) (struct _cnid_db *cdb, const char *name, size_t namelen, + void *buffer, size_t buflen); + int (*cnid_wipe) (struct _cnid_db *cdb); +} cnid_db; + +/* + * Consolidation of args passedn from main cnid_open to modules cnid_XXX_open, so + * that it's easier to add aditional args as required. + */ +struct cnid_open_args { + uint32_t cnid_args_flags; + struct vol *cnid_args_vol; +}; + +/* + * CNID module - represents particular CNID implementation + */ +struct _cnid_module { + char *name; + struct list_head db_list; /* CNID modules are also stored on a bidirectional list. */ + struct _cnid_db *(*cnid_open)(struct cnid_open_args *args); + uint32_t flags; /* Flags describing some CNID backend aspects. */ + +}; +typedef struct _cnid_module cnid_module; + +/* Inititalize the CNID backends */ +void cnid_init(); + +/* Registers new CNID backend module */ +void cnid_register(struct _cnid_module *module); + +/* This function opens a CNID database for selected volume. */ +struct _cnid_db *cnid_open(struct vol *vol, char *type, int flags); +cnid_t cnid_add (struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + const char *name, const size_t len, cnid_t hint); +int cnid_delete (struct _cnid_db *cdb, cnid_t id); +cnid_t cnid_get (struct _cnid_db *cdb, const cnid_t did, char *name,const size_t len); +int cnid_getstamp (struct _cnid_db *cdb, void *buffer, const size_t len); +cnid_t cnid_lookup (struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + char *name, const size_t len); +char *cnid_resolve (struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len); +int cnid_update (struct _cnid_db *cdb, const cnid_t id, const struct stat *st, + const cnid_t did, char *name, const size_t len); +cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + char *name, const size_t len, cnid_t hint); +int cnid_find (struct _cnid_db *cdb, const char *name, size_t namelen, + void *buffer, size_t buflen); +int cnid_wipe (struct _cnid_db *cdb); +void cnid_close (struct _cnid_db *db); + +#endif diff --git a/include/atalk/cnid_bdb_private.h b/include/atalk/cnid_bdb_private.h new file mode 100644 index 0000000..f87eddd --- /dev/null +++ b/include/atalk/cnid_bdb_private.h @@ -0,0 +1,71 @@ +/* + * Interface to the cnid_dbd daemon that stores/retrieves CNIDs from a database. + */ + + +#ifndef _ATALK_CNID_DBD_PRIVATE_H +#define _ATALK_CNID_DBD_PRIVATE_H 1 + +#include +#include +#include + +#include + +#define CNID_DBD_OP_OPEN 0x01 +#define CNID_DBD_OP_CLOSE 0x02 +#define CNID_DBD_OP_ADD 0x03 +#define CNID_DBD_OP_GET 0x04 +#define CNID_DBD_OP_RESOLVE 0x05 +#define CNID_DBD_OP_LOOKUP 0x06 +#define CNID_DBD_OP_UPDATE 0x07 +#define CNID_DBD_OP_DELETE 0x08 +#define CNID_DBD_OP_MANGLE_ADD 0x09 +#define CNID_DBD_OP_MANGLE_GET 0x0a +#define CNID_DBD_OP_GETSTAMP 0x0b +#define CNID_DBD_OP_REBUILD_ADD 0x0c +#define CNID_DBD_OP_SEARCH 0x0d +#define CNID_DBD_OP_WIPE 0x0e + +#define CNID_DBD_RES_OK 0x00 +#define CNID_DBD_RES_NOTFOUND 0x01 +#define CNID_DBD_RES_ERR_DB 0x02 +#define CNID_DBD_RES_ERR_MAX 0x03 +#define CNID_DBD_RES_ERR_DUPLCNID 0x04 +#define CNID_DBD_RES_SRCH_CNT 0x05 +#define CNID_DBD_RES_SRCH_DONE 0x06 + +#define DBD_MAX_SRCH_RSLTS 100 +#define DBD_NUM_OPEN_ARGS 3 + +struct cnid_dbd_rqst { + int op; + cnid_t cnid; + dev_t dev; + ino_t ino; + uint32_t type; + cnid_t did; + const char *name; + size_t namelen; +}; + +struct cnid_dbd_rply { + int result; + cnid_t cnid; + cnid_t did; + char *name; + size_t namelen; +}; + +typedef struct CNID_bdb_private { + struct vol *vol; + int fd; /* File descriptor to cnid_dbd */ + char stamp[ADEDLEN_PRIVSYN]; /* db timestamp */ + char *client_stamp; + size_t stamp_size; + int notfirst; /* already open before */ + int changed; /* stamp differ */ +} CNID_bdb_private; + + +#endif /* include/atalk/cnid_dbd.h */ diff --git a/include/atalk/cnid_mysql_private.h b/include/atalk/cnid_mysql_private.h new file mode 100644 index 0000000..79a54e8 --- /dev/null +++ b/include/atalk/cnid_mysql_private.h @@ -0,0 +1,20 @@ +#ifndef _ATALK_CNID_MYSQL_PRIVATE_H +#define _ATALK_CNID_MYSQL_PRIVATE_H 1 + +#include +#include + +#define CNID_MYSQL_FLAG_DEPLETED (1 << 0) /* CNID set overflowed */ + +typedef struct CNID_mysql_private { + struct vol *vol; + uint32_t cnid_mysql_flags; + MYSQL *cnid_mysql_con; + char *cnid_mysql_voluuid_str; + cnid_t cnid_mysql_hint; + MYSQL_STMT *cnid_lookup_stmt; + MYSQL_STMT *cnid_add_stmt; + MYSQL_STMT *cnid_put_stmt; +} CNID_mysql_private; + +#endif diff --git a/include/atalk/cnid_private.h b/include/atalk/cnid_private.h new file mode 100644 index 0000000..c030ff9 --- /dev/null +++ b/include/atalk/cnid_private.h @@ -0,0 +1,74 @@ +/* + * Common defines for cnid + */ + +#ifndef _ATALK_CNID_PRIVATE_H +#define _ATALK_CNID_PRIVATE_H 1 + +#define CNID_OFS 0 +#define CNID_LEN 4 + +#define CNID_DEV_OFS CNID_LEN +#define CNID_DEV_LEN 8 + +#define CNID_INO_OFS (CNID_DEV_OFS + CNID_DEV_LEN) +#define CNID_INO_LEN 8 + +#define CNID_DEVINO_OFS CNID_LEN +#define CNID_DEVINO_LEN (CNID_DEV_LEN + CNID_INO_LEN) + +#define CNID_TYPE_OFS (CNID_DEVINO_OFS + CNID_DEVINO_LEN) +#define CNID_TYPE_LEN 4 + +#define CNID_DID_OFS (CNID_TYPE_OFS + CNID_TYPE_LEN) +#define CNID_DID_LEN CNID_LEN + +#define CNID_NAME_OFS (CNID_DID_OFS + CNID_DID_LEN) +#define CNID_HEADER_LEN (CNID_NAME_OFS) + +#define CNIDFLAG_ROOTINFO_RO (1 << 0) +#define CNIDFLAG_DB_RO (1 << 1) + +/* special key/data pair we use to store current cnid and database stamp in cnid2.db */ + +#define ROOTINFO_KEY "\0\0\0\0" +#define ROOTINFO_KEYLEN 4 + +/* + Rootinfo data, fields as they are used by normal entries for CNIDs (for reference): + 4 bytes: CNID + 8 bytes: dev + 8 bytes: inode + 4 bytes: is a file/directory (type) + 4 bytes: DID + x bytes: name + + Contents in Rootinfo entry: + 4 bytes: 0 + 8 bytes: db stamp: struct stat.st_ctime of database file + 8 bytes: unused + 4 bytes: last used CNID + 4 bytes: version as htonl(uint32_t) + 9 bytes: name "RootInfo" +*/ +#define ROOTINFO_DATA "\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" \ + "RootInfo" +#define ROOTINFO_DATALEN (3*4 + 2*8 + 9) + +/* + * CNID version history: + * 0: up to Netatalk 2.1.x + * 1: starting with 2.2, additional name index, used in cnid_find + */ +#define CNID_VERSION_0 0 +#define CNID_VERSION_1 1 +#define CNID_VERSION_UNINTIALIZED_DB UINT32_MAX + +/* Current CNID version */ +#define CNID_VERSION CNID_VERSION_1 + +#endif diff --git a/include/atalk/compat.h b/include/atalk/compat.h new file mode 100644 index 0000000..08e15d7 --- /dev/null +++ b/include/atalk/compat.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1996 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + * + * NOTE: SunOS 4 and ultrix are pretty much the only reason why there + * are checks for EINTR everywhere. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" + +#include + +#if defined(ultrix) || defined(_IBMR2) || defined(NEED_GETUSERSHELL) +extern char *getusershell (void); +#endif + +/* OpenBSD */ +#if defined(__OpenBSD__) && !defined(ENOTSUP) +#define ENOTSUP EOPNOTSUPP +#endif + +#if !defined(HAVE_PSELECT) || defined(__OpenBSD__) +extern int pselect(int, fd_set * restrict, fd_set * restrict, + fd_set * restrict, const struct timespec * restrict, + const sigset_t * restrict); +#endif + +#ifndef HAVE_FLOCK +extern int flock (int, int); +#endif + +#ifndef HAVE_STRNLEN +extern size_t strnlen(const char *s, size_t n); +#endif + +#ifndef HAVE_STRLCPY +extern size_t strlcpy (char *, const char *, size_t); +#endif + +#ifndef HAVE_STRLCAT +extern size_t strlcat (char *, const char *, size_t); +#endif + +#ifndef HAVE_VASPRINTF +#include +#include +extern int vasprintf(char **ret, const char *fmt, va_list ap); +#endif + +#endif diff --git a/include/atalk/dalloc.h b/include/atalk/dalloc.h new file mode 100644 index 0000000..4e963cd --- /dev/null +++ b/include/atalk/dalloc.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef DALLOC_H +#define DALLOC_H + +#include + +/* dynamic datastore */ +typedef struct { + void **dd_talloc_array; +} DALLOC_CTX; + +/* Use dalloc_add_copy() macro, not this function */ +extern int dalloc_add_talloc_chunk(DALLOC_CTX *dd, void *talloc_chunk, void *obj, size_t size); + +#define dalloc_add_copy(d, obj, type) dalloc_add_talloc_chunk((d), talloc((d), type), (obj), sizeof(type)); +#define dalloc_add(d, obj, type) dalloc_add_talloc_chunk((d), NULL, (obj), 0); +extern void *dalloc_get(const DALLOC_CTX *d, ...); +extern void *dalloc_value_for_key(const DALLOC_CTX *d, ...); +extern int dalloc_size(DALLOC_CTX *d); +extern char *dalloc_strdup(const void *ctx, const char *string); +extern char *dalloc_strndup(const void *ctx, const char *string, size_t n); +#endif /* DALLOC_H */ diff --git a/include/atalk/dictionary.h b/include/atalk/dictionary.h new file mode 100644 index 0000000..1aa22af --- /dev/null +++ b/include/atalk/dictionary.h @@ -0,0 +1,68 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file dictionary.h + @author N. Devillard + @date Sep 2007 + @brief Implements a dictionary for string variables. + + This module implements a simple dictionary object, i.e. a list + of string/string associations. This object is useful to store e.g. + informations retrieved from a configuration file (ini files). +*/ +/*--------------------------------------------------------------------------*/ + +/* + $Author: ndevilla $ + $Date: 2007-11-23 21:37:00 $ +*/ + +#ifndef _DICTIONARY_H_ +#define _DICTIONARY_H_ + +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- + New types + ---------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------*/ +/** + @brief Dictionary object + + This object contains a list of string/string associations. Each + association is identified by a unique string key. Looking up values + in the dictionary is speeded up by the use of a (hopefully collision-free) + hash function. + */ +/*-------------------------------------------------------------------------*/ +typedef struct _dictionary_ { + int n ; /** Number of entries in dictionary */ + int size ; /** Storage size */ + char ** val ; /** List of string values */ + char ** key ; /** List of string keys */ + unsigned * hash ; /** List of hash values for keys */ +} dictionary ; + + +/*--------------------------------------------------------------------------- + Function prototypes + ---------------------------------------------------------------------------*/ + +unsigned atalkdict_hash (char * key); +dictionary *atalkdict_new (int size); +void atalkdict_del (dictionary * vd); +const char *atalkdict_get (const dictionary * d, const char *section, const char * key, const char * def); +int atalkdict_set (dictionary * vd, char *section, char * key, char * val); +void atalkdict_unset (dictionary * d, char *section, char * key); +void atalkdict_dump (dictionary * d, FILE * out); + +#endif diff --git a/include/atalk/directory.h b/include/atalk/directory.h new file mode 100644 index 0000000..d3764e5 --- /dev/null +++ b/include/atalk/directory.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifndef ATALK_DIRECTORY_H +#define ATALK_DIRECTORY_H 1 + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* setgid directories */ +#ifndef DIRBITS +# if (defined AFS) || (defined FREEBSD) +# define DIRBITS 0 +# else /* AFS */ +# define DIRBITS S_ISGID +# endif /* AFS */ +#endif /* DIRBITS */ + +/* reserved directory id's */ +#define DIRDID_ROOT_PARENT htonl(1) /* parent directory of root */ +#define DIRDID_ROOT htonl(2) /* root directory */ + +/* struct dir.d_flags */ +#define DIRF_FSMASK (3<<0) +#define DIRF_NOFS (0<<0) +#define DIRF_AFS (1<<0) +#define DIRF_UFS (1<<1) +#define DIRF_ISFILE (1<<3) /* it's cached file, not a directory */ +#define DIRF_OFFCNT (1<<4) /* offsprings count is valid */ +#define DIRF_CNID (1<<5) /* renumerate id */ + +struct dir { + bstring d_fullpath; /* complete unix path to dir (or file) */ + bstring d_m_name; /* mac name */ + bstring d_u_name; /* unix name */ + /* be careful here! if d_m_name == d_u_name, d_u_name */ + /* will just point to the same storage as d_m_name !! */ + ucs2_t *d_m_name_ucs2; /* mac name as UCS2 */ + qnode_t *qidx_node; /* pointer to position in queue index */ + time_t d_ctime; /* inode ctime, used and modified by reenumeration */ + + int d_flags; /* directory flags */ + cnid_t d_pdid; /* CNID of parent directory */ + cnid_t d_did; /* CNID of directory */ + uint32_t d_offcnt; /* offspring count */ + uint16_t d_vid; /* only needed in the dircache, because + we put all directories in one cache. */ + uint32_t d_rights_cache; /* cached rights combinded from mode and possible ACL */ + + /* Stuff used in the dircache */ + time_t dcache_ctime; /* inode ctime, used and modified by dircache */ + ino_t dcache_ino; /* inode number, used to detect changes in the dircache */ +}; + +struct path { + int m_type; /* mac name type (long name, unicode */ + char *m_name; /* mac name */ + char *u_name; /* unix name */ + cnid_t id; /* file id (only for getmetadata) */ + struct dir *d_dir; /* */ + int st_valid; /* does st_errno and st set */ + int st_errno; + struct stat st; +}; + +static inline int path_isadir(struct path *o_path) +{ + return o_path->d_dir != NULL; +#if 0 + return o_path->m_name == '\0' || /* we are in a it */ + !o_path->st_valid || /* in cache but we can't chdir in it */ + (!o_path->st_errno && S_ISDIR(o_path->st.st_mode)); /* not in cache an can't chdir */ +#endif +} + +#endif /* ATALK_DIRECTORY_H */ diff --git a/include/atalk/dsi.h b/include/atalk/dsi.h new file mode 100644 index 0000000..c816d96 --- /dev/null +++ b/include/atalk/dsi.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. + */ + +#ifndef _ATALK_DSI_H +#define _ATALK_DSI_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* What a DSI packet looks like: + 0 32 + |-------------------------------| + |flags |command| requestID | + |-------------------------------| + |error code/enclosed data offset| + |-------------------------------| + |total data length | + |-------------------------------| + |reserved field | + |-------------------------------| + + CONVENTION: anything with a dsi_ prefix is kept in network byte order. +*/ + +/* these need to be kept in sync w/ AFPTRANS_* in . + * convention: AFPTRANS_* = (1 << DSI_*) */ +typedef enum { + DSI_MIN = 1, + DSI_TCPIP = 1, + DSI_MAX = 1 +} dsi_proto; + +#define DSI_BLOCKSIZ 16 +struct dsi_block { + uint8_t dsi_flags; /* packet type: request or reply */ + uint8_t dsi_command; /* command */ + uint16_t dsi_requestID; /* request ID */ + union { + uint32_t dsi_code; /* error code */ + uint32_t dsi_doff; /* data offset */ + } dsi_data; + uint32_t dsi_len; /* total data length */ + uint32_t dsi_reserved; /* reserved field */ +}; + +#define DSI_DATASIZ 65536 + +/* child and parent processes might interpret a couple of these + * differently. */ +typedef struct DSI { + struct DSI *next; /* multiple listening addresses */ + AFPObj *AFPobj; + int statuslen; + char status[1400]; + char *signature; + struct dsi_block header; + struct sockaddr_storage server, client; + struct itimerval timer; + int tickle; /* tickle count */ + int in_write; /* in the middle of writing multiple packets, + signal handlers can't write to the socket */ + int msg_request; /* pending message to the client */ + int down_request; /* pending SIGUSR1 down in 5 mn */ + + uint32_t attn_quantum, datasize, server_quantum; + uint16_t serverID, clientID; + uint8_t *commands; /* DSI recieve buffer */ + uint8_t data[DSI_DATASIZ]; /* DSI reply buffer */ + size_t datalen, cmdlen; + off_t read_count, write_count; + uint32_t flags; /* DSI flags like DSI_SLEEPING, DSI_DISCONNECTED */ + int socket; /* AFP session socket */ + int serversock; /* listening socket */ + + /* DSI readahead buffer used for buffered reads in dsi_peek */ + size_t dsireadbuf; /* size of the DSI readahead buffer used in dsi_peek() */ + char *buffer; /* buffer start */ + char *start; /* current buffer head */ + char *eof; /* end of currently used buffer */ + char *end; + +#ifdef USE_ZEROCONF + char *bonjourname; /* server name as UTF8 maxlen MAXINSTANCENAMELEN */ + int zeroconf_registered; +#endif + + /* protocol specific open/close, send/receive + * send/receive fill in the header and use dsi->commands. + * write/read just write/read data */ + pid_t (*proto_open)(struct DSI *); + void (*proto_close)(struct DSI *); +} DSI; + +/* DSI flags */ +#define DSIFL_REQUEST 0x00 +#define DSIFL_REPLY 0x01 +#define DSIFL_MAX 0x01 + +/* DSI session options */ +#define DSIOPT_SERVQUANT 0x00 /* server request quantum */ +#define DSIOPT_ATTNQUANT 0x01 /* attention quantum */ +#define DSIOPT_REPLCSIZE 0x02 /* AFP replaycache size supported by the server (that's us) */ + +/* DSI Commands */ +#define DSIFUNC_CLOSE 1 /* DSICloseSession */ +#define DSIFUNC_CMD 2 /* DSICommand */ +#define DSIFUNC_STAT 3 /* DSIGetStatus */ +#define DSIFUNC_OPEN 4 /* DSIOpenSession */ +#define DSIFUNC_TICKLE 5 /* DSITickle */ +#define DSIFUNC_WRITE 6 /* DSIWrite */ +#define DSIFUNC_ATTN 8 /* DSIAttention */ +#define DSIFUNC_MAX 8 /* largest command */ + +/* DSI Error codes: most of these aren't used. */ +#define DSIERR_OK 0x0000 +#define DSIERR_BADVERS 0xfbd6 +#define DSIERR_BUFSMALL 0xfbd5 +#define DSIERR_NOSESS 0xfbd4 +#define DSIERR_NOSERV 0xfbd3 +#define DSIERR_PARM 0xfbd2 +#define DSIERR_SERVBUSY 0xfbd1 +#define DSIERR_SESSCLOS 0xfbd0 +#define DSIERR_SIZERR 0xfbcf +#define DSIERR_TOOMANY 0xfbce +#define DSIERR_NOACK 0xfbcd + +/* server and client quanta */ +#define DSI_DEFQUANT 2 /* default attention quantum size */ +#define DSI_SERVQUANT_MAX 0xffffffff /* server quantum */ +#define DSI_SERVQUANT_MIN 32000 /* minimum server quantum */ +#define DSI_SERVQUANT_DEF 0x100000L /* default server quantum (1 MB) */ + +/* default port number */ +#define DSI_AFPOVERTCP_PORT 548 + +/* DSI session State flags */ +#define DSI_DATA (1 << 0) /* we have received a DSI command */ +#define DSI_RUNNING (1 << 1) /* we have received a AFP command */ +#define DSI_SLEEPING (1 << 2) /* we're sleeping after FPZzz */ +#define DSI_EXTSLEEP (1 << 3) /* we're sleeping after FPZzz */ +#define DSI_DISCONNECTED (1 << 4) /* we're in diconnected state after a socket error */ +#define DSI_DIE (1 << 5) /* SIGUSR1, going down in 5 minutes */ +#define DSI_NOREPLY (1 << 6) /* in dsi_write we generate our own replies */ +#define DSI_RECONSOCKET (1 << 7) /* we have a new socket from primary reconnect */ +#define DSI_RECONINPROG (1 << 8) /* used in the new session in reconnect */ +#define DSI_AFP_LOGGED_OUT (1 << 9) /* client called afp_logout, quit on next EOF from socket */ + +/* basic initialization: dsi_init.c */ +extern DSI *dsi_init(AFPObj *obj, const char *hostname, const char *address, const char *port); +extern void dsi_setstatus (DSI *, char *, const size_t); +extern int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address, const char *port); +extern void dsi_free(DSI *dsi); + +/* in dsi_getsess.c */ +extern int dsi_getsession (DSI *, server_child_t *, const int, afp_child_t **); +extern void dsi_kill (int); + + +/* DSI Commands: individual files */ +extern void dsi_opensession (DSI *); +extern int dsi_attention (DSI *, AFPUserBytes); +extern int dsi_cmdreply (DSI *, const int); +extern int dsi_tickle (DSI *); +extern void dsi_getstatus (DSI *); +extern void dsi_close (DSI *); + +#define DSI_NOWAIT 1 +#define DSI_MSG_MORE 2 + +/* low-level stream commands -- in dsi_stream.c */ +extern ssize_t dsi_stream_write (DSI *, void *, const size_t, const int mode); +extern size_t dsi_stream_read (DSI *, void *, const size_t); +extern int dsi_stream_send (DSI *, void *, size_t); +extern int dsi_stream_receive (DSI *); +extern int dsi_disconnect(DSI *dsi); + +#ifdef WITH_SENDFILE +extern ssize_t dsi_stream_read_file(DSI *, int, off_t off, const size_t len, const int err); +#endif + +/* client writes -- dsi_write.c */ +extern size_t dsi_writeinit (DSI *, void *, const size_t); +extern size_t dsi_write (DSI *, void *, const size_t); +extern void dsi_writeflush (DSI *); +#define dsi_wrtreply(a,b) dsi_cmdreply(a,b) + +/* client reads -- dsi_read.c */ +extern ssize_t dsi_readinit (DSI *, void *, const size_t, const size_t, + const int); +extern ssize_t dsi_read (DSI *, void *, const size_t); +extern void dsi_readdone (DSI *); + +/* some useful macros */ +#define dsi_serverID(x) ((x)->serverID++) +#define dsi_send(x) do { \ + (x)->header.dsi_len = htonl((x)->cmdlen); \ + dsi_stream_send((x), (x)->commands, (x)->cmdlen); \ + } while (0) + +#endif /* atalk/dsi.h */ diff --git a/include/atalk/ea.h b/include/atalk/ea.h new file mode 100644 index 0000000..7cd4234 --- /dev/null +++ b/include/atalk/ea.h @@ -0,0 +1,211 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifndef ATALK_EA_H +#define ATALK_EA_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if HAVE_ATTR_XATTR_H +#include +#elif HAVE_SYS_XATTR_H +#include +#endif + +#ifdef HAVE_SYS_EA_H +#include +#endif + +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif + +/* FIXME: are the ACL includes really neccessary here ? */ +#ifdef HAVE_SOLARIS_ACLS +#include +#endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif + +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif + +#include + +/* + * This seems to be the current limit fo HFS+, we arbitrarily force that + * which also safes us from buffer overflows + */ +#define MAX_EA_SIZE 3802 + +/* + * At time of writing the 10.5.6 client adds 8 bytes to the + * length of the EA that we send him +*/ +#define MAX_REPLY_EXTRA_BYTES 8 + +/* + * Library user must provide a static buffer of size ATTRNAMEBUFSIZ. + * It's used when listing EAs as intermediate buffer. For afpd it's + * defined in extattrs.c. + */ +#define ATTRNAMEBUFSIZ 4096 + +enum { + kXAttrNoFollow = 0x1, + kXAttrCreate = 0x2, + kXAttrReplace = 0x4 +}; + +#if !defined(HAVE_SETXATTR) +#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ +#endif + +/* Names for our Extended Attributes adouble data */ +#define AD_EA_META "org.netatalk.Metadata" +#define AD_EA_RESO "org.netatalk.ResourceFork" +#define NOT_NETATALK_EA(a) (strcmp((a), AD_EA_META) != 0) && (strcmp((a), AD_EA_RESO) != 0) + +/**************************************************************************************** + * Wrappers for native EA functions taken from Samba + ****************************************************************************************/ +ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size); +ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size); +ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size); +ssize_t sys_listxattr (const char *path, char *list, size_t size); +ssize_t sys_llistxattr (const char *path, char *list, size_t size); +/* ssize_t sys_flistxattr (int filedes, char *list, size_t size); */ +ssize_t sys_flistxattr (int filedes, const char *path, char *list, size_t size); +int sys_removexattr (const char *path, const char *name); +int sys_lremovexattr (const char *path, const char *name); +/* int sys_fremovexattr (int filedes, const char *name); */ +int sys_fremovexattr (int filedes, const char *path, const char *name); +int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags); +int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags); +int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags); +int sys_copyxattr (const char *src, const char *dst); +int sys_getxattrfd(int fd, const char *uname, int oflag, ...); + +/**************************************************************************************** + * Stuff for our implementation of storing EAs in files in .AppleDouble dirs + ****************************************************************************************/ + +#define EA_INITED 0xea494e54 /* ea"INT", for interfacing ea_open w. ea_close */ +#define EA_MAGIC 0x61644541 /* "adEA" */ +#define EA_VERSION1 0x01 +#define EA_VERSION EA_VERSION1 + +typedef enum { + /* ea_open flags */ + EA_CREATE = (1<<1), /* create if not existing on ea_open */ + EA_RDONLY = (1<<2), /* open read only */ + EA_RDWR = (1<<3), /* open read/write */ + /* ea_open internal flags */ + EA_DIR = (1<<4) /* ea header file is for a dir, ea_open adds it as appropiate */ +} eaflags_t; + +#define EA_MAGIC_OFF 0 +#define EA_MAGIC_LEN 4 +#define EA_VERSION_OFF (EA_MAGIC_OFF + EA_MAGIC_LEN) +#define EA_VERSION_LEN 2 +#define EA_COUNT_OFF (EA_VERSION_OFF + EA_VERSION_LEN) +#define EA_COUNT_LEN 2 +#define EA_HEADER_SIZE (EA_MAGIC_LEN + EA_VERSION_LEN + EA_COUNT_LEN) + +/* + * structs describing the layout of the Extended Attributes bookkeeping file. + * This isn't really an AppleDouble structure, it's just a binary blob that + * lives in our .AppleDouble directory too. + */ + +struct ea_entry { + size_t ea_namelen; /* len of ea_name without terminating 0 ie. strlen(ea_name)*/ + size_t ea_size; /* size of EA*/ + char *ea_name; /* name of the EA */ +}; + +/* We read the on-disk data into *ea_data and parse it into this*/ +struct ea { + uint32_t ea_inited; /* needed for interfacing ea_open w. ea_close */ + const struct vol *vol; /* vol handle, ea_close needs it */ + int dirfd; /* for *at (cf openat) semantics, -1 means ignore */ + char *filename; /* name of file, needed by ea_close too */ + unsigned int ea_count; /* number of EAs in ea_entries array */ + struct ea_entry (*ea_entries)[]; /* malloced and realloced as needed by ea_count*/ + int ea_fd; /* open fd for ea_data */ + eaflags_t ea_flags; /* flags */ + size_t ea_size; /* size of header file = size of ea_data buffer */ + char *ea_data; /* pointer to buffer into that we actually * + * read the disc file into */ +}; + +/* On-disk format, just for reference ! */ +#if 0 +struct ea_entry_ondisk { + uint32_t ea_size; + char ea_name[]; /* zero terminated string */ +}; + +struct ea_ondisk { + u_int32_t ea_magic; + u_int16_t ea_version; + u_int16_t ea_count; + struct ea_entry_ondisk ea_entries[ea_count]; +}; +#endif /* 0 */ + +/* VFS inderected funcs ... : */ + +/* Default adouble EAs */ +extern int get_easize(VFS_FUNC_ARGS_EA_GETSIZE); +extern int get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT); +extern int list_eas(VFS_FUNC_ARGS_EA_LIST); +extern int set_ea(VFS_FUNC_ARGS_EA_SET); +extern int remove_ea(VFS_FUNC_ARGS_EA_REMOVE); +/* ... EA VFS funcs that deal with file/dir cp/mv/rm */ +extern int ea_deletefile(VFS_FUNC_ARGS_DELETEFILE); +extern int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE); +extern int ea_copyfile(VFS_FUNC_ARGS_COPYFILE); +extern int ea_chown(VFS_FUNC_ARGS_CHOWN); +extern int ea_chmod_file(VFS_FUNC_ARGS_SETFILEMODE); +extern int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE); + +/* native EAs */ +extern int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE); +extern int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT); +extern int sys_list_eas(VFS_FUNC_ARGS_EA_LIST); +extern int sys_set_ea(VFS_FUNC_ARGS_EA_SET); +extern int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE); +/* native EA VFSfile/dir cp/mv/rm */ +extern int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE); + +/* dbd needs access to these */ +extern int ea_open(const struct vol * restrict vol, + const char * restrict uname, + eaflags_t eaflags, + struct ea * restrict ea); +extern int ea_openat(const struct vol * restrict vol, + int dirfd, + const char * restrict uname, + eaflags_t eaflags, + struct ea * restrict ea); +extern int ea_close(struct ea * restrict ea); +extern char *ea_path(const struct ea * restrict ea, const char * restrict eaname, int macname); + +#endif /* ATALK_EA_H */ diff --git a/include/atalk/errchk.h b/include/atalk/errchk.h new file mode 100644 index 0000000..47576be --- /dev/null +++ b/include/atalk/errchk.h @@ -0,0 +1,170 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. + */ + +#ifndef ERRCHECK_H +#define ERRCHECK_H + +#define EC_INIT int ret = 0 +#define EC_STATUS(a) ret = (a) +#define EC_EXIT_STATUS(a) do { ret = (a); goto cleanup; } while (0) +#define EC_FAIL do { ret = -1; goto cleanup; } while (0) +#define EC_FAIL_LOG(...) \ + do { \ + LOG(log_error, logtype_default, __VA_ARGS__); \ + ret = -1; \ + goto cleanup; \ + } while (0) +#define EC_CLEANUP cleanup +#define EC_EXIT return ret + +/* + * Check out doc/DEVELOPER for more infos. + * + * We have these macros: + * EC_ZERO, EC_ZERO_LOG, EC_ZERO_LOGSTR, EC_ZERO_LOG_ERR, EC_ZERO_CUSTOM + * EC_NEG1, EC_NEG1_LOG, EC_NEG1_LOGSTR, EC_NEG1_LOG_ERR, EC_NEG1_CUSTOM + * EC_NULL, EC_NULL_LOG, EC_NULL_LOGSTR, EC_NULL_LOG_ERR, EC_NULL_CUSTOM + * + * A boileplate function template is: + + int func(void) + { + EC_INIT; + + ...your code here... + + EC_STATUS(0); + + EC_CLEANUP: + EC_EXIT; + } + */ + +/* check for return val 0 which is ok, every other is an error, prints errno */ +#define EC_ZERO_LOG(a) \ + do { \ + if ((a) != 0) { \ + LOG(log_error, logtype_default, "%s failed: %s", #a, strerror(errno)); \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_ZERO_LOGSTR(a, b, ...) \ + do { \ + if ((a) != 0) { \ + LOG(log_error, logtype_default, b, __VA_ARGS__); \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_ZERO_LOG_ERR(a, b) \ + do { \ + if ((a) != 0) { \ + LOG(log_error, logtype_default, "%s failed: %s", #a, strerror(errno)); \ + ret = (b); \ + goto cleanup; \ + } \ + } while (0) + +#define EC_ZERO(a) \ + do { \ + if ((a) != 0) { \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_ZERO_ERR(a,b ) \ + do { \ + if ((a) != 0) { \ + ret = b; \ + goto cleanup; \ + } \ + } while (0) + +/* check for return val 0 which is ok, every other is an error, prints errno */ +#define EC_NEG1_LOG(a) \ + do { \ + if ((a) == -1) { \ + LOG(log_error, logtype_default, "%s failed: %s", #a, strerror(errno)); \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_NEG1_LOGSTR(a, b, ...) \ + do { \ + if ((a) == -1) { \ + LOG(log_error, logtype_default, b, __VA_ARGS__); \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_NEG1_LOG_ERR(a, b) \ + do { \ + if ((a) == -1) { \ + LOG(log_error, logtype_default, "%s failed: %s", #a, strerror(errno)); \ + ret = b; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_NEG1(a) \ + do { \ + if ((a) == -1) { \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +/* check for return val != NULL, prints errno */ +#define EC_NULL_LOG(a) \ + do { \ + if ((a) == NULL) { \ + LOG(log_error, logtype_default, "%s failed: %s", #a, strerror(errno)); \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_NULL_LOGSTR(a, b, ...) \ + do { \ + if ((a) == NULL) { \ + LOG(log_error, logtype_default, b , __VA_ARGS__); \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_NULL_LOG_ERR(a, b) \ + do { \ + if ((a) == NULL) { \ + LOG(log_error, logtype_default, "%s failed: %s", #a, strerror(errno)); \ + ret = b; \ + goto cleanup; \ + } \ + } while (0) + +#define EC_NULL(a) \ + do { \ + if ((a) == NULL) { \ + ret = -1; \ + goto cleanup; \ + } \ + } while (0) + +#endif /* ERRCHECK_H */ diff --git a/include/atalk/fce_api.h b/include/atalk/fce_api.h new file mode 100755 index 0000000..c804d90 --- /dev/null +++ b/include/atalk/fce_api.h @@ -0,0 +1,134 @@ +/* + * File: fce_api.h + * Author: mw + * + * Created on 1. Oktober 2010, 21:35 + * + * API calls for file change event api + */ + +#ifndef _FCE_API_H +#define _FCE_API_H + +#include + +#define FCE_PACKET_VERSION 2 + +/* fce_packet.mode */ +#define FCE_FILE_MODIFY 1 +#define FCE_FILE_DELETE 2 +#define FCE_DIR_DELETE 3 +#define FCE_FILE_CREATE 4 +#define FCE_DIR_CREATE 5 +#define FCE_FILE_MOVE 6 +#define FCE_DIR_MOVE 7 +#define FCE_LOGIN 8 +#define FCE_LOGOUT 9 +#define FCE_CONN_START 42 +#define FCE_CONN_BROKEN 99 + +#define FCE_FIRST_EVENT FCE_FILE_MODIFY /* keep in sync with last file event above */ +#define FCE_LAST_EVENT FCE_LOGOUT /* keep in sync with last file event above */ + +/* fce_packet.fce_magic */ +#define FCE_PACKET_MAGIC "at_fcapi" + +/* flags for "fce_ev_info" of additional info to send in events */ +#define FCE_EV_INFO_PID (1 << 0) +#define FCE_EV_INFO_USER (1 << 1) +#define FCE_EV_INFO_SRCPATH (1 << 2) + +/* + * Network payload of an FCE packet, version 1 + * + * 1 2 3 4 5 6 7 8 + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * | FCE magic | + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * | version | + * +---------+ + * | event | + * +---------+-----------------------------+ + * | event ID | + * +-------------------+-------------------+ . . . . + * | pathlen | path + * +-------------------+------ . . . . . . . . . . . + * + * + * Network payload of an FCE packet, version 2 + * + * 1 2 3 4 5 6 7 8 + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * | FCE magic | + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * | version | + * +---------+ + * | options | + * +---------+ + * | event | + * +---------+ + * | padding | + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * | reserved | + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * | event ID | + * +---------+---------+---------+---------+ + * ... optional: + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * | pid | + * +---------+---------+---------+---------+---------+---------+----------+----------+ + * ... + * ... optional: + * +-------------------+---------- . . . . + * | username length | username + * +-------------------+---------- . . . . + * ... + * +-------------------+------ . . . . . . + * | pathlen | path + * +-------------------+------ . . . . . . + * ... optional: + * +-------------------+------------- . . . + * | pathlen | source path + * +-------------------+------------- . . . + * + * version = 2 + * options = bitfield: + * 0: pid present + * 1: username present + * 2: source path present + * pid = optional pid + * username = optional username + * source path = optional source path + */ + +struct fce_packet { + char fcep_magic[8]; + unsigned char fcep_version; + unsigned char fcep_options; + unsigned char fcep_event; + uint32_t fcep_event_id; + uint64_t fcep_pid; + uint16_t fcep_userlen; + char fcep_user[MAXPATHLEN]; + uint16_t fcep_pathlen1; + char fcep_path1[MAXPATHLEN]; + uint16_t fcep_pathlen2; + char fcep_path2[MAXPATHLEN]; +}; + +typedef uint32_t fce_ev_t; + +struct path; +struct ofork; + +void fce_pending_events(const AFPObj *obj); +int fce_register(const AFPObj *obj, fce_ev_t event, const char *path, const char *oldpath); +int fce_add_udp_socket(const char *target ); // IP or IP:Port +int fce_set_coalesce(const char *coalesce_opt ); // all|delete|create +int fce_set_events(const char *events); /* fmod,fdel,ddel,fcre,dcre */ + +#define FCE_DEFAULT_PORT 12250 +#define FCE_DEFAULT_PORT_STRING "12250" + +#endif /* _FCE_API_H */ + diff --git a/include/atalk/ftw.h b/include/atalk/ftw.h new file mode 100644 index 0000000..157efc5 --- /dev/null +++ b/include/atalk/ftw.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1992,1996-1999,2003,2004 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. */ + +/* + * X/Open Portability Guide 4.2: ftw.h + */ + +#ifndef _ATALK_FTW_H +#define _ATALK_FTW_H 1 + +#include +#include + +/* Values for the FLAG argument to the user function passed to `ftw' + and 'nftw'. */ +enum +{ + FTW_F, /* Regular file. */ +#define FTW_F FTW_F + FTW_D, /* Directory. */ +#define FTW_D FTW_D + FTW_DNR, /* Unreadable directory. */ +#define FTW_DNR FTW_DNR + FTW_NS, /* Unstatable file. */ +#define FTW_NS FTW_NS + FTW_SL, /* Symbolic link. */ +# define FTW_SL FTW_SL + +/* These flags are only passed from the `nftw' function. */ + FTW_DP, /* Directory, all subdirs have been visited. */ +# define FTW_DP FTW_DP + FTW_SLN /* Symbolic link naming non-existing file. */ +# define FTW_SLN FTW_SLN +}; + + +/* Flags for fourth argument of `nftw'. */ +enum +{ + FTW_PHYS = 1, /* Perform physical walk, ignore symlinks. */ +# define FTW_PHYS FTW_PHYS + FTW_MOUNT = 2, /* Report only files on same file system as the + argument. */ +# define FTW_MOUNT FTW_MOUNT + FTW_CHDIR = 4, /* Change to current directory while processing it. */ +# define FTW_CHDIR FTW_CHDIR + FTW_DEPTH = 8, /* Report files in directory before directory itself.*/ +# define FTW_DEPTH FTW_DEPTH + FTW_ACTIONRETVAL = 16 /* Assume callback to return FTW_* values instead of + zero to continue and non-zero to terminate. */ +# define FTW_ACTIONRETVAL FTW_ACTIONRETVAL +}; + +/* Return values from callback functions. */ +enum +{ + FTW_CONTINUE = 0, /* Continue with next sibling or for FTW_D with the + first child. */ +# define FTW_CONTINUE FTW_CONTINUE + FTW_STOP = 1, /* Return from `ftw' or `nftw' with FTW_STOP as return + value. */ +# define FTW_STOP FTW_STOP + FTW_SKIP_SUBTREE = 2, /* Only meaningful for FTW_D: Don't walk through the + subtree, instead just continue with its next + sibling. */ +# define FTW_SKIP_SUBTREE FTW_SKIP_SUBTREE + FTW_SKIP_SIBLINGS = 3,/* Continue with FTW_DP callback for current directory + (if FTW_DEPTH) and then its siblings. */ +# define FTW_SKIP_SIBLINGS FTW_SKIP_SIBLINGS +}; + +/* Structure used for fourth argument to callback function for `nftw'. */ +struct FTW + { + int base; + int level; + }; + +/* Convenient types for callback functions. */ +typedef int (*nftw_func_t) (const char *filename, + const struct stat *status, + int flag, + struct FTW *info); +#define NFTW_FUNC_T nftw_func_t + +typedef void (*dir_notification_func_t) (void); + +extern int nftw(const char *dir, + nftw_func_t func, + dir_notification_func_t up, + int descriptors, + int flag); + +#endif /* ATALK_FTW_H */ diff --git a/include/atalk/globals.h b/include/atalk/globals.h new file mode 100644 index 0000000..fb2848f --- /dev/null +++ b/include/atalk/globals.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifndef AFPD_GLOBALS_H +#define AFPD_GLOBALS_H 1 + +#include +#include +#include + +#ifdef HAVE_NETDB_H +#include /* this isn't header-protected under ultrix */ +#endif /* HAVE_NETDB_H */ + +#include +#include +#include +#include +#include +#ifdef WITH_DTRACE +#include +#else +/* List of empty dtrace macros */ +#define AFP_AFPFUNC_START(a,b) +#define AFP_AFPFUNC_DONE(a, b) +#define AFP_CNID_START(a) +#define AFP_CNID_DONE() +#define AFP_READ_START(a) +#define AFP_READ_DONE() +#define AFP_WRITE_START(a) +#define AFP_WRITE_DONE() +#endif + +/* #define DOSFILELEN 12 */ /* Type1, DOS-compat*/ +#define MACFILELEN 31 /* Type2, HFS-compat */ +#define UTF8FILELEN_EARLY 255 /* Type3, early Mac OS X 10.0-10.4.? */ +/* #define UTF8FILELEN_NAME_MAX 765 */ /* Type3, 10.4.?- , getconf NAME_MAX */ +/* #define UTF8FILELEN_SPEC 0xFFFF */ /* Type3, spec on document */ +/* #define HFSPLUSFILELEN 510 */ /* HFS+ spec, 510byte = 255codepoint */ + +#define MAXUSERLEN 256 + +#define DEFAULT_MAX_DIRCACHE_SIZE 8192 + +#define OPTION_DEBUG (1 << 0) +#define OPTION_CLOSEVOL (1 << 1) +#define OPTION_SERVERNOTIF (1 << 2) +#define OPTION_NOSENDFILE (1 << 3) +#define OPTION_VETOMSG (1 << 4) /* whether to send an AFP message for veto file access */ +#define OPTION_AFP_READ_LOCK (1 << 5) /* whether to do AFP spec conforming read locks (default: no) */ +#define OPTION_ANNOUNCESSH (1 << 6) +#define OPTION_UUID (1 << 7) +#define OPTION_ACL2MACCESS (1 << 8) +#define OPTION_NOZEROCONF (1 << 9) +#define OPTION_ACL2MODE (1 << 10) +#define OPTION_SHARE_RESERV (1 << 11) /* whether to use Solaris fcntl F_SHARE locks */ +#define OPTION_DBUS_AFPSTATS (1 << 12) /* whether to run dbus thread for afpstats */ +#define OPTION_SPOTLIGHT (1 << 13) /* whether to initialize Spotlight support */ +#define OPTION_SPOTLIGHT_VOL (1 << 14) /* whether spotlight shall be enabled by default for volumes */ +#define OPTION_RECVFILE (1 << 15) +#define OPTION_SPOTLIGHT_EXPR (1 << 16) /* whether to allow Spotlight logic expressions */ + +#define PASSWD_NONE 0 +#define PASSWD_SET (1 << 0) +#define PASSWD_NOSAVE (1 << 1) +#define PASSWD_ALL (PASSWD_SET | PASSWD_NOSAVE) + +#define IS_AFP_SESSION(obj) ((obj)->dsi && (obj)->dsi->serversock == -1) + +/********************************************************************************************** + * Ini config sections + **********************************************************************************************/ + +#define INISEC_GLOBAL "Global" +#define INISEC_HOMES "Homes" + +struct DSI; +#define AFPOBJ_TMPSIZ (MAXPATHLEN) + +struct afp_volume_name { + time_t mtime; + int loaded; +}; + +struct afp_options { + int connections; /* Maximum number of possible AFP connections */ + int tickleval; + int timeout; + int flags; + int dircachesize; + int sleep; /* Maximum time allowed to sleep (in tickles) */ + int disconnected; /* Maximum time in disconnected state (in tickles) */ + int fce_fmodwait; /* number of seconds FCE file mod events are put on hold */ + unsigned int tcp_sndbuf, tcp_rcvbuf; + unsigned char passwdbits, passwdminlen; + uint32_t server_quantum; + int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */ + char *hostname; + char *listen, *interfaces, *port; + char *Cnid_srv, *Cnid_port; + char *configfile; + char *uampath, *fqdn; + char *sigconffile; + char *uuidconf; + char *guest, *loginmesg, *keyfile, *passwdfile, *extmapfile; + char *uamlist; + char *signatureopt; + unsigned char signature[16]; + char *k5service, *k5realm, *k5keytab; + size_t k5principal_buflen; + char *k5principal; + char *unixcodepage, *maccodepage, *volcodepage; + charset_t maccharset, unixcharset; + mode_t umask; + mode_t save_mask; + gid_t admingid; + int volnamelen; + /* default value for winbind authentication */ + char *ntdomain, *ntseparator, *addomain; + char *logconfig; + char *logfile; + char *mimicmodel; + char *adminauthuser; + char *ignored_attr; + int splice_size; + char *cnid_mysql_host; + char *cnid_mysql_user; + char *cnid_mysql_pw; + char *cnid_mysql_db; + struct afp_volume_name volfile; + struct afp_volume_name includefile; + uint64_t sparql_limit; +}; + +typedef struct AFPObj { + const char *cmdlineconfigfile; + int cmdlineflags; + const void *signature; + struct DSI *dsi; + struct afp_options options; + dictionary *iniconfig; + char username[MAXUSERLEN]; + /* to prevent confusion, only use these in afp_* calls */ + char oldtmp[AFPOBJ_TMPSIZ + 1], newtmp[AFPOBJ_TMPSIZ + 1]; + void *uam_cookie; /* cookie for uams */ + struct session_info sinfo; + uid_t uid; /* client running user id */ + int ipc_fd; /* anonymous PF_UNIX socket for IPC with afpd parent */ + gid_t *groups; + int ngroups; + int afp_version; + int cnx_cnt, cnx_max; + /* Functions */ + void (*logout)(void); + void (*exit)(int); + int (*reply)(void *, int); + int (*attention)(void *, AFPUserBytes); + int fce_version; + char *fce_ign_names; + char *fce_notify_script; + struct sl_ctx *sl_ctx; +} AFPObj; + +/* typedef for AFP functions handlers */ +typedef int (*AFPCmd)(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); + +/* Global variables */ +extern AFPObj *AFPobj; +extern int afp_version; +extern int afp_errno; +extern unsigned char nologin; +extern struct dir *curdir; +extern char getwdbuf[]; +extern struct afp_options default_options; +extern const char *Cnid_srv; +extern const char *Cnid_port; + +extern int get_afp_errno (const int param); +extern void afp_options_init (struct afp_options *); +extern void afp_options_parse_cmdline(AFPObj *obj, int ac, char **av); +extern int setmessage (const char *); +extern void readmessage (AFPObj *); + +/* afp_util.c */ +extern const char *AfpNum2name (int ); +extern const char *AfpErr2name(int err); + +/* directory.c */ +extern struct dir rootParent; + +extern void afp_over_dsi (AFPObj *); +extern void afp_over_dsi_sighandlers(AFPObj *obj); +#endif /* globals.h */ diff --git a/include/atalk/hash.h b/include/atalk/hash.h new file mode 100644 index 0000000..0a75e4f --- /dev/null +++ b/include/atalk/hash.h @@ -0,0 +1,179 @@ +/* + * Hash Table Data Type + * Copyright (C) 1997 Kaz Kylheku + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Name: $ + */ + +#ifndef ATALK_HASH_H +#define ATALK_HASH_H + +#include +#include + +typedef unsigned long hashcount_t; +#define HASHCOUNT_T_MAX ULONG_MAX + +typedef uint32_t hash_val_t; +#define HASH_VAL_T_MAX UINT32_MAX + +extern int hash_val_t_bit; + +#ifndef HASH_VAL_T_BIT +#define HASH_VAL_T_BIT ((int) hash_val_t_bit) +#endif + +/* + * Hash chain node structure. + * Notes: + * 1. This preprocessing directive is for debugging purposes. The effect is + * that if the preprocessor symbol KAZLIB_OPAQUE_DEBUG is defined prior to the + * inclusion of this header, then the structure shall be declared as having + * the single member int __OPAQUE__. This way, any attempts by the + * client code to violate the principles of information hiding (by accessing + * the structure directly) can be diagnosed at translation time. However, + * note the resulting compiled unit is not suitable for linking. + * 2. This is a pointer to the next node in the chain. In the last node of a + * chain, this pointer is null. + * 3. The key is a pointer to some user supplied data that contains a unique + * identifier for each hash node in a given table. The interpretation of + * the data is up to the user. When creating or initializing a hash table, + * the user must supply a pointer to a function for comparing two keys, + * and a pointer to a function for hashing a key into a numeric value. + * 4. The value is a user-supplied pointer to void which may refer to + * any data object. It is not interpreted in any way by the hashing + * module. + * 5. The hashed key is stored in each node so that we don't have to rehash + * each key when the table must grow or shrink. + */ + +typedef struct hnode_t { + #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) /* 1 */ + struct hnode_t *hash_next; /* 2 */ + const void *hash_key; /* 3 */ + void *hash_data; /* 4 */ + hash_val_t hash_hkey; /* 5 */ + #else + int hash_dummy; + #endif +} hnode_t; + +/* + * The comparison function pointer type. A comparison function takes two keys + * and produces a value of -1 if the left key is less than the right key, a + * value of 0 if the keys are equal, and a value of 1 if the left key is + * greater than the right key. + */ + +typedef int (*hash_comp_t)(const void *, const void *); + +/* + * The hashing function performs some computation on a key and produces an + * integral value of type hash_val_t based on that key. For best results, the + * function should have a good randomness properties in *all* significant bits + * over the set of keys that are being inserted into a given hash table. In + * particular, the most significant bits of hash_val_t are most significant to + * the hash module. Only as the hash table expands are less significant bits + * examined. Thus a function that has good distribution in its upper bits but + * not lower is preferrable to one that has poor distribution in the upper bits + * but not the lower ones. + */ + +typedef hash_val_t (*hash_fun_t)(const void *); + +/* + * allocator functions + */ + +typedef hnode_t *(*hnode_alloc_t)(void *); +typedef void (*hnode_free_t)(hnode_t *, void *); + +/* + * This is the hash table control structure. It keeps track of information + * about a hash table, as well as the hash table itself. + * Notes: + * 1. Pointer to the hash table proper. The table is an array of pointers to + * hash nodes (of type hnode_t). If the table is empty, every element of + * this table is a null pointer. A non-null entry points to the first + * element of a chain of nodes. + * 2. This member keeps track of the size of the hash table---that is, the + * number of chain pointers. + * 3. The count member maintains the number of elements that are presently + * in the hash table. + * 4. The maximum count is the greatest number of nodes that can populate this + * table. If the table contains this many nodes, no more can be inserted, + * and the hash_isfull() function returns true. + * 5. The high mark is a population threshold, measured as a number of nodes, + * which, if exceeded, will trigger a table expansion. Only dynamic hash + * tables are subject to this expansion. + * 6. The low mark is a minimum population threshold, measured as a number of + * nodes. If the table population drops below this value, a table shrinkage + * will occur. Only dynamic tables are subject to this reduction. No table + * will shrink beneath a certain absolute minimum number of nodes. + * 7. This is the a pointer to the hash table's comparison function. The + * function is set once at initialization or creation time. + * 8. Pointer to the table's hashing function, set once at creation or + * initialization time. + * 9. The current hash table mask. If the size of the hash table is 2^N, + * this value has its low N bits set to 1, and the others clear. It is used + * to select bits from the result of the hashing function to compute an + * index into the table. + * 10. A flag which indicates whether the table is to be dynamically resized. It + * is set to 1 in dynamically allocated tables, 0 in tables that are + * statically allocated. + */ + +typedef struct hash_t { + #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + struct hnode_t **hash_table; /* 1 */ + hashcount_t hash_nchains; /* 2 */ + hashcount_t hash_nodecount; /* 3 */ + hashcount_t hash_maxcount; /* 4 */ + hashcount_t hash_highmark; /* 5 */ + hashcount_t hash_lowmark; /* 6 */ + hash_comp_t hash_compare; /* 7 */ + hash_fun_t hash_function; /* 8 */ + hnode_alloc_t hash_allocnode; + hnode_free_t hash_freenode; + void *hash_context; + hash_val_t hash_mask; /* 9 */ + int hash_dynamic; /* 10 */ + #else + int hash_dummy; + #endif +} hash_t; + +/* + * Hash scanner structure, used for traversals of the data structure. + * Notes: + * 1. Pointer to the hash table that is being traversed. + * 2. Reference to the current chain in the table being traversed (the chain + * that contains the next node that shall be retrieved). + * 3. Pointer to the node that will be retrieved by the subsequent call to + * hash_scan_next(). + */ + +typedef struct hscan_t { + #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + hash_t *hash_table; /* 1 */ + hash_val_t hash_chain; /* 2 */ + hnode_t *hash_next; /* 3 */ + #else + int hash_dummy; + #endif +} hscan_t; + + +#endif /* ATALK_HASH_H */ diff --git a/include/atalk/iniparser.h b/include/atalk/iniparser.h new file mode 100644 index 0000000..186c90e --- /dev/null +++ b/include/atalk/iniparser.h @@ -0,0 +1,50 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file iniparser.h + @author N. Devillard + @date Sep 2007 + @version 3.0 + @brief Parser for ini files. +*/ +/*--------------------------------------------------------------------------*/ + +/* +*/ + +#ifndef _INIPARSER_H_ +#define _INIPARSER_H_ + +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ + +#include +#include +#include + +/* + * The following #include is necessary on many Unixes but not Linux. + * It is not needed for Windows platforms. + * Uncomment it if needed. + */ +/* #include */ + +#include "dictionary.h" + +int atalk_iniparser_getnsec(const dictionary * d); +const char *atalk_iniparser_getsecname(const dictionary * d, int n); +void atalk_iniparser_dump_ini(const dictionary * d, FILE * f); +void atalk_iniparser_dump(const dictionary * d, FILE * f); +const char *atalk_iniparser_getstring(const dictionary * d, const char *section, const char * key, const char * def); +char *atalk_iniparser_getstrdup(const dictionary * d, const char *section, const char * key, const char * def); +int atalk_iniparser_getint(const dictionary * d, const char *section, const char * key, int notfound); +double atalk_iniparser_getdouble(const dictionary * d, const char *section, const char * key, double notfound); +int atalk_iniparser_getboolean(const dictionary * d, const char *section, const char * key, int notfound); +int atalk_iniparser_set(dictionary * ini, char *section, char * key, char * val); +void atalk_iniparser_unset(dictionary * ini, char *section, char * key); +int atalk_iniparser_find_entry(const dictionary * ini, const char * entry) ; +dictionary *atalk_iniparser_load(const char * ininame); +void atalk_iniparser_freedict(dictionary * d); + +#endif diff --git a/include/atalk/ldapconfig.h b/include/atalk/ldapconfig.h new file mode 100644 index 0000000..f01e0a0 --- /dev/null +++ b/include/atalk/ldapconfig.h @@ -0,0 +1,57 @@ +#ifdef HAVE_LDAP + +#ifndef LDAPCONFIG_H +#define LDAPCONFIG_H + +#include + +/* One function does the whole job */ +extern int acl_ldap_readconfig(dictionary *iniconfig); +extern void acl_ldap_freeconfig(void); + +/* These are the prefvalues */ +extern char *ldap_server; +extern int ldap_auth_method; +extern char *ldap_auth_dn; +extern char *ldap_auth_pw; +extern char *ldap_userbase; +extern char *ldap_groupbase; +extern char *ldap_uuid_attr; +extern char *ldap_uuid_string; +extern char *ldap_name_attr; +extern char *ldap_group_attr; +extern char *ldap_uid_attr; +extern char *ldap_userfilter; +extern char *ldap_groupfilter; +extern int ldap_uuid_encoding; + +typedef enum { + LDAP_UUID_ENCODING_STRING = 0, /* Plain ASCII string */ + LDAP_UUID_ENCODING_MSGUID = 1 /* Raw byte array, from Active Directory objectGUID */ +} ldap_uuid_encoding_type; + +struct ldap_pref { + const void *pref; + char *name; + int strorint; /* string to just store in char * or convert to int ? */ + int intfromarray; /* convert to int, but use string to int mapping array pref_array[] */ + int valid; /* -1 = mandatory, 0 = omittable/valid */ + int valid_save; /* copy of 'valid', used when resettting config */ +}; + +struct pref_array { + const char *pref; /* name of pref from ldap_prefs[] to which this value corresponds */ + char *valuestring; /* config string */ + int value; /* corresponding value */ +}; + + + +/* For parsing */ +extern struct ldap_pref ldap_prefs[]; +extern struct pref_array prefs_array[]; +extern int ldap_config_valid; + +#endif /* LDAPCONFIG_H */ + +#endif /* HAVE_LDAP */ diff --git a/include/atalk/list.h b/include/atalk/list.h new file mode 100644 index 0000000..bb39b90 --- /dev/null +++ b/include/atalk/list.h @@ -0,0 +1,165 @@ +/* This code has been stolen from Linux kernel :) */ +/* distributed under GNU GPL version 2. */ + +#ifndef _ATALK_LIST_H +#define _ATALK_LIST_H + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define ATALK_LIST_HEAD_INIT(name) { &(name), &(name) } + +#define ATALK_LIST_HEAD(name) \ + struct list_head name = ATALK_LIST_HEAD_INIT(name) + +#define ATALK_INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +#ifdef USE_LIST +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + ATALK_INIT_LIST_HEAD(entry); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +#endif +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) + +/** + * list_for_each_prev - iterate over a list in reverse order + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) +#endif diff --git a/include/atalk/logger.h b/include/atalk/logger.h new file mode 100644 index 0000000..3f13965 --- /dev/null +++ b/include/atalk/logger.h @@ -0,0 +1,199 @@ +#ifndef _ATALK_LOGGER_H +#define _ATALK_LOGGER_H 1 + +/* + * logger LOG Macro Usage + * ====================== + * + * LOG(, , ""[, args]); + * + * + * logger API Setup + * ================ + * + * Standard interface: + * ------------------- + * + * setuplog(char *confstring) + * confstring = " []" + * + * Calling without configures basic logging to syslog. Specifying + * configures extended logging to . + * + * You can later disable logging by calling + * + * unsetuplog(char *confstring) + * confstring = " []" + * + * Calling without disables syslog logging, calling with + * disables file logging. + * + * : + * you can setup a default with "Default". Any other logtype used in LOG will then + * use the default if not setup itself. This is probabyl the only thing you may + * want to use. + * + * Example: + * setuplog("default log_debug /var/log/debug.log"); + * See also libatalk/util/test/logger_test.c + * + * "Legacy" interface: + * ------------------- + * + * Some netatalk daemons (31.3.2009.: e.g. atalkd, papd) may not be converted to + * use the new API and might still call + * + * syslog_setup(int loglevel, enum logtypes logtype, int display_options, int facility); + * + * directly. These daemons are therefore limited to syslog logging. Also their + * loglevel can't be changed at runtime. + * + * + * Note: + * dont get confused by log_init(). It only gets called if your app + * forgets to setup logging before calling LOG. + */ + + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* logger is used by pam modules */ +#ifndef UAM_MODULE_EXPORT +#define UAM_MODULE_EXPORT +#endif + +enum loglevels { + log_none, + log_severe, + log_error, + log_warning, + log_note, + log_info, + log_debug, + log_debug6, + log_debug7, + log_debug8, + log_debug9, + log_maxdebug +}; + +/* this is the enum specifying all availiable logtypes */ +enum logtypes { + logtype_default, + logtype_logger, + logtype_cnid, + logtype_afpd, + logtype_dsi, + logtype_uams, + logtype_fce, + logtype_ad, + logtype_sl, + logtype_end_of_list_marker /* don't put any logtypes after this */ +}; + + +/* Display Option flags. */ +/* redefine these so they can don't interfeer with syslog */ +/* these can be used in standard logging too */ +#define logoption_nsrcinfo 0x04 /* don't log source info */ +/* the following do not work anymore, they're only provided in order to not + * break existing source code */ +#define logoption_pid 0x01 /* log the pid with each message */ +#define logoption_cons 0x02 /* log on the console if error logging */ +#define logoption_ndelay 0x08 /* don't delay open */ +#define logoption_perror 0x20 /* log to stderr as well */ +#define logoption_nfile 0x40 /* ignore the file that called the log */ +#define logoption_nline 0x80 /* ignore the line that called the log*/ + +/* facility codes */ +/* redefine these so they can don't interfeer with syslog */ +#define logfacility_user (1<<3) /* random user-level messages */ +#define logfacility_mail (2<<3) /* mail system */ +#define logfacility_daemon (3<<3) /* system daemons */ +#define logfacility_auth (4<<3) /* security/authorization messages */ +#define logfacility_syslog (5<<3) /* messages generated by syslogd */ +#define logfacility_lpr (6<<3) /* line printer subsystem */ +#define logfacility_authpriv (10<<3) /* security/auth messages (private) */ +#define logfacility_ftp (11<<3) /* ftp daemon */ + +/* ========================================================================= + Structure definitions + ========================================================================= */ + +/* Main log config */ +typedef struct { + bool inited; /* file log config initialized ? */ + bool syslog_opened; /* syslog opened ? */ + bool console; /* if logging to console from a cli util */ + char processname[16]; + int syslog_facility; + int syslog_display_options; +} log_config_t; + +/* This stores the config and options for one filelog type (e.g. logger, afpd etc.) */ +typedef struct { + bool set; /* set individually ? yes: changing default + * doesnt change it. no: it changes it.*/ + bool syslog; /* This type logs to syslog */ + int fd; /* logfiles fd */ + enum loglevels level; /* Log Level to put in this file */ + int display_options; +} logtype_conf_t; + + +/* ========================================================================= + Global variables + ========================================================================= */ + +/* Make config accessible for LOG macro */ +extern log_config_t log_config; + +extern UAM_MODULE_EXPORT logtype_conf_t type_configs[logtype_end_of_list_marker]; + +/* ========================================================================= + Global function decarations + ========================================================================= */ + +void setuplog(const char *loglevel, const char *logfile); +void set_processname(const char *processname); + +/* LOG macro func no.1: log the message to file */ +UAM_MODULE_EXPORT void make_log_entry(enum loglevels loglevel, enum logtypes logtype, const char *file, int line, char *message, ...); + +/* + * How to write a LOG macro: + * http://c-faq.com/cpp/debugmacs.html + * + * We choose the verbose form in favor of the obfuscated ones, its easier + * to parse for human beings and facilitates expanding the macro for + * inline checks for debug levels. + */ + +#define LOG_MAX log_info + +#ifdef NO_DEBUG + +#define LOG(log_level, type, ...) \ + do { \ + if (log_level <= LOG_MAX) \ + if (log_level <= type_configs[type].level) \ + make_log_entry((log_level), (type), __FILE__, __LINE__, __VA_ARGS__); \ + } while(0) + +#else /* ! NO_DEBUG */ + +#define LOG(log_level, type, ...) \ + do { \ + if (log_level <= type_configs[type].level) \ + make_log_entry((log_level), (type), __FILE__, __LINE__, __VA_ARGS__); \ + } while(0) + +#endif /* NO_DEBUG */ + +#endif /* _ATALK_LOGGER_H */ diff --git a/include/atalk/netatalk_conf.h b/include/atalk/netatalk_conf.h new file mode 100644 index 0000000..5b30e0b --- /dev/null +++ b/include/atalk/netatalk_conf.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. + */ + +#ifndef AFP_CONFIG_H +#define AFP_CONFIG_H + +#include + +#include +#include + +extern int afp_config_parse(AFPObj *obj, char *processname); +extern void afp_config_free(AFPObj *obj); +extern int load_charset(struct vol *vol); +extern int load_volumes(AFPObj *obj, lv_flags_t flags); +extern void unload_volumes(AFPObj *obj); +extern struct vol *getvolumes(void); +extern struct vol *getvolbyvid(const uint16_t); +extern struct vol *getvolbypath(AFPObj *obj, const char *path); +extern struct vol *getvolbyname(const char *name); +extern void volume_free(struct vol *vol); +extern void volume_unlink(struct vol *volume); + +/* Extension type/creator mapping */ +struct extmap *getdefextmap(void); +struct extmap *getextmap(const char *path); + +#endif diff --git a/include/atalk/paths.h b/include/atalk/paths.h new file mode 100644 index 0000000..f5f6486 --- /dev/null +++ b/include/atalk/paths.h @@ -0,0 +1,17 @@ +#ifndef ATALK_PATHS_H +#define ATALK_PATHS_H 1 + +/* we need a way of concatenating strings */ +#ifdef __STDC__ +#ifdef HAVE_BROKEN_CPP +#define BROKEN_ECHO(a) a +#define ATALKPATHCAT(a,b) BROKEN_ECHO(a)##BROKEN_ECHO(b) +#else +#define ATALKPATHCAT(a,b) a b +#endif +#else +#define ATALKPATHCAT(a,b) a/**/b +#endif + +#endif /* atalk/paths.h */ + diff --git a/include/atalk/queue.h b/include/atalk/queue.h new file mode 100644 index 0000000..a3f433e --- /dev/null +++ b/include/atalk/queue.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2010 Frank Lahm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef ATALK_QUEUE_H +#define ATALK_QUEUE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +typedef struct qnode { + struct qnode *prev; + struct qnode *next; + void *data; +} qnode_t; + +typedef qnode_t q_t; + +extern q_t *queue_init(void); +extern void queue_destroy(q_t *q, void (*callback)(void *)); +#define queue_free(q) queue_destroy((q), free) +extern qnode_t *enqueue(q_t *q, void *data); +extern qnode_t *prequeue(q_t *q, void *data); +extern void *dequeue(q_t *q); + +#endif /* ATALK_QUEUE_H */ diff --git a/include/atalk/server_child.h b/include/atalk/server_child.h new file mode 100644 index 0000000..27ee305 --- /dev/null +++ b/include/atalk/server_child.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. + */ + +#ifndef _ATALK_SERVER_CHILD_H +#define _ATALK_SERVER_CHILD_H 1 + +#include +#include +#include + +/* useful stuff for child processes. most of this is hidden in + * server_child.c to ease changes in implementation */ + +#define CHILD_HASHSIZE 32 + +/* One AFP session child process */ +typedef struct afp_child { + pid_t afpch_pid; /* afpd worker process pid (from the worker afpd process )*/ + uid_t afpch_uid; /* user id of connected client (from the worker afpd process) */ + int afpch_valid; /* 1 if we have a clientid */ + int afpch_killed; /* 1 if we already tried to kill the client */ + uint32_t afpch_boottime; /* client boot time (from the mac client) */ + time_t afpch_logintime; /* time the child was added */ + uint32_t afpch_idlen; /* clientid len (from the Mac client) */ + char *afpch_clientid; /* clientid (from the Mac client) */ + int afpch_ipc_fd; /* socket for IPC bw afpd parent and childs */ + int16_t afpch_state; /* state of AFP session (eg active, sleeping, disconnected) */ + char *afpch_volumes; /* mounted volumes */ + struct afp_child **afpch_prevp; + struct afp_child *afpch_next; +} afp_child_t; + +/* Info and table with all AFP session child processes */ +typedef struct { + pthread_mutex_t servch_lock; /* Lock */ + int servch_count; /* Current count of active AFP sessions */ + int servch_nsessions; /* Number of allowed AFP sessions */ + afp_child_t *servch_table[CHILD_HASHSIZE]; /* Hashtable with data of AFP sesssions */ +} server_child_t; + +/* server_child.c */ +extern server_child_t *server_child_alloc(int); +extern afp_child_t *server_child_add(server_child_t *, pid_t, int ipc_fd); +extern int server_child_remove(server_child_t *, pid_t); +extern void server_child_free(server_child_t *); +extern afp_child_t *server_child_resolve(server_child_t *childs, id_t pid); + +extern void server_child_kill(server_child_t *, int); +extern void server_child_kill_one_by_id(server_child_t *children, pid_t pid, uid_t, + uint32_t len, char *id, uint32_t boottime); +extern int server_child_transfer_session(server_child_t *children, pid_t, uid_t, int, uint16_t); +extern void server_child_handler(server_child_t *); +extern void server_reset_signal(void); + +#endif diff --git a/include/atalk/server_ipc.h b/include/atalk/server_ipc.h new file mode 100644 index 0000000..0c38a7b --- /dev/null +++ b/include/atalk/server_ipc.h @@ -0,0 +1,17 @@ +#ifndef ATALK_SERVER_IPC_H +#define ATALK_SERVER_IPC_H + +#include +#include + +/* Remember to add IPC commands to server_ipc.c:ipc_cmd_str[] */ +#define IPC_DISCOLDSESSION 0 +#define IPC_GETSESSION 1 +#define IPC_STATE 2 /* pass AFP session state */ +#define IPC_VOLUMES 3 /* pass list of open volumes */ + +extern int ipc_server_read(server_child_t *children, int fd); +extern int ipc_child_write(int fd, uint16_t command, int len, void *token); +extern int ipc_child_state(AFPObj *obj, uint16_t state); + +#endif /* IPC_GETSESSION_LOGIN */ diff --git a/include/atalk/spotlight.h b/include/atalk/spotlight.h new file mode 100644 index 0000000..0e64b86 --- /dev/null +++ b/include/atalk/spotlight.h @@ -0,0 +1,128 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef SPOTLIGHT_H +#define SPOTLIGHT_H + +#include +#include + +#include +#include +#include + +#ifdef HAVE_TRACKER +#include +#include +#include +#endif + +/****************************************************************************** + * Spotlight RPC and marshalling stuff + ******************************************************************************/ + +/* FPSpotlightRPC subcommand codes */ +#define SPOTLIGHT_CMD_OPEN 1 +#define SPOTLIGHT_CMD_FLAGS 2 +#define SPOTLIGHT_CMD_RPC 3 +#define SPOTLIGHT_CMD_OPEN2 4 + +/* Can be ored and used as flags */ +#define SL_ENC_LITTLE_ENDIAN 1 +#define SL_ENC_BIG_ENDIAN 2 +#define SL_ENC_UTF_16 4 + +typedef DALLOC_CTX sl_array_t; /* an array of elements */ +typedef DALLOC_CTX sl_dict_t; /* an array of key/value elements */ +typedef DALLOC_CTX sl_filemeta_t; /* contains one sl_array_t */ +typedef int sl_nil_t; /* a nil element */ +typedef bool sl_bool_t; /* a boolean, we avoid bool_t */ +typedef struct timeval sl_time_t; +typedef struct { + char sl_uuid[16]; +} sl_uuid_t; /* a UUID */ +typedef struct { + uint16_t ca_unkn1; + uint32_t ca_context; + DALLOC_CTX *ca_cnids; +} sl_cnids_t; /* an array of CNIDs */ + +/****************************************************************************** + * Some helper stuff dealing with queries + ******************************************************************************/ + +/* query state */ +typedef enum { + SLQ_STATE_NEW, /* Query received from client */ + SLQ_STATE_RUNNING, /* Query dispatched to Tracker */ + SLQ_STATE_RESULTS, /* Async Tracker query read */ + SLQ_STATE_FULL, /* result queue is full */ + SLQ_STATE_DONE, /* Got all results from Tracker */ + SLQ_STATE_CANCEL_PENDING, /* a cancel op for the query is pending */ + SLQ_STATE_CANCELLED, /* the query has been cancelled */ + SLQ_STATE_ERROR /* an error happended somewhere */ +} slq_state_t; + +/* Handle for query results */ +struct sl_rslts { + int num_results; + sl_cnids_t *cnids; + sl_array_t *fm_array; +}; + +/* Internal query data structure */ +typedef struct _slq_t { + struct list_head slq_list; /* queries are stored in a list */ + slq_state_t slq_state; /* State */ + AFPObj *slq_obj; /* global AFPObj handle */ + const struct vol *slq_vol; /* volume handle */ + char *slq_scope; /* search scope */ + time_t slq_time; /* timestamp received query */ + uint64_t slq_ctx1; /* client context 1 */ + uint64_t slq_ctx2; /* client context 2 */ + sl_array_t *slq_reqinfo; /* array with requested metadata */ + const char *slq_qstring; /* the Spotlight query string */ + uint64_t *slq_cnids; /* Pointer to array with CNIDs */ + size_t slq_cnids_num; /* Size of slq_cnids array */ + void *tracker_cursor; /* Tracker SPARQL cursor */ + bool slq_allow_expr; /* Whether to allow expressions */ + uint64_t slq_result_limit; /* Whether to LIMIT SPARQL results */ + struct sl_rslts *query_results; /* query results */ +} slq_t; + +struct sl_ctx { +#ifdef HAVE_TRACKER + TrackerSparqlConnection *tracker_con; + GCancellable *cancellable; + GMainLoop *mainloop; +#endif + slq_t *query_list; /* list of active queries */ +}; + +/****************************************************************************** + * Function declarations + ******************************************************************************/ + +extern int spotlight_init(AFPObj *obj); +extern int afp_spotlight_rpc(AFPObj *obj, char *ibuf, size_t ibuflen _U_, + char *rbuf, size_t *rbuflen); +extern int sl_pack(DALLOC_CTX *query, char *buf); +extern int sl_unpack(DALLOC_CTX *query, const char *buf); +extern void configure_spotlight_attributes(const char *attributes); + +#endif /* SPOTLIGHT_H */ diff --git a/include/atalk/standards.h b/include/atalk/standards.h new file mode 100644 index 0000000..85421f2 --- /dev/null +++ b/include/atalk/standards.h @@ -0,0 +1,34 @@ +/* + Copyright (c) 2011, Frank Lahm + + 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. +*/ + +#ifndef ATALK_STANDARDS_H +#define ATALK_STANDARDS_H 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) +# ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 600 +# endif +# ifndef __EXTENSIONS__ +# define __EXTENSIONS__ +# endif +# ifndef _GNU_SOURCE +# define _GNU_SOURCE +# endif +#endif + +#endif /* ATALK_STANDARDS_H */ diff --git a/include/atalk/talloc.h b/include/atalk/talloc.h new file mode 100644 index 0000000..96c7e24 --- /dev/null +++ b/include/atalk/talloc.h @@ -0,0 +1,1711 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup talloc The talloc API + * + * talloc is a hierarchical, reference counted memory pool system with + * destructors. It is the core memory allocator used in Samba. + * + * @{ + */ + +#define TALLOC_VERSION_MAJOR 2 +#define TALLOC_VERSION_MINOR 0 + +int talloc_version_major(void); +int talloc_version_minor(void); + +/** + * @brief Define a talloc parent type + * + * As talloc is a hierarchial memory allocator, every talloc chunk is a + * potential parent to other talloc chunks. So defining a separate type for a + * talloc chunk is not strictly necessary. TALLOC_CTX is defined nevertheless, + * as it provides an indicator for function arguments. You will frequently + * write code like + * + * @code + * struct foo *foo_create(TALLOC_CTX *mem_ctx) + * { + * struct foo *result; + * result = talloc(mem_ctx, struct foo); + * if (result == NULL) return NULL; + * ... initialize foo ... + * return result; + * } + * @endcode + * + * In this type of allocating functions it is handy to have a general + * TALLOC_CTX type to indicate which parent to put allocated structures on. + */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#ifndef __location__ +#define __TALLOC_STRING_LINE1__(s) #s +#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s) +#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__) +#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__ +#endif + +#ifndef TALLOC_DEPRECATED +#define TALLOC_DEPRECATED 0 +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#ifdef DOXYGEN +/** + * @brief Create a new talloc context. + * + * The talloc() macro is the core of the talloc library. It takes a memory + * context and a type, and returns a pointer to a new area of memory of the + * given type. + * + * The returned pointer is itself a talloc context, so you can use it as the + * context argument to more calls to talloc if you wish. + * + * The returned pointer is a "child" of the supplied context. This means that if + * you talloc_free() the context then the new child disappears as well. + * Alternatively you can free just the child. + * + * @param[in] ctx A talloc context to create a new reference on or NULL to + * create a new top level context. + * + * @param[in] type The type of memory to allocate. + * + * @return A type casted talloc context or NULL on error. + * + * @code + * unsigned int *a, *b; + * + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * @endcode + * + * @see talloc_zero + * @see talloc_array + * @see talloc_steal + * @see talloc_free + */ +void *talloc(const void *ctx, #type); +#else +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +void *_talloc(const void *context, size_t size); +#endif + +/** + * @brief Create a new top level talloc context. + * + * This function creates a zero length named talloc context as a top level + * context. It is equivalent to: + * + * @code + * talloc_named(NULL, 0, fmt, ...); + * @endcode + * @param[in] fmt Format string for the name. + * + * @param[in] ... Additional printf-style arguments. + * + * @return The allocated memory chunk, NULL on error. + * + * @see talloc_named() + */ +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); + +#ifdef DOXYGEN +/** + * @brief Free a chunk of talloc memory. + * + * The talloc_free() function frees a piece of talloc memory, and all its + * children. You can call talloc_free() on any pointer returned by + * talloc(). + * + * The return value of talloc_free() indicates success or failure, with 0 + * returned for success and -1 for failure. A possible failure condition + * is if the pointer had a destructor attached to it and the destructor + * returned -1. See talloc_set_destructor() for details on + * destructors. Likewise, if "ptr" is NULL, then the function will make + * no modifications and return -1. + * + * From version 2.0 and onwards, as a special case, talloc_free() is + * refused on pointers that have more than one parent associated, as talloc + * would have no way of knowing which parent should be removed. This is + * different from older versions in the sense that always the reference to + * the most recently established parent has been destroyed. Hence to free a + * pointer that has more than one parent please use talloc_unlink(). + * + * To help you find problems in your code caused by this behaviour, if + * you do try and free a pointer with more than one parent then the + * talloc logging function will be called to give output like this: + * + * @code + * ERROR: talloc_free with references at some_dir/source/foo.c:123 + * reference at some_dir/source/other.c:325 + * reference at some_dir/source/third.c:121 + * @endcode + * + * Please see the documentation for talloc_set_log_fn() and + * talloc_set_log_stderr() for more information on talloc logging + * functions. + * + * talloc_free() operates recursively on its children. + * + * @param[in] ptr The chunk to be freed. + * + * @return Returns 0 on success and -1 on error. A possible + * failure condition is if the pointer had a destructor + * attached to it and the destructor returned -1. Likewise, + * if "ptr" is NULL, then the function will make no + * modifications and returns -1. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * + * talloc_free(a); // Frees a and b + * @endcode + * + * @see talloc_set_destructor() + * @see talloc_unlink() + */ +int talloc_free(void *ptr); +#else +#define talloc_free(ctx) _talloc_free(ctx, __location__) +int _talloc_free(void *ptr, const char *location); +#endif + +/** + * @brief Free a talloc chunk's children. + * + * The function walks along the list of all children of a talloc context and + * talloc_free()s only the children, not the context itself. + * + * A NULL argument is handled as no-op. + * + * @param[in] ptr The chunk that you want to free the children of + * (NULL is allowed too) + */ +void talloc_free_children(void *ptr); + +#ifdef DOXYGEN +/** + * @brief Assign a destructor function to be called when a chunk is freed. + * + * The function talloc_set_destructor() sets the "destructor" for the pointer + * "ptr". A destructor is a function that is called when the memory used by a + * pointer is about to be released. The destructor receives the pointer as an + * argument, and should return 0 for success and -1 for failure. + * + * The destructor can do anything it wants to, including freeing other pieces + * of memory. A common use for destructors is to clean up operating system + * resources (such as open file descriptors) contained in the structure the + * destructor is placed on. + * + * You can only place one destructor on a pointer. If you need more than one + * destructor then you can create a zero-length child of the pointer and place + * an additional destructor on that. + * + * To remove a destructor call talloc_set_destructor() with NULL for the + * destructor. + * + * If your destructor attempts to talloc_free() the pointer that it is the + * destructor for then talloc_free() will return -1 and the free will be + * ignored. This would be a pointless operation anyway, as the destructor is + * only called when the memory is just about to go away. + * + * @param[in] ptr The talloc chunk to add a destructor to. + * + * @param[in] destructor The destructor function to be called. NULL to remove + * it. + * + * Example: + * @code + * static int destroy_fd(int *fd) { + * close(*fd); + * return 0; + * } + * + * int *open_file(const char *filename) { + * int *fd = talloc(NULL, int); + * *fd = open(filename, O_RDONLY); + * if (*fd < 0) { + * talloc_free(fd); + * return NULL; + * } + * // Whenever they free this, we close the file. + * talloc_set_destructor(fd, destroy_fd); + * return fd; + * } + * @endcode + * + * @see talloc() + * @see talloc_free() + */ +void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); + +/** + * @brief Change a talloc chunk's parent. + * + * The talloc_steal() function changes the parent context of a talloc + * pointer. It is typically used when the context that the pointer is + * currently a child of is going to be freed and you wish to keep the + * memory for a longer time. + * + * To make the changed hierarchy less error-prone, you might consider to use + * talloc_move(). + * + * If you try and call talloc_steal() on a pointer that has more than one + * parent then the result is ambiguous. Talloc will choose to remove the + * parent that is currently indicated by talloc_parent() and replace it with + * the chosen parent. You will also get a message like this via the talloc + * logging functions: + * + * @code + * WARNING: talloc_steal with references at some_dir/source/foo.c:123 + * reference at some_dir/source/other.c:325 + * reference at some_dir/source/third.c:121 + * @endcode + * + * To unambiguously change the parent of a pointer please see the function + * talloc_reparent(). See the talloc_set_log_fn() documentation for more + * information on talloc logging. + * + * @param[in] new_ctx The new parent context. + * + * @param[in] ptr The talloc chunk to move. + * + * @return Returns the pointer that you pass it. It does not have + * any failure modes. + * + * @note It is possible to produce loops in the parent/child relationship + * if you are not careful with talloc_steal(). No guarantees are provided + * as to your sanity or the safety of your data if you do this. + */ +void *talloc_steal(const void *new_ctx, const void *ptr); +#else /* DOXYGEN */ +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ + _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ + } while(0) +/* this extremely strange macro is to avoid some braindamaged warning + stupidity in gcc 4.1.x */ +#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; }) +#else /* __GNUC__ >= 3 */ +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__) +#endif /* __GNUC__ >= 3 */ +void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); +void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location); +#endif /* DOXYGEN */ + +/** + * @brief Assign a name to a talloc chunk. + * + * Each talloc pointer has a "name". The name is used principally for + * debugging purposes, although it is also possible to set and get the name on + * a pointer in as a way of "marking" pointers in your code. + * + * The main use for names on pointer is for "talloc reports". See + * talloc_report() and talloc_report_full() for details. Also see + * talloc_enable_leak_report() and talloc_enable_leak_report_full(). + * + * The talloc_set_name() function allocates memory as a child of the + * pointer. It is logically equivalent to: + * + * @code + * talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...)); + * @endcode + * + * @param[in] ptr The talloc chunk to assign a name to. + * + * @param[in] fmt Format string for the name. + * + * @param[in] ... Add printf-style additional arguments. + * + * @return The assigned name, NULL on error. + * + * @note Multiple calls to talloc_set_name() will allocate more memory without + * releasing the name. All of the memory is released when the ptr is freed + * using talloc_free(). + */ +const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +#ifdef DOXYGEN +/** + * @brief Change a talloc chunk's parent. + * + * This function has the same effect as talloc_steal(), and additionally sets + * the source pointer to NULL. You would use it like this: + * + * @code + * struct foo *X = talloc(tmp_ctx, struct foo); + * struct foo *Y; + * Y = talloc_move(new_ctx, &X); + * @endcode + * + * @param[in] new_ctx The new parent context. + * + * @param[in] pptr Pointer to the talloc chunk to move. + * + * @return The pointer of the talloc chunk it has been moved to, + * NULL on error. + */ +void *talloc_move(const void *new_ctx, void **pptr); +#else +#define talloc_move(ctx, pptr) (_TALLOC_TYPEOF(*(pptr)))_talloc_move((ctx),(void *)(pptr)) +void *_talloc_move(const void *new_ctx, const void *pptr); +#endif + +/** + * @brief Assign a name to a talloc chunk. + * + * The function is just like talloc_set_name(), but it takes a string constant, + * and is much faster. It is extensively used by the "auto naming" macros, such + * as talloc_p(). + * + * This function does not allocate any memory. It just copies the supplied + * pointer into the internal representation of the talloc ptr. This means you + * must not pass a name pointer to memory that will disappear before the ptr + * is freed with talloc_free(). + * + * @param[in] ptr The talloc chunk to assign a name to. + * + * @param[in] name Format string for the name. + */ +void talloc_set_name_const(const void *ptr, const char *name); + +/** + * @brief Create a named talloc chunk. + * + * The talloc_named() function creates a named talloc pointer. It is + * equivalent to: + * + * @code + * ptr = talloc_size(context, size); + * talloc_set_name(ptr, fmt, ....); + * @endcode + * + * @param[in] context The talloc context to hang the result off. + * + * @param[in] size Number of char's that you want to allocate. + * + * @param[in] fmt Format string for the name. + * + * @param[in] ... Additional printf-style arguments. + * + * @return The allocated memory chunk, NULL on error. + * + * @see talloc_set_name() + */ +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); + +/** + * @brief Basic routine to allocate a chunk of memory. + * + * This is equivalent to: + * + * @code + * ptr = talloc_size(context, size); + * talloc_set_name_const(ptr, name); + * @endcode + * + * @param[in] context The parent context. + * + * @param[in] size The number of char's that we want to allocate. + * + * @param[in] name The name the talloc block has. + * + * @return The allocated memory chunk, NULL on error. + */ +void *talloc_named_const(const void *context, size_t size, const char *name); + +#ifdef DOXYGEN +/** + * @brief Untyped allocation. + * + * The function should be used when you don't have a convenient type to pass to + * talloc(). Unlike talloc(), it is not type safe (as it returns a void *), so + * you are on your own for type checking. + * + * Best to use talloc() or talloc_array() instead. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] size Number of char's that you want to allocate. + * + * @return The allocated memory chunk, NULL on error. + * + * Example: + * @code + * void *mem = talloc_size(NULL, 100); + * @endcode + */ +void *talloc_size(const void *ctx, size_t size); +#else +#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate into a typed pointer. + * + * The talloc_ptrtype() macro should be used when you have a pointer and want + * to allocate memory to point at with this pointer. When compiling with + * gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size() and + * talloc_get_name() will return the current location in the source file and + * not the type. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The pointer you want to assign the result to. + * + * @return The properly casted allocated memory chunk, NULL on + * error. + * + * Example: + * @code + * unsigned int *a = talloc_ptrtype(NULL, a); + * @endcode + */ +void *talloc_ptrtype(const void *ctx, #type); +#else +#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate a new 0-sized talloc chunk. + * + * This is a utility macro that creates a new memory context hanging off an + * existing context, automatically naming it "talloc_new: __location__" where + * __location__ is the source line it is called from. It is particularly + * useful for creating a new temporary working context. + * + * @param[in] ctx The talloc parent context. + * + * @return A new talloc chunk, NULL on error. + */ +void *talloc_new(const void *ctx); +#else +#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate a 0-initizialized structure. + * + * The macro is equivalent to: + * + * @code + * ptr = talloc(ctx, type); + * if (ptr) memset(ptr, 0, sizeof(type)); + * @endcode + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The type that we want to allocate. + * + * @return Pointer to a piece of memory, properly cast to 'type *', + * NULL on error. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc_zero(NULL, unsigned int); + * b = talloc_zero(a, unsigned int); + * @endcode + * + * @see talloc() + * @see talloc_zero_size() + * @see talloc_zero_array() + */ +void *talloc_zero(const void *ctx, #type); + +/** + * @brief Allocate untyped, 0-initialized memory. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] size Number of char's that you want to allocate. + * + * @return The allocated memory chunk. + */ +void *talloc_zero_size(const void *ctx, size_t size); +#else +#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) +void *_talloc_zero(const void *ctx, size_t size, const char *name); +#endif + +/** + * @brief Return the name of a talloc chunk. + * + * @param[in] ptr The talloc chunk. + * + * @return The current name for the given talloc pointer. + * + * @see talloc_set_name() + */ +const char *talloc_get_name(const void *ptr); + +/** + * @brief Verify that a talloc chunk carries a specified name. + * + * This function checks if a pointer has the specified name. If it does + * then the pointer is returned. + * + * @param[in] ptr The talloc chunk to check. + * + * @param[in] name The name to check against. + * + * @return The pointer if the name matches, NULL if it doesn't. + */ +void *talloc_check_name(const void *ptr, const char *name); + +/** + * @brief Get the parent chunk of a pointer. + * + * @param[in] ptr The talloc pointer to inspect. + * + * @return The talloc parent of ptr, NULL on error. + */ +void *talloc_parent(const void *ptr); + +/** + * @brief Get a talloc chunk's parent name. + * + * @param[in] ptr The talloc pointer to inspect. + * + * @return The name of ptr's parent chunk. + */ +const char *talloc_parent_name(const void *ptr); + +/** + * @brief Get the total size of a talloc chunk including its children. + * + * The function returns the total size in bytes used by this pointer and all + * child pointers. Mostly useful for debugging. + * + * Passing NULL is allowed, but it will only give a meaningful result if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() has + * been called. + * + * @param[in] ptr The talloc chunk. + * + * @return The total size. + */ +size_t talloc_total_size(const void *ptr); + +/** + * @brief Get the number of talloc chunks hanging off a chunk. + * + * The talloc_total_blocks() function returns the total memory block + * count used by this pointer and all child pointers. Mostly useful for + * debugging. + * + * Passing NULL is allowed, but it will only give a meaningful result if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() has + * been called. + * + * @param[in] ptr The talloc chunk. + * + * @return The total size. + */ +size_t talloc_total_blocks(const void *ptr); + +#ifdef DOXYGEN +/** + * @brief Duplicate a memory area into a talloc chunk. + * + * The function is equivalent to: + * + * @code + * ptr = talloc_size(ctx, size); + * if (ptr) memcpy(ptr, p, size); + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] p The memory chunk you want to duplicate. + * + * @param[in] size Number of char's that you want copy. + * + * @return The allocated memory chunk. + * + * @see talloc_size() + */ +void *talloc_memdup(const void *t, const void *p, size_t size); +#else +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Assign a type to a talloc chunk. + * + * This macro allows you to force the name of a pointer to be of a particular + * type. This can be used in conjunction with talloc_get_type() to do type + * checking on void* pointers. + * + * It is equivalent to this: + * + * @code + * talloc_set_name_const(ptr, #type) + * @endcode + * + * @param[in] ptr The talloc chunk to assign the type to. + * + * @param[in] type The type to assign. + */ +void talloc_set_type(const char *ptr, #type); + +/** + * @brief Get a typed pointer out of a talloc pointer. + * + * This macro allows you to do type checking on talloc pointers. It is + * particularly useful for void* private pointers. It is equivalent to + * this: + * + * @code + * (type *)talloc_check_name(ptr, #type) + * @endcode + * + * @param[in] ptr The talloc pointer to check. + * + * @param[in] type The type to check against. + * + * @return The properly casted pointer given by ptr, NULL on error. + */ +type *talloc_get_type(const void *ptr, #type); +#else +#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) +#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#endif + +#ifdef DOXYGEN +/** + * @brief Safely turn a void pointer into a typed pointer. + * + * This macro is used together with talloc(mem_ctx, struct foo). If you had to + * assing the talloc chunk pointer to some void pointer variable, + * talloc_get_type_abort() is the recommended way to get the convert the void + * pointer back to a typed pointer. + * + * @param[in] ptr The void pointer to convert. + * + * @param[in] type The type that this chunk contains + * + * @return The same value as ptr, type-checked and properly cast. + */ +void *talloc_get_type_abort(const void *ptr, #type); +#else +#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); +#endif + +/** + * @brief Find a parent context by name. + * + * Find a parent memory context of the current context that has the given + * name. This can be very useful in complex programs where it may be + * difficult to pass all information down to the level you need, but you + * know the structure you want is a parent of another context. + * + * @param[in] ctx The talloc chunk to start from. + * + * @param[in] name The name of the parent we look for. + * + * @return The memory context we are looking for, NULL if not + * found. + */ +void *talloc_find_parent_byname(const void *ctx, const char *name); + +#ifdef DOXYGEN +/** + * @brief Find a parent context by type. + * + * Find a parent memory context of the current context that has the given + * name. This can be very useful in complex programs where it may be + * difficult to pass all information down to the level you need, but you + * know the structure you want is a parent of another context. + * + * Like talloc_find_parent_byname() but takes a type, making it typesafe. + * + * @param[in] ptr The talloc chunk to start from. + * + * @param[in] type The type of the parent to look for. + * + * @return The memory context we are looking for, NULL if not + * found. + */ +void *talloc_find_parent_bytype(const void *ptr, #type); +#else +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) +#endif + +/** + * @brief Allocate a talloc pool. + * + * A talloc pool is a pure optimization for specific situations. In the + * release process for Samba 3.2 we found out that we had become considerably + * slower than Samba 3.0 was. Profiling showed that malloc(3) was a large CPU + * consumer in benchmarks. For Samba 3.2 we have internally converted many + * static buffers to dynamically allocated ones, so malloc(3) being beaten + * more was no surprise. But it made us slower. + * + * talloc_pool() is an optimization to call malloc(3) a lot less for the use + * pattern Samba has: The SMB protocol is mainly a request/response protocol + * where we have to allocate a certain amount of memory per request and free + * that after the SMB reply is sent to the client. + * + * talloc_pool() creates a talloc chunk that you can use as a talloc parent + * exactly as you would use any other ::TALLOC_CTX. The difference is that + * when you talloc a child of this pool, no malloc(3) is done. Instead, talloc + * just increments a pointer inside the talloc_pool. This also works + * recursively. If you use the child of the talloc pool as a parent for + * grand-children, their memory is also taken from the talloc pool. + * + * If you talloc_free() children of a talloc pool, the memory is not given + * back to the system. Instead, free(3) is only called if the talloc_pool() + * itself is released with talloc_free(). + * + * The downside of a talloc pool is that if you talloc_move() a child of a + * talloc pool to a talloc parent outside the pool, the whole pool memory is + * not free(3)'ed until that moved chunk is also talloc_free()ed. + * + * @param[in] context The talloc context to hang the result off. + * + * @param[in] size Size of the talloc pool. + * + * @return The allocated talloc pool, NULL on error. + */ +void *talloc_pool(const void *context, size_t size); + +/** + * @brief Free a talloc chunk and NULL out the pointer. + * + * TALLOC_FREE() frees a pointer and sets it to NULL. Use this if you want + * immediate feedback (i.e. crash) if you use a pointer after having free'ed + * it. + * + * @param[in] ctx The chunk to be freed. + */ +#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) + +/* @} ******************************************************************/ + +/** + * \defgroup talloc_ref The talloc reference function. + * @ingroup talloc + * + * This module contains the definitions around talloc references + * + * @{ + */ + +/** + * @brief Increase the reference count of a talloc chunk. + * + * The talloc_increase_ref_count(ptr) function is exactly equivalent to: + * + * @code + * talloc_reference(NULL, ptr); + * @endcode + * + * You can use either syntax, depending on which you think is clearer in + * your code. + * + * @param[in] ptr The pointer to increase the reference count. + * + * @return 0 on success, -1 on error. + */ +int talloc_increase_ref_count(const void *ptr); + +/** + * @brief Get the number of references to a talloc chunk. + * + * @param[in] ptr The pointer to retrieve the reference count from. + * + * @return The number of references. + */ +size_t talloc_reference_count(const void *ptr); + +#ifdef DOXYGEN +/** + * @brief Create an additional talloc parent to a pointer. + * + * The talloc_reference() function makes "context" an additional parent of + * ptr. Each additional reference consumes around 48 bytes of memory on intel + * x86 platforms. + * + * If ptr is NULL, then the function is a no-op, and simply returns NULL. + * + * After creating a reference you can free it in one of the following ways: + * + * - you can talloc_free() any parent of the original pointer. That + * will reduce the number of parents of this pointer by 1, and will + * cause this pointer to be freed if it runs out of parents. + * + * - you can talloc_free() the pointer itself if it has at maximum one + * parent. This behaviour has been changed since the release of version + * 2.0. Further informations in the description of "talloc_free". + * + * For more control on which parent to remove, see talloc_unlink() + * @param[in] ctx The additional parent. + * + * @param[in] ptr The pointer you want to create an additional parent for. + * + * @return The original pointer 'ptr', NULL if talloc ran out of + * memory in creating the reference. + * + * Example: + * @code + * unsigned int *a, *b, *c; + * a = talloc(NULL, unsigned int); + * b = talloc(NULL, unsigned int); + * c = talloc(a, unsigned int); + * // b also serves as a parent of c. + * talloc_reference(b, c); + * @endcode + * + * @see talloc_unlink() + */ +void *talloc_reference(const void *ctx, const void *ptr); +#else +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__) +void *_talloc_reference_loc(const void *context, const void *ptr, const char *location); +#endif + +/** + * @brief Remove a specific parent from a talloc chunk. + * + * The function removes a specific parent from ptr. The context passed must + * either be a context used in talloc_reference() with this pointer, or must be + * a direct parent of ptr. + * + * You can just use talloc_free() instead of talloc_unlink() if there + * is at maximum one parent. This behaviour has been changed since the + * release of version 2.0. Further informations in the description of + * "talloc_free". + * + * @param[in] context The talloc parent to remove. + * + * @param[in] ptr The talloc ptr you want to remove the parent from. + * + * @return 0 on success, -1 on error. + * + * @note If the parent has already been removed using talloc_free() then + * this function will fail and will return -1. Likewise, if ptr is NULL, + * then the function will make no modifications and return -1. + * + * Example: + * @code + * unsigned int *a, *b, *c; + * a = talloc(NULL, unsigned int); + * b = talloc(NULL, unsigned int); + * c = talloc(a, unsigned int); + * // b also serves as a parent of c. + * talloc_reference(b, c); + * talloc_unlink(b, c); + * @endcode + */ +int talloc_unlink(const void *context, void *ptr); + +/** + * @brief Provide a talloc context that is freed at program exit. + * + * This is a handy utility function that returns a talloc context + * which will be automatically freed on program exit. This can be used + * to reduce the noise in memory leak reports. + * + * Never use this in code that might be used in objects loaded with + * dlopen and unloaded with dlclose. talloc_autofree_context() + * internally uses atexit(3). Some platforms like modern Linux handles + * this fine, but for example FreeBSD does not deal well with dlopen() + * and atexit() used simultaneously: dlclose() does not clean up the + * list of atexit-handlers, so when the program exits the code that + * was registered from within talloc_autofree_context() is gone, the + * program crashes at exit. + * + * @return A talloc context, NULL on error. + */ +void *talloc_autofree_context(void); + +/** + * @brief Get the size of a talloc chunk. + * + * This function lets you know the amount of memory allocated so far by + * this context. It does NOT account for subcontext memory. + * This can be used to calculate the size of an array. + * + * @param[in] ctx The talloc chunk. + * + * @return The size of the talloc chunk. + */ +size_t talloc_get_size(const void *ctx); + +/** + * @brief Show the parentage of a context. + * + * @param[in] context The talloc context to look at. + * + * @param[in] file The output to use, a file, stdout or stderr. + */ +void talloc_show_parents(const void *context, FILE *file); + +/** + * @brief Check if a context is parent of a talloc chunk. + * + * This checks if context is referenced in the talloc hierarchy above ptr. + * + * @param[in] context The assumed talloc context. + * + * @param[in] ptr The talloc chunk to check. + * + * @return Return 1 if this is the case, 0 if not. + */ +int talloc_is_parent(const void *context, const void *ptr); + +/** + * @brief Change the parent context of a talloc pointer. + * + * The function changes the parent context of a talloc pointer. It is typically + * used when the context that the pointer is currently a child of is going to be + * freed and you wish to keep the memory for a longer time. + * + * The difference between talloc_reparent() and talloc_steal() is that + * talloc_reparent() can specify which parent you wish to change. This is + * useful when a pointer has multiple parents via references. + * + * @param[in] old_parent + * @param[in] new_parent + * @param[in] ptr + * + * @return Return the pointer you passed. It does not have any + * failure modes. + */ +void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); + +/* @} ******************************************************************/ + +/** + * @defgroup talloc_array The talloc array functions + * @ingroup talloc + * + * Talloc contains some handy helpers for handling Arrays conveniently + * + * @{ + */ + +#ifdef DOXYGEN +/** + * @brief Allocate an array. + * + * The macro is equivalent to: + * + * @code + * (type *)talloc_size(ctx, sizeof(type) * count); + * @endcode + * + * except that it provides integer overflow protection for the multiply, + * returning NULL if the multiply overflows. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The type that we want to allocate. + * + * @param[in] count The number of 'type' elements you want to allocate. + * + * @return The allocated result, properly cast to 'type *', NULL on + * error. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc_zero(NULL, unsigned int); + * b = talloc_array(a, unsigned int, 100); + * @endcode + * + * @see talloc() + * @see talloc_zero_array() + */ +void *talloc_array(const void *ctx, #type, unsigned count); +#else +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate an array. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] size The size of an array element. + * + * @param[in] count The number of elements you want to allocate. + * + * @return The allocated result, NULL on error. + */ +void *talloc_array_size(const void *ctx, size_t size, unsigned count); +#else +#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate an array into a typed pointer. + * + * The macro should be used when you have a pointer to an array and want to + * allocate memory of an array to point at with this pointer. When compiling + * with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size() + * and talloc_get_name() will return the current location in the source file + * and not the type. + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] ptr The pointer you want to assign the result to. + * + * @param[in] count The number of elements you want to allocate. + * + * @return The allocated memory chunk, properly casted. NULL on + * error. + */ +void *talloc_array_ptrtype(const void *ctx, const void *ptr, unsigned count); +#else +#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) +#endif + +#ifdef DOXYGEN +/** + * @brief Get the number of elements in a talloc'ed array. + * + * A talloc chunk carries its own size, so for talloc'ed arrays it is not + * necessary to store the number of elements explicitly. + * + * @param[in] ctx The allocated array. + * + * @return The number of elements in ctx. + */ +size_t talloc_array_length(const void *ctx); +#else +#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) +#endif + +#ifdef DOXYGEN +/** + * @brief Allocate a zero-initialized array + * + * @param[in] ctx The talloc context to hang the result off. + * + * @param[in] type The type that we want to allocate. + * + * @param[in] count The number of "type" elements you want to allocate. + * + * @return The allocated result casted to "type *", NULL on error. + * + * The talloc_zero_array() macro is equivalent to: + * + * @code + * ptr = talloc_array(ctx, type, count); + * if (ptr) memset(ptr, sizeof(type) * count); + * @endcode + */ +void *talloc_zero_array(const void *ctx, #type, unsigned count); +#else +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +void *_talloc_zero_array(const void *ctx, + size_t el_size, + unsigned count, + const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Change the size of a talloc array. + * + * The macro changes the size of a talloc pointer. The 'count' argument is the + * number of elements of type 'type' that you want the resulting pointer to + * hold. + * + * talloc_realloc() has the following equivalences: + * + * @code + * talloc_realloc(ctx, NULL, type, 1) ==> talloc(ctx, type); + * talloc_realloc(ctx, NULL, type, N) ==> talloc_array(ctx, type, N); + * talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr); + * @endcode + * + * The "context" argument is only used if "ptr" is NULL, otherwise it is + * ignored. + * + * @param[in] ctx The parent context used if ptr is NULL. + * + * @param[in] ptr The chunk to be resized. + * + * @param[in] type The type of the array element inside ptr. + * + * @param[in] count The intended number of array elements. + * + * @return The new array, NULL on error. The call will fail either + * due to a lack of memory, or because the pointer has more + * than one parent (see talloc_reference()). + */ +void *talloc_realloc(const void *ctx, void *ptr, #type, size_t count); +#else +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +#endif + +#ifdef DOXYGEN +/** + * @brief Untyped realloc to change the size of a talloc array. + * + * The macro is useful when the type is not known so the typesafe + * talloc_realloc() cannot be used. + * + * @param[in] ctx The parent context used if 'ptr' is NULL. + * + * @param[in] ptr The chunk to be resized. + * + * @param[in] size The new chunk size. + * + * @return The new array, NULL on error. + */ +void *talloc_realloc_size(const void *ctx, void *ptr, size_t size); +#else +#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +#endif + +/** + * @brief Provide a function version of talloc_realloc_size. + * + * This is a non-macro version of talloc_realloc(), which is useful as + * libraries sometimes want a ralloc function pointer. A realloc() + * implementation encapsulates the functionality of malloc(), free() and + * realloc() in one call, which is why it is useful to be able to pass around + * a single function pointer. + * + * @param[in] context The parent context used if ptr is NULL. + * + * @param[in] ptr The chunk to be resized. + * + * @param[in] size The new chunk size. + * + * @return The new chunk, NULL on error. + */ +void *talloc_realloc_fn(const void *context, void *ptr, size_t size); + +/* @} ******************************************************************/ + +/** + * @defgroup talloc_string The talloc string functions. + * @ingroup talloc + * + * talloc string allocation and manipulation functions. + * @{ + */ + +/** + * @brief Duplicate a string into a talloc chunk. + * + * This function is equivalent to: + * + * @code + * ptr = talloc_size(ctx, strlen(p)+1); + * if (ptr) memcpy(ptr, p, strlen(p)+1); + * @endcode + * + * This functions sets the name of the new pointer to the passed + * string. This is equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] p The string you want to duplicate. + * + * @return The duplicated string, NULL on error. + */ +char *talloc_strdup(const void *t, const char *p); + +/** + * @brief Append a string to given string and duplicate the result. + * + * @param[in] s The destination to append to. + * + * @param[in] a The string you want to append. + * + * @return The duplicated string, NULL on error. + * + * @see talloc_strdup() + */ +char *talloc_strdup_append(char *s, const char *a); + +/** + * @brief Append a string to a given buffer and duplicate the result. + * + * @param[in] s The destination buffer to append to. + * + * @param[in] a The string you want to append. + * + * @return The duplicated string, NULL on error. + * + * @see talloc_strdup() + */ +char *talloc_strdup_append_buffer(char *s, const char *a); + +/** + * @brief Duplicate a length-limited string into a talloc chunk. + * + * This function is the talloc equivalent of the C library function strndup(3). + * + * This functions sets the name of the new pointer to the passed string. This is + * equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] p The string you want to duplicate. + * + * @param[in] n The maximum string length to duplicate. + * + * @return The duplicated string, NULL on error. + */ +char *talloc_strndup(const void *t, const char *p, size_t n); + +/** + * @brief Append at most n characters of a string to given string and duplicate + * the result. + * + * @param[in] s The destination string to append to. + * + * @param[in] a The source string you want to append. + * + * @param[in] n The number of characters you want to append from the + * string. + * + * @return The duplicated string, NULL on error. + * + * @see talloc_strndup() + */ +char *talloc_strndup_append(char *s, const char *a, size_t n); + +/** + * @brief Append at most n characters of a string to given buffer and duplicate + * the result. + * + * @param[in] s The destination buffer to append to. + * + * @param[in] a The source string you want to append. + * + * @param[in] n The number of characters you want to append from the + * string. + * + * @return The duplicated string, NULL on error. + * + * @see talloc_strndup() + */ +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); + +/** + * @brief Format a string given a va_list. + * + * This function is the talloc equivalent of the C library function + * vasprintf(3). + * + * This functions sets the name of the new pointer to the new string. This is + * equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] fmt The format string. + * + * @param[in] ap The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + */ +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +/** + * @brief Format a string given a va_list and append it to the given destination + * string. + * + * @param[in] s The destination string to append to. + * + * @param[in] fmt The format string. + * + * @param[in] ap The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + * + * @see talloc_vasprintf() + */ +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +/** + * @brief Format a string given a va_list and append it to the given destination + * buffer. + * + * @param[in] s The destination buffer to append to. + * + * @param[in] fmt The format string. + * + * @param[in] ap The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + * + * @see talloc_vasprintf() + */ +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +/** + * @brief Format a string. + * + * This function is the talloc equivalent of the C library function asprintf(3). + * + * This functions sets the name of the new pointer to the new string. This is + * equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] t The talloc context to hang the result off. + * + * @param[in] fmt The format string. + * + * @param[in] ... The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + */ +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +/** + * @brief Append a formatted string to another string. + * + * This function appends the given formatted string to the given string. Use + * this variant when the string in the current talloc buffer may have been + * truncated in length. + * + * This functions sets the name of the new pointer to the new + * string. This is equivalent to: + * + * @code + * talloc_set_name_const(ptr, ptr) + * @endcode + * + * @param[in] s The string to append to. + * + * @param[in] fmt The format string. + * + * @param[in] ... The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + */ +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +/** + * @brief Append a formatted string to another string. + * + * @param[in] s The string to append to + * + * @param[in] fmt The format string. + * + * @param[in] ... The parameters used to fill fmt. + * + * @return The formatted string, NULL on error. + */ +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +/* @} ******************************************************************/ + +/** + * @defgroup talloc_debug The talloc debugging support functions + * @ingroup talloc + * + * To aid memory debugging, talloc contains routines to inspect the currently + * allocated memory hierarchy. + * + * @{ + */ + +/** + * @brief Walk a complete talloc hierarchy. + * + * This provides a more flexible reports than talloc_report(). It + * will recursively call the callback for the entire tree of memory + * referenced by the pointer. References in the tree are passed with + * is_ref = 1 and the pointer that is referenced. + * + * You can pass NULL for the pointer, in which case a report is + * printed for the top level memory context, but only if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() + * has been called. + * + * The recursion is stopped when depth >= max_depth. + * max_depth = -1 means only stop at leaf nodes. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] depth Internal parameter to control recursion. Call with 0. + * + * @param[in] max_depth Maximum recursion level. + * + * @param[in] callback Function to be called on every chunk. + * + * @param[in] private_data Private pointer passed to callback. + */ +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data); + +/** + * @brief Print a talloc hierarchy. + * + * This provides a more flexible reports than talloc_report(). It + * will let you specify the depth and max_depth. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] depth Internal parameter to control recursion. Call with 0. + * + * @param[in] max_depth Maximum recursion level. + * + * @param[in] f The file handle to print to. + */ +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); + +/** + * @brief Print a summary report of all memory used by ptr. + * + * This provides a more detailed report than talloc_report(). It will + * recursively print the entire tree of memory referenced by the + * pointer. References in the tree are shown by giving the name of the + * pointer that is referenced. + * + * You can pass NULL for the pointer, in which case a report is printed + * for the top level memory context, but only if + * talloc_enable_leak_report() or talloc_enable_leak_report_full() has + * been called. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] f The file handle to print to. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * fprintf(stderr, "Dumping memory tree for a:\n"); + * talloc_report_full(a, stderr); + * @endcode + * + * @see talloc_report() + */ +void talloc_report_full(const void *ptr, FILE *f); + +/** + * @brief Print a summary report of all memory used by ptr. + * + * This function prints a summary report of all memory used by ptr. One line of + * report is printed for each immediate child of ptr, showing the total memory + * and number of blocks used by that child. + * + * You can pass NULL for the pointer, in which case a report is printed + * for the top level memory context, but only if talloc_enable_leak_report() + * or talloc_enable_leak_report_full() has been called. + * + * @param[in] ptr The talloc chunk. + * + * @param[in] f The file handle to print to. + * + * Example: + * @code + * unsigned int *a, *b; + * a = talloc(NULL, unsigned int); + * b = talloc(a, unsigned int); + * fprintf(stderr, "Summary of memory tree for a:\n"); + * talloc_report(a, stderr); + * @endcode + * + * @see talloc_report_full() + */ +void talloc_report(const void *ptr, FILE *f); + +/** + * @brief Enable tracking the use of NULL memory contexts. + * + * This enables tracking of the NULL memory context without enabling leak + * reporting on exit. Useful for when you want to do your own leak + * reporting call via talloc_report_null_full(); + */ +void talloc_enable_null_tracking(void); + +/** + * @brief Enable tracking the use of NULL memory contexts. + * + * This enables tracking of the NULL memory context without enabling leak + * reporting on exit. Useful for when you want to do your own leak + * reporting call via talloc_report_null_full(); + */ +void talloc_enable_null_tracking_no_autofree(void); + +/** + * @brief Disable tracking of the NULL memory context. + * + * This disables tracking of the NULL memory context. + */ +void talloc_disable_null_tracking(void); + +/** + * @brief Enable leak report when a program exits. + * + * This enables calling of talloc_report(NULL, stderr) when the program + * exits. In Samba4 this is enabled by using the --leak-report command + * line option. + * + * For it to be useful, this function must be called before any other + * talloc function as it establishes a "null context" that acts as the + * top of the tree. If you don't call this function first then passing + * NULL to talloc_report() or talloc_report_full() won't give you the + * full tree printout. + * + * Here is a typical talloc report: + * + * @code + * talloc report on 'null_context' (total 267 bytes in 15 blocks) + * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + * iconv(UTF8,CP850) contains 42 bytes in 2 blocks + * libcli/auth/spnego_parse.c:55 contains 31 bytes in 2 blocks + * iconv(CP850,UTF8) contains 42 bytes in 2 blocks + * iconv(UTF8,UTF-16LE) contains 45 bytes in 2 blocks + * iconv(UTF-16LE,UTF8) contains 45 bytes in 2 blocks + * @endcode + */ +void talloc_enable_leak_report(void); + +/** + * @brief Enable full leak report when a program exits. + * + * This enables calling of talloc_report_full(NULL, stderr) when the + * program exits. In Samba4 this is enabled by using the + * --leak-report-full command line option. + * + * For it to be useful, this function must be called before any other + * talloc function as it establishes a "null context" that acts as the + * top of the tree. If you don't call this function first then passing + * NULL to talloc_report() or talloc_report_full() won't give you the + * full tree printout. + * + * Here is a typical full report: + * + * @code + * full talloc report on 'root' (total 18 bytes in 8 blocks) + * p1 contains 18 bytes in 7 blocks (ref 0) + * r1 contains 13 bytes in 2 blocks (ref 0) + * reference to: p2 + * p2 contains 1 bytes in 1 blocks (ref 1) + * x3 contains 1 bytes in 1 blocks (ref 0) + * x2 contains 1 bytes in 1 blocks (ref 0) + * x1 contains 1 bytes in 1 blocks (ref 0) + * @endcode + */ +void talloc_enable_leak_report_full(void); + +/* @} ******************************************************************/ + +void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); +void talloc_set_log_fn(void (*log_fn)(const char *message)); +void talloc_set_log_stderr(void); + +#if TALLOC_DEPRECATED +#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) +#define talloc_p(ctx, type) talloc(ctx, type) +#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) +#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#define talloc_destroy(ctx) talloc_free(ctx) +#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) +#endif + +#ifndef TALLOC_MAX_DEPTH +#define TALLOC_MAX_DEPTH 10000 +#endif + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/include/atalk/tdb.h b/include/atalk/tdb.h new file mode 100644 index 0000000..b13ee35 --- /dev/null +++ b/include/atalk/tdb.h @@ -0,0 +1,181 @@ +#ifndef USE_BUILTIN_TDB +# include +#else +# ifndef __TDB_H__ +# define __TDB_H__ + +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2004 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* flags to tdb_store() */ +#define TDB_REPLACE 1 /* Unused */ +#define TDB_INSERT 2 /* Don't overwrite an existing entry */ +#define TDB_MODIFY 3 /* Don't create an existing entry */ + +/* flags for tdb_open() */ +#define TDB_DEFAULT 0 /* just a readability place holder */ +#define TDB_CLEAR_IF_FIRST 1 +#define TDB_INTERNAL 2 /* don't store on disk */ +#define TDB_NOLOCK 4 /* don't do any locking */ +#define TDB_NOMMAP 8 /* don't use mmap */ +#define TDB_CONVERT 16 /* convert endian (internal use) */ +#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */ +#define TDB_NOSYNC 64 /* don't use synchronous transactions */ +#define TDB_SEQNUM 128 /* maintain a sequence number */ +#define TDB_VOLATILE 256 /* Activate the per-hashchain freelist, default 5 */ +#define TDB_ALLOW_NESTING 512 /* Allow transactions to nest */ +#define TDB_DISALLOW_NESTING 1024 /* Disallow transactions to nest */ + +/* error codes */ +enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, + TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, + TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY, + TDB_ERR_NESTING}; + +/* debugging uses one of the following levels */ +enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR, + TDB_DEBUG_WARNING, TDB_DEBUG_TRACE}; + +typedef struct TDB_DATA { + unsigned char *dptr; + size_t dsize; +} TDB_DATA; + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* this is the context structure that is returned from a db open */ +typedef struct tdb_context TDB_CONTEXT; + +typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *); +typedef void (*tdb_log_func)(struct tdb_context *, enum tdb_debug_level, const char *, ...) PRINTF_ATTRIBUTE(3, 4); +typedef unsigned int (*tdb_hash_func)(TDB_DATA *key); + +struct tdb_logging_context { + tdb_log_func log_fn; + void *log_private; +}; + +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode); +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn); +void tdb_set_max_dead(struct tdb_context *tdb, int max_dead); + +int tdb_reopen(struct tdb_context *tdb); +int tdb_reopen_all(int parent_longlived); +void tdb_set_logging_function(struct tdb_context *tdb, const struct tdb_logging_context *log_ctx); +enum TDB_ERROR tdb_error(struct tdb_context *tdb); +const char *tdb_errorstr(struct tdb_context *tdb); +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); +int tdb_delete(struct tdb_context *tdb, TDB_DATA key); +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag); +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf); +int tdb_close(struct tdb_context *tdb); +TDB_DATA tdb_firstkey(struct tdb_context *tdb); +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key); +int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *); +int tdb_exists(struct tdb_context *tdb, TDB_DATA key); +int tdb_lockall(struct tdb_context *tdb); +int tdb_lockall_nonblock(struct tdb_context *tdb); +int tdb_unlockall(struct tdb_context *tdb); +int tdb_lockall_read(struct tdb_context *tdb); +int tdb_lockall_read_nonblock(struct tdb_context *tdb); +int tdb_unlockall_read(struct tdb_context *tdb); +int tdb_lockall_mark(struct tdb_context *tdb); +int tdb_lockall_unmark(struct tdb_context *tdb); +const char *tdb_name(struct tdb_context *tdb); +int tdb_fd(struct tdb_context *tdb); +tdb_log_func tdb_log_fn(struct tdb_context *tdb); +void *tdb_get_logging_private(struct tdb_context *tdb); +int tdb_transaction_start(struct tdb_context *tdb); +int tdb_transaction_prepare_commit(struct tdb_context *tdb); +int tdb_transaction_commit(struct tdb_context *tdb); +int tdb_transaction_cancel(struct tdb_context *tdb); +int tdb_transaction_recover(struct tdb_context *tdb); +int tdb_get_seqnum(struct tdb_context *tdb); +int tdb_hash_size(struct tdb_context *tdb); +size_t tdb_map_size(struct tdb_context *tdb); +int tdb_get_flags(struct tdb_context *tdb); +void tdb_add_flags(struct tdb_context *tdb, unsigned flag); +void tdb_remove_flags(struct tdb_context *tdb, unsigned flag); +void tdb_enable_seqnum(struct tdb_context *tdb); +void tdb_increment_seqnum_nonblock(struct tdb_context *tdb); +int tdb_check(struct tdb_context *tdb, + int (*check) (TDB_DATA key, TDB_DATA data, void *private_data), + void *private_data); + +/* Low level locking functions: use with care */ +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key); + +void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *sigptr); + +/* wipe and repack */ +int tdb_wipe_all(struct tdb_context *tdb); +int tdb_repack(struct tdb_context *tdb); + +/* Debug functions. Not used in production. */ +void tdb_dump_all(struct tdb_context *tdb); +int tdb_printfreelist(struct tdb_context *tdb); +int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries); +int tdb_freelist_size(struct tdb_context *tdb); + +extern TDB_DATA tdb_null; + +#ifdef __cplusplus +} +#endif + +# endif /* tdb.h */ +#endif /* USE_BUILTIN_TDB */ diff --git a/include/atalk/uam.h b/include/atalk/uam.h new file mode 100644 index 0000000..d2890e7 --- /dev/null +++ b/include/atalk/uam.h @@ -0,0 +1,101 @@ +/* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + */ + +#ifndef UAM_H +#define UAM_H 1 + +#include +#include + +#ifdef TRU64 +#include +#include +#endif /* TRU64 */ + +/* just a label for exported bits */ +#ifndef UAM_MODULE_EXPORT +#define UAM_MODULE_EXPORT +#endif + +/* type of uam */ +#define UAM_MODULE_SERVER 1 +#define UAM_MODULE_CLIENT 2 + +/* in case something drastic has to change */ +#define UAM_MODULE_VERSION 1 + +/* things for which we can have uams */ +#define UAM_SERVER_LOGIN (1 << 0) +#define UAM_SERVER_CHANGEPW (1 << 1) +#define UAM_SERVER_PRINTAUTH (1 << 2) +#define UAM_SERVER_LOGIN_EXT (1 << 3) + +/* options */ +#define UAM_OPTION_USERNAME (1 << 0) /* get space for username */ +#define UAM_OPTION_GUEST (1 << 1) /* get guest user */ +#define UAM_OPTION_PASSWDOPT (1 << 2) /* get the password file */ +#define UAM_OPTION_SIGNATURE (1 << 3) /* get server signature */ +#define UAM_OPTION_RANDNUM (1 << 4) /* request a random number */ +#define UAM_OPTION_HOSTNAME (1 << 5) /* get host name */ +#define UAM_OPTION_COOKIE (1 << 6) /* cookie handle */ +#define UAM_OPTION_CLIENTNAME (1 << 8) /* get client IP address */ +#define UAM_OPTION_KRB5SERVICE (1 << 9) /* service name for krb5 principal */ +#define UAM_OPTION_MACCHARSET (1 << 10) /* mac charset handle */ +#define UAM_OPTION_UNIXCHARSET (1 << 11) /* unix charset handle */ +#define UAM_OPTION_SESSIONINFO (1 << 12) /* unix charset handle */ +#define UAM_OPTION_KRB5REALM (1 << 13) /* krb realm */ +#define UAM_OPTION_FQDN (1 << 14) /* fully qualified name */ + +/* some password options. you pass these in the length parameter and + * get back the corresponding option. not all of these are implemented. */ +#define UAM_PASSWD_FILENAME (1 << 0) +#define UAM_PASSWD_MINLENGTH (1 << 1) +#define UAM_PASSWD_EXPIRETIME (1 << 3) /* not implemented yet. */ + +/* max lenght of username */ +#define UAM_USERNAMELEN 255 + +/* i'm doing things this way because os x server's dynamic linker + * support is braindead. it also allows me to do a little versioning. */ +struct uam_export { + int uam_type, uam_version; + int (*uam_setup)(void *, const char *); + void (*uam_cleanup)(void); +}; + +#define SESSIONKEY_LEN 64 +#define SESSIONTOKEN_LEN 8 + +struct session_info { + void *sessionkey; /* random session key */ + size_t sessionkey_len; + void *cryptedkey; /* kerberos/gssapi crypted key */ + size_t cryptedkey_len; + void *sessiontoken; /* session token sent to the client on FPGetSessionToken*/ + size_t sessiontoken_len; + void *clientid; /* whole buffer cotaining eg idlen, id and boottime */ + size_t clientid_len; +}; + +/* register and unregister uams with these functions */ +extern UAM_MODULE_EXPORT int uam_register (const int, const char *, const char *, ...); +extern UAM_MODULE_EXPORT void uam_unregister (const int, const char *); + +/* helper functions */ +extern UAM_MODULE_EXPORT struct passwd *uam_getname (void*, char *, const int); +extern UAM_MODULE_EXPORT int uam_checkuser (const struct passwd *); + +/* afp helper functions */ +extern UAM_MODULE_EXPORT int uam_afp_read (void *, char *, size_t *, + int (*)(void *, void *, const int)); +extern UAM_MODULE_EXPORT int uam_afpserver_option (void *, const int, void *, size_t *); + +#ifdef TRU64 +extern void uam_afp_getcmdline (int *, char ***); +extern int uam_sia_validate_user (sia_collect_func_t *, int, char **, + char *, char *, char *, int, char *, + char *); +#endif /* TRU64 */ + +#endif diff --git a/include/atalk/unicode.h b/include/atalk/unicode.h new file mode 100644 index 0000000..75a970b --- /dev/null +++ b/include/atalk/unicode.h @@ -0,0 +1,152 @@ +#ifndef _ATALK_UNICODE_H +#define _ATALK_UNICODE_H 1 + +#include +#include +#include + +#define ucs2_t uint16_t + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif /* ! MIN */ + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif /* ! MIN */ + +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) + +#ifndef EILSEQ +#define EILSEQ 84 /* Illegal byte sequence. */ +#endif + +/* generic iconv conversion structure */ +typedef struct { + size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + size_t (*pull)(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + size_t (*push)(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + void *cd_direct, *cd_pull, *cd_push; + char *from_name, *to_name; +} *atalk_iconv_t; + +#define CHARSET_CLIENT 1 +#define CHARSET_VOLUME 2 +#define CHARSET_PRECOMPOSED 4 +#define CHARSET_DECOMPOSED 8 +#define CHARSET_MULTIBYTE 16 +#define CHARSET_WIDECHAR 32 +#define CHARSET_ICONV 64 + +#define IGNORE_CHAR '_' + +/* conversion flags */ +#define CONV_IGNORE (1<<0) /* return the first convertable characters. */ +#define CONV_ESCAPEHEX (1<<1) /* escape unconvertable chars with :[UCS2HEX], */ + /* also escape '/'. Escape ':' if also CONV_ALLOW_COLON, */ + /* else ':' raises EILSEQ */ +#define CONV_ESCAPEDOTS (1<<2) /* escape leading dots with :2600 */ +#define CONV_UNESCAPEHEX (1<<3) +#define CONV_TOUPPER (1<<4) /* convert to UPPERcase */ +#define CONV_TOLOWER (1<<5) /* convert to lowercase */ +#define CONV_PRECOMPOSE (1<<6) /* precompose */ +#define CONV_DECOMPOSE (1<<7) /* precompose */ +#define CONV_FORCE (1<<8) /* force convertion */ +#define CONV__EILSEQ (1<<9) /* ignore EILSEQ, replace with IGNORE_CHAR (try USC2) */ + +/* conversion return flags */ +#define CONV_REQMANGLE (1<<14) /* mangling of returned name is required */ +#define CONV_REQESCAPE (1<<15) /* espace unconvertable chars with :[UCS2HEX] */ + +/* this defines the charset types used in samba */ +typedef enum {CH_UCS2=0, CH_UTF8=1, CH_MAC=2, CH_UNIX=3, CH_UTF8_MAC=4} charset_t; + +#define NUM_CHARSETS 5 + +/* + * for each charset we have a function that pulls from that charset to + * a ucs2 buffer, and a function that pushes to a ucs2 buffer + */ + +struct charset_functions { + const char *name; + const long kTextEncoding; + size_t (*pull)(void *, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + size_t (*push)(void *, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + uint32_t flags; + const char *iname; + struct charset_functions *prev, *next; +}; + +/* from iconv.c */ +extern atalk_iconv_t atalk_iconv_open (const char *, const char *); +extern size_t atalk_iconv (atalk_iconv_t, const char **, size_t *, char **, size_t *); +extern int atalk_iconv_close (atalk_iconv_t); +extern struct charset_functions *find_charset_functions (const char *); +extern int atalk_register_charset (struct charset_functions *); + +/* from utf16_case.c */ +extern ucs2_t toupper_w (ucs2_t); +extern uint32_t toupper_sp (uint32_t); +extern ucs2_t tolower_w (ucs2_t); +extern uint32_t tolower_sp (uint32_t); + +/* from util_unistr.c */ +extern int strupper_w (ucs2_t *); +extern int strlower_w (ucs2_t *); +extern int islower_w (ucs2_t); +extern int isupper_w (ucs2_t); +extern size_t strlen_w (const ucs2_t *); +extern size_t strnlen_w (const ucs2_t *, size_t); +extern ucs2_t* strchr_w (const ucs2_t *, ucs2_t); +extern ucs2_t *strcasechr_w (const ucs2_t *s, ucs2_t c); +extern int strcmp_w (const ucs2_t *, const ucs2_t *); +extern int strncmp_w (const ucs2_t *, const ucs2_t *, size_t); +extern int strcasecmp_w (const ucs2_t *, const ucs2_t *); +extern int strncasecmp_w (const ucs2_t *, const ucs2_t *, size_t); +extern ucs2_t *strstr_w (const ucs2_t *s, const ucs2_t *ins); +extern ucs2_t *strcasestr_w (const ucs2_t *, const ucs2_t *); +extern ucs2_t *strndup_w (const ucs2_t *, size_t); +extern ucs2_t *strdup_w (const ucs2_t *); +extern ucs2_t *strncpy_w (ucs2_t *, const ucs2_t *, const size_t); +extern ucs2_t *strncat_w (ucs2_t *, const ucs2_t *, const size_t); +extern ucs2_t *strcat_w (ucs2_t *, const ucs2_t *); +extern size_t precompose_w (ucs2_t *, size_t, ucs2_t *,size_t *); +extern size_t decompose_w (ucs2_t *, size_t, ucs2_t *,size_t *); +extern size_t utf8_charlen ( char* ); +extern size_t utf8_strlen_validate ( char *); + +/* from charcnv.c */ +extern int set_charset_name(charset_t, const char *); +extern void free_charset_names(void); +extern void init_iconv (void); +extern size_t convert_string (charset_t, charset_t, void const *, size_t, void *, size_t); +extern size_t convert_string_allocate (charset_t, charset_t, void const *, size_t, char **); +extern size_t utf8_strupper (const char *, size_t, char *, size_t); +extern size_t utf8_strlower (const char *, size_t, char *, size_t); +extern size_t unix_strupper (const char *, size_t, char *, size_t); +extern size_t unix_strlower (const char *, size_t, char *, size_t); +extern size_t charset_strupper (charset_t, const char *, size_t, char *, size_t); +extern size_t charset_strlower (charset_t, const char *, size_t, char *, size_t); + +extern size_t charset_to_ucs2_allocate (charset_t, ucs2_t **dest, const char *src); +extern size_t charset_to_utf8_allocate (charset_t, char **dest, const char *src); +extern size_t ucs2_to_charset_allocate (charset_t, char **dest, const ucs2_t *src); +extern size_t utf8_to_charset_allocate (charset_t, char **dest, const char *src); +extern size_t ucs2_to_charset (charset_t, const ucs2_t *src, char *dest, size_t); + +extern size_t convert_charset (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *); + +extern size_t charset_precompose ( charset_t, char *, size_t, char *, size_t); +extern size_t charset_decompose ( charset_t, char *, size_t, char *, size_t); +extern size_t utf8_precompose ( char *, size_t, char *, size_t); +extern size_t utf8_decompose ( char *, size_t, char *, size_t); + +extern charset_t add_charset (const char* name); + +#endif /* _ATALK_UNICODE_H */ diff --git a/include/atalk/unix.h b/include/atalk/unix.h new file mode 100644 index 0000000..c12bf5b --- /dev/null +++ b/include/atalk/unix.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifndef ATALK_UNIX_H +#define ATALK_UNIX_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#define NETATALK_DIOSZ_STACK 65536 +#define NETATALK_DIOSZ_HEAP (1024*1024) + +struct vol; + +/* vfs/unix.c */ +extern int netatalk_unlink(const char *name); +extern int netatalk_unlinkat(int dirfd, const char *name); +extern int statat(int dirfd, const char *path, struct stat *st); +extern DIR *opendirat(int dirfd, const char *path); + +/* rmdir ENOENT not an error */ +extern int netatalk_rmdir(int dirfd, const char *name); +extern int netatalk_rmdir_all_errors(int dirfd, const char *name); + +extern int setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat *st); +extern int dir_rx_set(mode_t mode); +extern int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath); +extern int copy_file(int sfd, const char *src, const char *dst, mode_t mode); +extern int copy_file_fd(int sfd, int dfd); +extern int copy_ea(const char *ea, int sfd, const char *src, const char *dst, mode_t mode); + +extern void become_root(void); +extern void unbecome_root(void); +extern int gmem(gid_t gid, int ngroups, gid_t *groups); +extern int set_groups(AFPObj *obj, struct passwd *pwd); +extern const char *print_groups(int ngroups, gid_t *groups); +#endif /* ATALK_UNIX_H */ diff --git a/include/atalk/util.h b/include/atalk/util.h new file mode 100644 index 0000000..94aab1a --- /dev/null +++ b/include/atalk/util.h @@ -0,0 +1,227 @@ +/*! + * @file + * Netatalk utility functions + * + * Utility functions for these areas: \n + * * sockets \n + * * locking \n + * * misc UNIX function wrappers, eg for getcwd + */ + +#ifndef _ATALK_UTIL_H +#define _ATALK_UTIL_H 1 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* exit error codes */ +#define EXITERR_CLNT 1 /* client related error */ +#define EXITERR_CONF 2 /* error in config files/cmd line parameters */ +#define EXITERR_SYS 3 /* local system error */ +#define EXITERR_CLOSED 4 /* connection was immediately closed after TCP handshake */ + +/* Print a SBT and exit */ +#define AFP_PANIC(why) \ + do { \ + netatalk_panic(why); \ + abort(); \ + } while(0); + +/* LOG assert errors */ +#ifndef NDEBUG +#define AFP_ASSERT(b) \ + do { \ + if (!(b)) { \ + AFP_PANIC(#b); \ + } \ + } while(0); +#else +#define AFP_ASSERT(b) +#endif /* NDEBUG */ + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define STRCMP(a,b,c) (strcmp(a,c) b 0) +#define ZERO_STRUCT(a) memset(&(a), 0, sizeof(a)) +#define ZERO_STRUCTP(a) memset((a), 0, sizeof(a)) +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? a : b) +#endif +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? a : b) +#endif + +#ifdef WORDS_BIGENDIAN +#define hton64(x) (x) +#define ntoh64(x) (x) +#else +#define hton64(x) ((uint64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \ + (uint64_t) ((htonl(x) & 0xffffffffLL) << 32)) +#define ntoh64(x) (hton64(x)) +#endif + +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) +#endif + +#ifdef WITH_SENDFILE +extern ssize_t sys_sendfile (int __out_fd, int __in_fd, off_t *__offset,size_t __count); +#endif + +extern const int _diacasemap[], _dialowermap[]; + +extern char **getifacelist(void); +extern void freeifacelist(char **); + +#define diatolower(x) _dialowermap[(unsigned char) (x)] +#define diatoupper(x) _diacasemap[(unsigned char) (x)] +extern void bprint (char *, int); +extern int strdiacasecmp (const char *, const char *); +extern int strndiacasecmp (const char *, const char *, size_t); +extern pid_t server_lock (char * /*program*/, char * /*file*/, int /*debug*/); +extern int check_lockfile (const char *program, const char *pidfile); +extern int create_lockfile(const char *program, const char *pidfile); +extern void fault_setup (void (*fn)(void *)); +extern void netatalk_panic(const char *why); +#define server_unlock(x) (unlink(x)) + +#ifndef HAVE_DLFCN_H +extern void *mod_open (const char *); +extern void *mod_symbol (void *, const char *); +extern void mod_close (void *); +#define mod_error() "" +#else /* ! HAVE_DLFCN_H */ +#include + +#ifndef RTLD_NOW +#define RTLD_NOW 1 +#endif /* ! RTLD_NOW */ + +/* NetBSD doesn't like RTLD_NOW for dlopen (it fails). Use RTLD_LAZY. + * OpenBSD currently does not use the second arg for dlopen(). For + * future compatibility we define DL_LAZY */ +#ifdef __NetBSD__ +#define mod_open(a) dlopen(a, RTLD_LAZY) +#elif defined(__OpenBSD__) +#define mod_open(a) dlopen(a, DL_LAZY) +#else /* ! __NetBSD__ && ! __OpenBSD__ */ +#define mod_open(a) dlopen(a, RTLD_NOW) +#endif /* __NetBSD__ */ + +#ifndef DLSYM_PREPEND_UNDERSCORE +#define mod_symbol(a, b) dlsym(a, b) +#else /* ! DLSYM_PREPEND_UNDERSCORE */ +extern void *mod_symbol (void *, const char *); +#endif /* ! DLSYM_PREPEND_UNDERSCORE */ +#define mod_error() dlerror() +#define mod_close(a) dlclose(a) +#endif /* ! HAVE_DLFCN_H */ + +#ifndef strequal +#define strequal(a,b) (strcmp((a),(b)) == 0) +#endif + +/****************************************************************** + * locking.c + ******************************************************************/ + +extern int lock_reg(int fd, int cmd, int type, off_t offest, int whence, off_t len); +#define read_lock(fd, offset, whence, len) \ + lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len)) +#define write_lock(fd, offset, whence, len) \ + lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len)) +#define unlock(fd, offset, whence, len) \ + lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len)) + +/****************************************************************** + * socket.c + ******************************************************************/ + +extern int setnonblock(int fd, int cmd); +extern ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, int timeout); +extern ssize_t writet(int socket, void *data, const size_t length, int setnonblocking, int timeout); +extern const char *getip_string(const struct sockaddr *sa); +extern unsigned int getip_port(const struct sockaddr *sa); +extern void apply_ip_mask(struct sockaddr *ai, int maskbits); +extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2); +extern int tokenize_ip_port(const char *ipurl, char **address, char **port); + +/* Structures and functions dealing with dynamic pollfd arrays */ + +enum asev_fdtype {IPC_FD, LISTEN_FD}; + +/** + * atalk socket event data + **/ +struct asev_data { + enum asev_fdtype fdtype; /* IPC fd or listening socket fd */ + void *private; /* pointer to AFPconfig for listening socket and * + * pointer to afp_child_t for IPC fd */ +}; + +/** + * atalk socket event + **/ +struct asev { + struct pollfd *fdset; /* struct pollfd array for poll() */ + struct asev_data *data; /* associated array of data */ + int max; + int used; +}; + +extern struct asev *asev_init(int max); +extern bool asev_add_fd(struct asev *sev, int fd, enum asev_fdtype fdtype, void *private); +extern bool asev_del_fd(struct asev *sev, int fd); + +extern int send_fd(int socket, int fd); +extern int recv_fd(int fd, int nonblocking); + +/****************************************************************** + * unix.c + *****************************************************************/ + +extern const char *getcwdpath(void); +extern const char *fullpathname(const char *); +extern char *stripped_slashes_basename(char *p); +extern void randombytes(void *buf, int n); +extern int daemonize(int nochdir, int noclose); +extern int run_cmd(const char *cmd, char **cmd_argv); +extern char *realpath_safe(const char *path); +extern const char *basename_safe(const char *path); +extern char *strtok_quote (char *s, const char *delim); + +extern int ochdir(const char *dir, int options); +extern int ostat(const char *path, struct stat *buf, int options); +extern int ostatat(int dirfd, const char *path, struct stat *st, int options); +extern int ochown(const char *path, uid_t owner, gid_t group, int options); +extern int ochmod(char *path, mode_t mode, const struct stat *st, int options); + +/****************************************************************** + * cnid.c + *****************************************************************/ + +extern bstring rel_path_in_vol(const char *path, const char *volpath); +extern cnid_t cnid_for_path(struct _cnid_db *cdb, const char *volpath, const char *path, cnid_t *did); + +/****************************************************************** + * cnid.c + *****************************************************************/ + +extern void initline (int, char *); +extern int parseline (int, char *); + +#endif /* _ATALK_UTIL_H */ diff --git a/include/atalk/uuid.h b/include/atalk/uuid.h new file mode 100644 index 0000000..4c9b3c9 --- /dev/null +++ b/include/atalk/uuid.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. + */ + +#ifndef AFP_UUID_H +#define AFP_UUID_H + +#define UUID_BINSIZE 16 + +typedef const unsigned char *uuidp_t; +typedef unsigned char atalk_uuid_t[UUID_BINSIZE]; + +typedef enum {UUID_USER = 1, + UUID_GROUP = 2, + UUID_ENOENT = 4} /* used as bit flag */ + uuidtype_t; +#define UUIDTYPESTR_MASK 3 +extern char *uuidtype[]; + +/******************************************************** + * Interface + ********************************************************/ + +extern int getuuidfromname( const char *name, uuidtype_t type, unsigned char *uuid); +extern int getnamefromuuid( const unsigned char *uuid, char **name, uuidtype_t *type); +extern void localuuid_from_id(unsigned char *buf, uuidtype_t type, unsigned int id); +extern const char *uuid_bin2string(const unsigned char *uuid); +extern void uuid_string2bin( const char *uuidstring, unsigned char *uuid); +extern void uuidcache_dump(void); + +#endif /* AFP_UUID_H */ diff --git a/include/atalk/vfs.h b/include/atalk/vfs.h new file mode 100644 index 0000000..580c22b --- /dev/null +++ b/include/atalk/vfs.h @@ -0,0 +1,127 @@ +/* + Copyright (c) 2004 Didier Gautheron + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + vfs layer for afp +*/ + +#ifndef ATALK_VFS_H +#define ATALK_VFS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#define VFS_FUNC_ARGS_VALIDUPATH const struct vol *vol, const char *name +#define VFS_FUNC_VARS_VALIDUPATH vol, name + +#define VFS_FUNC_ARGS_CHOWN const struct vol *vol, const char *path, uid_t uid, gid_t gid +#define VFS_FUNC_VARS_CHOWN vol, path, uid, gid + +#define VFS_FUNC_ARGS_RENAMEDIR const struct vol *vol, int dirfd, const char *oldpath, const char *newpath +#define VFS_FUNC_VARS_RENAMEDIR vol, dirfd, oldpath, newpath + +#define VFS_FUNC_ARGS_DELETECURDIR const struct vol *vol +#define VFS_FUNC_VARS_DELETECURDIR vol + +#define VFS_FUNC_ARGS_SETFILEMODE const struct vol *vol, const char *name, mode_t mode, struct stat *st +#define VFS_FUNC_VARS_SETFILEMODE vol, name, mode, st + +#define VFS_FUNC_ARGS_SETDIRMODE const struct vol *vol, const char *name, mode_t mode, struct stat *st +#define VFS_FUNC_VARS_SETDIRMODE vol, name, mode, st + +#define VFS_FUNC_ARGS_SETDIRUNIXMODE const struct vol *vol, const char *name, mode_t mode, struct stat *st +#define VFS_FUNC_VARS_SETDIRUNIXMODE vol, name, mode, st + +#define VFS_FUNC_ARGS_SETDIROWNER const struct vol *vol, const char *name, uid_t uid, gid_t gid +#define VFS_FUNC_VARS_SETDIROWNER vol, name, uid, gid + +#define VFS_FUNC_ARGS_DELETEFILE const struct vol *vol, int dirfd, const char *file +#define VFS_FUNC_VARS_DELETEFILE vol, dirfd, file + +#define VFS_FUNC_ARGS_RENAMEFILE const struct vol *vol, int dirfd, const char *src, const char *dst +#define VFS_FUNC_VARS_RENAMEFILE vol, dirfd, src, dst + +#define VFS_FUNC_ARGS_COPYFILE const struct vol *vol, int sfd, const char *src, const char *dst +#define VFS_FUNC_VARS_COPYFILE vol, sfd, src, dst + +#ifdef HAVE_NFSV4_ACLS +#define VFS_FUNC_ARGS_ACL const struct vol *vol, const char *path, int cmd, int count, void *aces +#define VFS_FUNC_VARS_ACL vol, path, cmd, count, aces +#endif +#ifdef HAVE_POSIX_ACLS +#define VFS_FUNC_ARGS_ACL const struct vol *vol, const char *path, acl_type_t type, int count, acl_t acl +#define VFS_FUNC_VARS_ACL vol, path, type, count, acl +#endif + +#define VFS_FUNC_ARGS_REMOVE_ACL const struct vol *vol, const char *path, int dir +#define VFS_FUNC_VARS_REMOVE_ACL vol, path, dir + +#define VFS_FUNC_ARGS_EA_GETSIZE const struct vol * restrict vol, char * restrict rbuf, size_t * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname, int fd +#define VFS_FUNC_VARS_EA_GETSIZE vol, rbuf, rbuflen, uname, oflag, attruname, fd + +#define VFS_FUNC_ARGS_EA_GETCONTENT const struct vol * restrict vol, char * restrict rbuf, size_t * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname, int maxreply, int fd +#define VFS_FUNC_VARS_EA_GETCONTENT vol, rbuf, rbuflen, uname, oflag, attruname, maxreply, fd + +#define VFS_FUNC_ARGS_EA_LIST const struct vol * restrict vol, char * restrict attrnamebuf, size_t * restrict buflen, const char * restrict uname, int oflag, int fd +#define VFS_FUNC_VARS_EA_LIST vol, attrnamebuf, buflen, uname, oflag, fd + +#define VFS_FUNC_ARGS_EA_SET const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, const char * restrict ibuf, size_t attrsize, int oflag, int fd +#define VFS_FUNC_VARS_EA_SET vol, uname, attruname, ibuf, attrsize, oflag, fd + +#define VFS_FUNC_ARGS_EA_REMOVE const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, int oflag, int fd +#define VFS_FUNC_VARS_EA_REMOVE vol, uname, attruname, oflag, fd + +/* + * Forward declaration. We need it because of the circular inclusion of + * of vfs.h <-> volume.h. + */ +struct vol; + +struct vfs_ops { + int (*vfs_validupath) (VFS_FUNC_ARGS_VALIDUPATH); + int (*vfs_chown) (VFS_FUNC_ARGS_CHOWN); + int (*vfs_renamedir) (VFS_FUNC_ARGS_RENAMEDIR); + int (*vfs_deletecurdir) (VFS_FUNC_ARGS_DELETECURDIR); + int (*vfs_setfilmode) (VFS_FUNC_ARGS_SETFILEMODE); + int (*vfs_setdirmode) (VFS_FUNC_ARGS_SETDIRMODE); + int (*vfs_setdirunixmode)(VFS_FUNC_ARGS_SETDIRUNIXMODE); + int (*vfs_setdirowner) (VFS_FUNC_ARGS_SETDIROWNER); + int (*vfs_deletefile) (VFS_FUNC_ARGS_DELETEFILE); + int (*vfs_renamefile) (VFS_FUNC_ARGS_RENAMEFILE); + int (*vfs_copyfile) (VFS_FUNC_ARGS_COPYFILE); + +#ifdef HAVE_ACLS + /* ACLs */ + int (*vfs_acl) (VFS_FUNC_ARGS_ACL); + int (*vfs_remove_acl) (VFS_FUNC_ARGS_REMOVE_ACL); +#endif + + /* Extended Attributes */ + int (*vfs_ea_getsize) (VFS_FUNC_ARGS_EA_GETSIZE); + int (*vfs_ea_getcontent) (VFS_FUNC_ARGS_EA_GETCONTENT); + int (*vfs_ea_list) (VFS_FUNC_ARGS_EA_LIST); + int (*vfs_ea_set) (VFS_FUNC_ARGS_EA_SET); + int (*vfs_ea_remove) (VFS_FUNC_ARGS_EA_REMOVE); +}; + +extern void initvol_vfs(struct vol * restrict vol); + +#endif /* ATALK_VFS_H */ diff --git a/include/atalk/volume.h b/include/atalk/volume.h new file mode 100644 index 0000000..774b6a2 --- /dev/null +++ b/include/atalk/volume.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1990,1994 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifndef ATALK_VOLUME_H +#define ATALK_VOLUME_H 1 + +#include +#include + +#include +#include +#include +#include +#include + +#define AFPVOL_U8MNAMELEN 255 /* AFP3 sepc */ +#define AFPVOL_MACNAMELEN 27 /* AFP2 spec */ + +typedef uint64_t VolSpace; + +/* This should belong in a file.h */ +struct extmap { + char *em_ext; + char em_creator[4]; + char em_type[4]; +}; + +struct vol { + struct vol *v_next; + AFPObj *v_obj; + uint16_t v_vid; + int v_flags; + char *v_path; + struct dir *v_root; + time_t v_mtime; + + charset_t v_volcharset; + charset_t v_maccharset; + uint16_t v_mtou_flags; /* flags for convert_charset in mtoupath */ + uint16_t v_utom_flags; + long v_kTextEncoding; /* mac charset encoding in network order + * FIXME: should be a u_int32_t ? */ + size_t max_filename; + char *v_veto; + int v_adouble; /* adouble format: v1, v2, sfm ... */ + int v_ad_options; /* adouble option NODEV, NOCACHE, etc.. */ + const char *(*ad_path)(const char *, int); + struct _cnid_db *v_cdb; + char v_stamp[ADEDLEN_PRIVSYN]; + VolSpace v_limitsize; /* Size limit, if any, in MiB */ + mode_t v_umask; + mode_t v_dperm; /* default directories permission value OR with requested perm*/ + mode_t v_fperm; /* default files permission value OR with requested perm*/ + ucs2_t *v_u8mname; /* converted to utf8-mac in ucs2 */ + ucs2_t *v_macname; /* mangled to legacy longname in ucs2 */ + ucs2_t *v_name; /* either v_u8mname or v_macname */ + + /* get/set volparams */ + time_t v_ctime; /* volume creation date, not unix ctime */ + dev_t v_dev; /* Unix volume device, Set but not used */ + + /* adouble VFS indirection */ + struct vfs_ops *vfs; /* pointer to vfs_master_funcs for chaining */ + const struct vfs_ops *vfs_modules[4]; + int v_vfs_ea; /* The AFPVOL_EA_xx flag */ + + /* misc */ + char *v_gvs; + void *v_nfsclient; + int v_nfs; + VolSpace v_tm_used; /* used bytes on a TM volume */ + time_t v_tm_cachetime; /* time at which v_tm_used was calculated last */ + VolSpace v_appended; /* amount of data appended to files */ + + /* only when opening/closing volumes or in error */ + int v_casefold; + char *v_configname; /* as defined in afpc.conf */ + char *v_localname; /* as defined in afp.conf but with vars expanded */ + char *v_volcodepage; + char *v_maccodepage; + char *v_password; + char *v_cnidscheme; + char *v_dbpath; + char *v_cnidserver; + char *v_cnidport; +#if 0 + int v_hide; /* new volume wait until old volume is closed */ + int v_new; /* volume deleted but there's a new one with the same name */ +#endif + int v_deleted; /* volume open but deleted in new config file */ + char *v_root_preexec; + char *v_preexec; + char *v_root_postexec; + char *v_postexec; + int v_root_preexec_close; + int v_preexec_close; + char *v_uuid; /* For TimeMachine zeroconf record */ + int v_qfd; + uint32_t v_ignattr; /* AFP attributes that shall be ignored */ +}; + +/* load_volumes() flags */ +typedef enum { + lv_none = 0, + lv_all = 1, + lv_force = 2 +} lv_flags_t; + +/* volume flags */ +#define AFPVOL_OPEN (1<<0) +/* flags for AFS and quota 0xxx0 */ +#define AFPVOL_GVSMASK (7<<2) +#define AFPVOL_NONE (0<<2) +#define AFPVOL_AFSGVS (1<<2) +#define AFPVOL_USTATFS (1<<3) +#define AFPVOL_UQUOTA (1<<4) + +#define AFPVOL_NOV2TOEACONV (1 << 5) /* no adouble:v2 to adouble:ea conversion */ +#define AFPVOL_SPOTLIGHT (1 << 6) /* Index volume for Spotlight searches */ +#define AFPVOL_RO (1 << 8) /* read-only volume */ +#define AFPVOL_CHMOD_PRESERVE_ACL (1 << 9) /* try to preserve ACLs */ +#define AFPVOL_CHMOD_IGNORE (1 << 10) /* try to preserve ACLs */ +#define AFPVOL_FORCE_STICKY_XATTR (1 << 11) /* write metadata xattr as root on sticky dirs */ +#define AFPVOL_NOSTAT (1 << 16) /* advertise the volume even if we can't stat() it + * maybe because it will be mounted later in preexec */ +#define AFPVOL_UNIX_PRIV (1 << 17) /* support unix privileges */ +#define AFPVOL_NODEV (1 << 18) /* always use 0 for device number in cnid calls + * help if device number is notconsistent across reboot + * NOTE symlink to a different device will return an ACCESS error + */ +#define AFPVOL_EILSEQ (1 << 20) /* encode illegal sequence 'asis' UCS2, ex "\217-", which is not + a valid SHIFT-JIS char, is encoded as U\217 -*/ +#define AFPVOL_INV_DOTS (1 << 22) /* dots files are invisible */ +#define AFPVOL_TM (1 << 23) /* Supports TimeMachine */ +#define AFPVOL_ACLS (1 << 24) /* Volume supports ACLS */ +#define AFPVOL_SEARCHDB (1 << 25) /* Use fast CNID db search instead of filesystem */ +#define AFPVOL_NONETIDS (1 << 26) /* signal the client it shall do privelege mapping */ +#define AFPVOL_FOLLOWSYM (1 << 27) /* follow symlinks on the server, default is not to */ +#define AFPVOL_DELVETO (1 << 28) /* delete veto files and dirs */ + +/* Extended Attributes vfs indirection */ +#define AFPVOL_EA_NONE 0 /* No EAs */ +#define AFPVOL_EA_AUTO 1 /* try sys, fallback to ad (default) */ +#define AFPVOL_EA_SYS 2 /* Store them in native EAs */ +#define AFPVOL_EA_AD 3 /* Store them in adouble files */ + +/* FPGetSrvrParms options */ +#define AFPSRVR_CONFIGINFO (1 << 0) +#define AFPSRVR_PASSWD (1 << 7) + +/* handle casefolding */ +#define AFPVOL_MTOUUPPER (1 << 0) +#define AFPVOL_MTOULOWER (1 << 1) +#define AFPVOL_UTOMUPPER (1 << 2) +#define AFPVOL_UTOMLOWER (1 << 3) +#define AFPVOL_UMLOWER (AFPVOL_MTOULOWER | AFPVOL_UTOMLOWER) +#define AFPVOL_UMUPPER (AFPVOL_MTOUUPPER | AFPVOL_UTOMUPPER) +#define AFPVOL_UUPPERMLOWER (AFPVOL_MTOUUPPER | AFPVOL_UTOMLOWER) +#define AFPVOL_ULOWERMUPPER (AFPVOL_MTOULOWER | AFPVOL_UTOMUPPER) +#define AFPVOL_CASESENS (1 << 4) + +#define AFPVOLSIG_FLAT 0x0001 /* flat fs */ +#define AFPVOLSIG_FIX 0x0002 /* fixed ids */ +#define AFPVOLSIG_VAR 0x0003 /* variable ids */ +#define AFPVOLSIG_DEFAULT AFPVOLSIG_FIX + +/* volume attributes */ +#define VOLPBIT_ATTR_RO (1 << 0) +#define VOLPBIT_ATTR_PASSWD (1 << 1) +#define VOLPBIT_ATTR_FILEID (1 << 2) +#define VOLPBIT_ATTR_CATSEARCH (1 << 3) +#define VOLPBIT_ATTR_BLANKACCESS (1 << 4) +#define VOLPBIT_ATTR_UNIXPRIV (1 << 5) +#define VOLPBIT_ATTR_UTF8 (1 << 6) +#define VOLPBIT_ATTR_NONETIDS (1 << 7) +#define VOLPBIT_ATTR_PRIVPARENT (1 << 8) +#define VOLPBIT_ATTR_NOTFILEXCHG (1 << 9) +#define VOLPBIT_ATTR_EXT_ATTRS (1 << 10) +#define VOLPBIT_ATTR_ACLS (1 << 11) +#define VOLPBIT_ATTR_CASESENS (1 << 12) +#define VOLPBIT_ATTR_TM (1 << 13) + +#define VOLPBIT_ATTR 0 +#define VOLPBIT_SIG 1 +#define VOLPBIT_CDATE 2 +#define VOLPBIT_MDATE 3 +#define VOLPBIT_BDATE 4 +#define VOLPBIT_VID 5 +#define VOLPBIT_BFREE 6 +#define VOLPBIT_BTOTAL 7 +#define VOLPBIT_NAME 8 +/* handle > 4GB volumes */ +#define VOLPBIT_XBFREE 9 +#define VOLPBIT_XBTOTAL 10 +#define VOLPBIT_BSIZE 11 /* block size */ + +#define utf8_encoding(obj) ((obj)->afp_version >= 30) + +#define vol_nodev(vol) (((vol)->v_flags & AFPVOL_NODEV) ? 1 : 0) +#define vol_unix_priv(vol) ((vol)->v_obj->afp_version >= 30 && ((vol)->v_flags & AFPVOL_UNIX_PRIV)) +#define vol_inv_dots(vol) (((vol)->v_flags & AFPVOL_INV_DOTS) ? 1 : 0) +#define vol_syml_opt(vol) (((vol)->v_flags & AFPVOL_FOLLOWSYM) ? 0 : O_NOFOLLOW) +#define vol_chmod_opt(vol) (((vol)->v_flags & AFPVOL_CHMOD_PRESERVE_ACL) ? O_NETATALK_ACL : \ + ((vol)->v_flags & AFPVOL_CHMOD_IGNORE) ? O_IGNORE : 0) + +#endif diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..377bb86 --- /dev/null +++ b/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/libatalk/Makefile.am b/libatalk/Makefile.am new file mode 100644 index 0000000..7dcf204 --- /dev/null +++ b/libatalk/Makefile.am @@ -0,0 +1,126 @@ +# Makefile.am for libatalk/ + +# This is the version info for the libatalk binary API. It has three +# numbers: +# +# Current -- the number of the binary API that we're implementing +# Revision -- which iteration of the implementation of the binary +# API are we supplying? +# Age -- How many previous binary API versions do we also +# support? +# +# To increment a VERSION_INFO (current:revision:age): +# If the ABI didn't change, but any library code changed: +# current:revision+1:age +# If the ABI changed, but it's backward-compatible: +# current+1:0:age+1 +# If the ABI changed and it isn't backward-compatible: +# current+1:0:0 +# + +VERSION_INFO = 16:0:0 + +# History: VERSION_INFO +# +# 3.0.0-alpha1 0:0:0 +# 3.0.0-alpha2 0:0:0 +# 3.0.0-alpha3 0:0:0 +# 3.0.0-beta1 0:0:0 +# 3.0.0-beta2 1:0:0 +# 3.0 1:0:0 +# 3.0.1 2:0:0 +# 3.0.2 3:0:0 +# 3.0.3 4:0:0 +# 3.0.4 5:0:0 +# 3.0.5 6:0:0 +# 3.0.6 7:0:0 + +# 3.1.0 12:0:0 +# 3.1.1 13:0:0 +# 3.1.2 14:0:0 +# 3.1.3 15:0:0 +# 3.1.4 16:0:0 +# 3.1.5 16:0:0 +# 3.1.6 16:0:0 + +SUBDIRS = acl adouble bstring compat cnid dsi iniparser talloc util unicode vfs + +lib_LTLIBRARIES = libatalk.la + +libatalk_la_SOURCES = dummy.c + +libatalk_la_CFLAGS = \ + @PTHREAD_CFLAGS@ + +libatalk_la_LIBADD = \ + @WRAP_LIBS@ @ACL_LIBS@ @PTHREAD_LIBS@ @MYSQL_LIBS@ \ + acl/libacl.la \ + adouble/libadouble.la \ + bstring/libbstring.la \ + cnid/libcnid.la \ + compat/libcompat.la \ + dsi/libdsi.la \ + iniparser/libiniparser.la \ + talloc/libtalloc.la \ + unicode/libunicode.la \ + util/libutil.la \ + vfs/libvfs.la + +libatalk_la_DEPENDENCIES = \ + acl/libacl.la \ + adouble/libadouble.la \ + bstring/libbstring.la \ + cnid/libcnid.la \ + compat/libcompat.la \ + dsi/libdsi.la \ + talloc/libtalloc.la \ + iniparser/libiniparser.la \ + unicode/libunicode.la \ + util/libutil.la \ + vfs/libvfs.la + +libatalk_la_LDFLAGS = -version-info $(VERSION_INFO) + +if USE_BUILTIN_TDB +SUBDIRS += tdb +libatalk_la_LIBADD += tdb/libtdb.la +libatalk_la_DEPENDENCIES += tdb/libtdb.la +endif + +if DEVELOPER +all-local: .libs/libatalk.so + @$(top_srcdir)/abigen.sh .libs/libatalk.so > libatalk.abi.tmp + @if [ ! -f libatalk-$(NETATALK_VERSION).abi ] ; then \ + cp libatalk.abi.tmp libatalk-$(NETATALK_VERSION).abi ; \ + echo "**********************************************************************************************************" ; \ + echo " created ABI file libatalk-$(NETATALK_VERSION).abi" ; \ + echo " check https://sourceforge.net/apps/mediawiki/netatalk/index.php?title=Developer_Infos#ABI_checking" ; \ + echo "**********************************************************************************************************" ; \ + exit 1 ; \ + fi + @diff -u libatalk-$(NETATALK_VERSION).abi libatalk.abi.tmp || ( \ + echo '**********************************************************************************************************' && \ + echo '*** libatalk ABI changed ***' && \ + echo '*** check https://sourceforge.net/apps/mediawiki/netatalk/index.php?title=Developer_Infos#ABI_checking ***' && \ + echo '**********************************************************************************************************' && \ + exit 1 ) + +endif + +EXTRA_DIST = \ + libatalk-3.0beta1.abi \ + libatalk-3.0beta2.abi \ + libatalk-3.0.abi \ + libatalk-3.0.1.abi \ + libatalk-3.0.2.abi \ + libatalk-3.0.3.abi \ + libatalk-3.0.4.abi \ + libatalk-3.0.5.abi \ + libatalk-3.0.6.abi \ + libatalk-3.1.0.abi \ + libatalk-3.1.1.abi \ + libatalk-3.1.2.abi \ + libatalk-3.1.3.abi \ + libatalk-3.1.4.abi \ + libatalk-3.1.6.abi \ + libatalk-3.1.5.abi diff --git a/libatalk/Makefile.in b/libatalk/Makefile.in new file mode 100644 index 0000000..5b82238 --- /dev/null +++ b/libatalk/Makefile.in @@ -0,0 +1,952 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/ + +# This is the version info for the libatalk binary API. It has three +# numbers: +# +# Current -- the number of the binary API that we're implementing +# Revision -- which iteration of the implementation of the binary +# API are we supplying? +# Age -- How many previous binary API versions do we also +# support? +# +# To increment a VERSION_INFO (current:revision:age): +# If the ABI didn't change, but any library code changed: +# current:revision+1:age +# If the ABI changed, but it's backward-compatible: +# current+1:0:age+1 +# If the ABI changed and it isn't backward-compatible: +# current+1:0:0 +# + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@USE_BUILTIN_TDB_TRUE@am__append_1 = tdb +@USE_BUILTIN_TDB_TRUE@am__append_2 = tdb/libtdb.la +@USE_BUILTIN_TDB_TRUE@am__append_3 = tdb/libtdb.la +subdir = libatalk +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am_libatalk_la_OBJECTS = libatalk_la-dummy.lo +libatalk_la_OBJECTS = $(am_libatalk_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libatalk_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libatalk_la_CFLAGS) \ + $(CFLAGS) $(libatalk_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libatalk_la_SOURCES) +DIST_SOURCES = $(libatalk_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = acl adouble bstring compat cnid dsi iniparser talloc \ + util unicode vfs tdb +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +VERSION_INFO = 16:0:0 + +# History: VERSION_INFO +# +# 3.0.0-alpha1 0:0:0 +# 3.0.0-alpha2 0:0:0 +# 3.0.0-alpha3 0:0:0 +# 3.0.0-beta1 0:0:0 +# 3.0.0-beta2 1:0:0 +# 3.0 1:0:0 +# 3.0.1 2:0:0 +# 3.0.2 3:0:0 +# 3.0.3 4:0:0 +# 3.0.4 5:0:0 +# 3.0.5 6:0:0 +# 3.0.6 7:0:0 + +# 3.1.0 12:0:0 +# 3.1.1 13:0:0 +# 3.1.2 14:0:0 +# 3.1.3 15:0:0 +# 3.1.4 16:0:0 +# 3.1.5 16:0:0 +# 3.1.6 16:0:0 +SUBDIRS = acl adouble bstring compat cnid dsi iniparser talloc util \ + unicode vfs $(am__append_1) +lib_LTLIBRARIES = libatalk.la +libatalk_la_SOURCES = dummy.c +libatalk_la_CFLAGS = \ + @PTHREAD_CFLAGS@ + +libatalk_la_LIBADD = @WRAP_LIBS@ @ACL_LIBS@ @PTHREAD_LIBS@ \ + @MYSQL_LIBS@ acl/libacl.la adouble/libadouble.la \ + bstring/libbstring.la cnid/libcnid.la compat/libcompat.la \ + dsi/libdsi.la iniparser/libiniparser.la talloc/libtalloc.la \ + unicode/libunicode.la util/libutil.la vfs/libvfs.la \ + $(am__append_2) +libatalk_la_DEPENDENCIES = acl/libacl.la adouble/libadouble.la \ + bstring/libbstring.la cnid/libcnid.la compat/libcompat.la \ + dsi/libdsi.la talloc/libtalloc.la iniparser/libiniparser.la \ + unicode/libunicode.la util/libutil.la vfs/libvfs.la \ + $(am__append_3) +libatalk_la_LDFLAGS = -version-info $(VERSION_INFO) +EXTRA_DIST = \ + libatalk-3.0beta1.abi \ + libatalk-3.0beta2.abi \ + libatalk-3.0.abi \ + libatalk-3.0.1.abi \ + libatalk-3.0.2.abi \ + libatalk-3.0.3.abi \ + libatalk-3.0.4.abi \ + libatalk-3.0.5.abi \ + libatalk-3.0.6.abi \ + libatalk-3.1.0.abi \ + libatalk-3.1.1.abi \ + libatalk-3.1.2.abi \ + libatalk-3.1.3.abi \ + libatalk-3.1.4.abi \ + libatalk-3.1.6.abi \ + libatalk-3.1.5.abi + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libatalk.la: $(libatalk_la_OBJECTS) $(libatalk_la_DEPENDENCIES) $(EXTRA_libatalk_la_DEPENDENCIES) + $(AM_V_CCLD)$(libatalk_la_LINK) -rpath $(libdir) $(libatalk_la_OBJECTS) $(libatalk_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libatalk_la-dummy.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libatalk_la-dummy.lo: dummy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libatalk_la_CFLAGS) $(CFLAGS) -MT libatalk_la-dummy.lo -MD -MP -MF $(DEPDIR)/libatalk_la-dummy.Tpo -c -o libatalk_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libatalk_la-dummy.Tpo $(DEPDIR)/libatalk_la-dummy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy.c' object='libatalk_la-dummy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libatalk_la_CFLAGS) $(CFLAGS) -c -o libatalk_la-dummy.lo `test -f 'dummy.c' || echo '$(srcdir)/'`dummy.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +@DEVELOPER_FALSE@all-local: +all-am: Makefile $(LTLIBRARIES) all-local +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am all-local check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist \ + cscopelist-recursive ctags ctags-recursive distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-libLTLIBRARIES + + +@DEVELOPER_TRUE@all-local: .libs/libatalk.so +@DEVELOPER_TRUE@ @$(top_srcdir)/abigen.sh .libs/libatalk.so > libatalk.abi.tmp +@DEVELOPER_TRUE@ @if [ ! -f libatalk-$(NETATALK_VERSION).abi ] ; then \ +@DEVELOPER_TRUE@ cp libatalk.abi.tmp libatalk-$(NETATALK_VERSION).abi ; \ +@DEVELOPER_TRUE@ echo "**********************************************************************************************************" ; \ +@DEVELOPER_TRUE@ echo " created ABI file libatalk-$(NETATALK_VERSION).abi" ; \ +@DEVELOPER_TRUE@ echo " check https://sourceforge.net/apps/mediawiki/netatalk/index.php?title=Developer_Infos#ABI_checking" ; \ +@DEVELOPER_TRUE@ echo "**********************************************************************************************************" ; \ +@DEVELOPER_TRUE@ exit 1 ; \ +@DEVELOPER_TRUE@ fi +@DEVELOPER_TRUE@ @diff -u libatalk-$(NETATALK_VERSION).abi libatalk.abi.tmp || ( \ +@DEVELOPER_TRUE@ echo '**********************************************************************************************************' && \ +@DEVELOPER_TRUE@ echo '*** libatalk ABI changed ***' && \ +@DEVELOPER_TRUE@ echo '*** check https://sourceforge.net/apps/mediawiki/netatalk/index.php?title=Developer_Infos#ABI_checking ***' && \ +@DEVELOPER_TRUE@ echo '**********************************************************************************************************' && \ +@DEVELOPER_TRUE@ exit 1 ) + +# 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/libatalk/acl/Makefile.am b/libatalk/acl/Makefile.am new file mode 100644 index 0000000..1013f46 --- /dev/null +++ b/libatalk/acl/Makefile.am @@ -0,0 +1,17 @@ +# Makefile.am for libatalk/acl/ + +noinst_HEADERS = aclldap.h cache.h + +noinst_LTLIBRARIES = libacl.la +libacl_la_SOURCES = cache.c unix.c uuid.c +libacl_la_CFLAGS = +libacl_la_LDFLAGS = +libacl_la_LIBADD = @ACL_LIBS@ + +if HAVE_LDAP +libacl_la_SOURCES += ldap.c ldap_config.c +libacl_la_CFLAGS += @LDAP_CFLAGS@ +libacl_la_LIBADD += @LDAP_LIBS@ +libacl_la_LDFLAGS += @LDAP_LDFLAGS@ +endif + diff --git a/libatalk/acl/Makefile.in b/libatalk/acl/Makefile.in new file mode 100644 index 0000000..8714e10 --- /dev/null +++ b/libatalk/acl/Makefile.in @@ -0,0 +1,719 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/acl/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_LDAP_TRUE@am__append_1 = ldap.c ldap_config.c +@HAVE_LDAP_TRUE@am__append_2 = @LDAP_CFLAGS@ +@HAVE_LDAP_TRUE@am__append_3 = @LDAP_LIBS@ +@HAVE_LDAP_TRUE@am__append_4 = @LDAP_LDFLAGS@ +subdir = libatalk/acl +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libacl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__libacl_la_SOURCES_DIST = cache.c unix.c uuid.c ldap.c \ + ldap_config.c +@HAVE_LDAP_TRUE@am__objects_1 = libacl_la-ldap.lo \ +@HAVE_LDAP_TRUE@ libacl_la-ldap_config.lo +am_libacl_la_OBJECTS = libacl_la-cache.lo libacl_la-unix.lo \ + libacl_la-uuid.lo $(am__objects_1) +libacl_la_OBJECTS = $(am_libacl_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libacl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libacl_la_CFLAGS) \ + $(CFLAGS) $(libacl_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libacl_la_SOURCES) +DIST_SOURCES = $(am__libacl_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_HEADERS = aclldap.h cache.h +noinst_LTLIBRARIES = libacl.la +libacl_la_SOURCES = cache.c unix.c uuid.c $(am__append_1) +libacl_la_CFLAGS = $(am__append_2) +libacl_la_LDFLAGS = $(am__append_4) +libacl_la_LIBADD = @ACL_LIBS@ $(am__append_3) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/acl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/acl/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libacl.la: $(libacl_la_OBJECTS) $(libacl_la_DEPENDENCIES) $(EXTRA_libacl_la_DEPENDENCIES) + $(AM_V_CCLD)$(libacl_la_LINK) $(libacl_la_OBJECTS) $(libacl_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libacl_la-cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libacl_la-ldap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libacl_la-ldap_config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libacl_la-unix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libacl_la-uuid.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libacl_la-cache.lo: cache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -MT libacl_la-cache.lo -MD -MP -MF $(DEPDIR)/libacl_la-cache.Tpo -c -o libacl_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libacl_la-cache.Tpo $(DEPDIR)/libacl_la-cache.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='libacl_la-cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -c -o libacl_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c + +libacl_la-unix.lo: unix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -MT libacl_la-unix.lo -MD -MP -MF $(DEPDIR)/libacl_la-unix.Tpo -c -o libacl_la-unix.lo `test -f 'unix.c' || echo '$(srcdir)/'`unix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libacl_la-unix.Tpo $(DEPDIR)/libacl_la-unix.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unix.c' object='libacl_la-unix.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -c -o libacl_la-unix.lo `test -f 'unix.c' || echo '$(srcdir)/'`unix.c + +libacl_la-uuid.lo: uuid.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -MT libacl_la-uuid.lo -MD -MP -MF $(DEPDIR)/libacl_la-uuid.Tpo -c -o libacl_la-uuid.lo `test -f 'uuid.c' || echo '$(srcdir)/'`uuid.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libacl_la-uuid.Tpo $(DEPDIR)/libacl_la-uuid.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uuid.c' object='libacl_la-uuid.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -c -o libacl_la-uuid.lo `test -f 'uuid.c' || echo '$(srcdir)/'`uuid.c + +libacl_la-ldap.lo: ldap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -MT libacl_la-ldap.lo -MD -MP -MF $(DEPDIR)/libacl_la-ldap.Tpo -c -o libacl_la-ldap.lo `test -f 'ldap.c' || echo '$(srcdir)/'`ldap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libacl_la-ldap.Tpo $(DEPDIR)/libacl_la-ldap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap.c' object='libacl_la-ldap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -c -o libacl_la-ldap.lo `test -f 'ldap.c' || echo '$(srcdir)/'`ldap.c + +libacl_la-ldap_config.lo: ldap_config.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -MT libacl_la-ldap_config.lo -MD -MP -MF $(DEPDIR)/libacl_la-ldap_config.Tpo -c -o libacl_la-ldap_config.lo `test -f 'ldap_config.c' || echo '$(srcdir)/'`ldap_config.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libacl_la-ldap_config.Tpo $(DEPDIR)/libacl_la-ldap_config.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ldap_config.c' object='libacl_la-ldap_config.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libacl_la_CFLAGS) $(CFLAGS) -c -o libacl_la-ldap_config.lo `test -f 'ldap_config.c' || echo '$(srcdir)/'`ldap_config.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/acl/aclldap.h b/libatalk/acl/aclldap.h new file mode 100644 index 0000000..b4adea9 --- /dev/null +++ b/libatalk/acl/aclldap.h @@ -0,0 +1,27 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. + */ + +#ifndef ACLLDAP_H +#define ACLLDAP_H + +#include /* just for uuidtype_t*/ + +/******************************************************** + * Interface + ********************************************************/ + +extern int ldap_getuuidfromname( const char *name, uuidtype_t type, char **uuid_string); +extern int ldap_getnamefromuuid( const char *uuidstr, char **name, uuidtype_t *type); + +#endif /* ACLLDAP_H */ diff --git a/libatalk/acl/cache.c b/libatalk/acl/cache.c new file mode 100644 index 0000000..15eea47 --- /dev/null +++ b/libatalk/acl/cache.c @@ -0,0 +1,362 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "cache.h" + +typedef struct cacheduser { + unsigned long uid; /* for future use */ + uuidtype_t type; + unsigned char *uuid; + char *name; + time_t creationtime; + struct cacheduser *prev; + struct cacheduser *next; +} cacheduser_t; + +static cacheduser_t *namecache[256]; /* indexed by hash of name */ +static cacheduser_t *uuidcache[256]; /* indexed by hash of uuid */ + +/******************************************************** + * helper function + ********************************************************/ + +void uuidcache_dump(void) { + int i; + cacheduser_t *entry; + char timestr[200]; + struct tm *tmp = NULL; + + for ( i=0 ; i<256; i++) { + if ((entry = namecache[i]) != NULL) { + do { + tmp = localtime(&entry->creationtime); + if (tmp == NULL) + continue; + if (strftime(timestr, 200, "%c", tmp) == 0) + continue; + LOG(log_debug, logtype_default, + "namecache{%d}: name:%s, uuid:%s, type%s: %s, cached: %s", + i, + entry->name, + uuid_bin2string(entry->uuid), + (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "", + uuidtype[entry->type & UUIDTYPESTR_MASK], + timestr); + } while ((entry = entry->next) != NULL); + } + } + + for ( i=0; i<256; i++) { + if ((entry = uuidcache[i]) != NULL) { + do { + + tmp = localtime(&entry->creationtime); + if (tmp == NULL) + continue; + if (strftime(timestr, 200, "%c", tmp) == 0) + continue; + LOG(log_debug, logtype_default, + "uuidcache{%d}: uuid:%s, name:%s, type%s: %s, cached: %s", + i, + uuid_bin2string(entry->uuid), + entry->name, + (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "", + uuidtype[entry->type & UUIDTYPESTR_MASK], + timestr); + } while ((entry = entry->next) != NULL); + } + } +} + +/* hash string it into unsigned char */ +static unsigned char hashstring(unsigned char *str) { + unsigned long hash = 5381; + unsigned char index; + int c; + while ((c = *str++) != 0) + hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */ + + index = 85 ^ (hash & 0xff); + while ((hash = hash >> 8) != 0) + index ^= (hash & 0xff); + + return index; +} + +/* hash atalk_uuid_t into unsigned char */ +static unsigned char hashuuid(uuidp_t uuid) { + unsigned char index = 83; + int i; + + for (i=0; i<16; i++) { + index ^= uuid[i]; + index += uuid[i]; + } + return index; +} + +/******************************************************** + * Interface + ********************************************************/ + +int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid _U_) { + int ret = 0; + char *name = NULL; + unsigned char *uuid = NULL; + cacheduser_t *cacheduser = NULL; + unsigned char hash; + + /* allocate mem and copy values */ + name = malloc(strlen(inname)+1); + if (!name) { + LOG(log_error, logtype_default, "add_cachebyname: mallor error"); + ret = -1; + goto cleanup; + } + + uuid = malloc(UUID_BINSIZE); + if (!uuid) { + LOG(log_error, logtype_default, "add_cachebyname: mallor error"); + ret = -1; + goto cleanup; + } + + cacheduser = malloc(sizeof(cacheduser_t)); + if (!cacheduser) { + LOG(log_error, logtype_default, "add_cachebyname: mallor error"); + ret = -1; + goto cleanup; + } + + strcpy(name, inname); + memcpy(uuid, inuuid, UUID_BINSIZE); + + /* fill in the cacheduser */ + cacheduser->name = name; + cacheduser->uuid = uuid; + cacheduser->type = type; + cacheduser->creationtime = time(NULL); + cacheduser->prev = NULL; + cacheduser->next = NULL; + + /* get hash */ + hash = hashstring((unsigned char *)name); + + /* insert cache entry into cache array at head of queue */ + if (namecache[hash] == NULL) { + /* this queue is empty */ + namecache[hash] = cacheduser; + } else { + cacheduser->next = namecache[hash]; + namecache[hash]->prev = cacheduser; + namecache[hash] = cacheduser; + } + +cleanup: + if (ret != 0) { + if (name) + free(name); + if (uuid) + free(uuid); + if (cacheduser) + free(cacheduser); + } + + return ret; +} + +/*! + * Search cache by name and uuid type + * + * @args name (r) name to search + * @args type (rw) type (user or group) of name, returns found type here which might + * mark it as a negative entry + * @args uuid (w) found uuid is returned here + * @returns 0 on sucess, entry found + * -1 no entry found + */ +int search_cachebyname( const char *name, uuidtype_t *type, unsigned char *uuid) { + int ret; + unsigned char hash; + cacheduser_t *entry; + time_t tim; + + hash = hashstring((unsigned char *)name); + + if (namecache[hash] == NULL) + return -1; + + entry = namecache[hash]; + while (entry) { + ret = strcmp(entry->name, name); + if (ret == 0 && *type == (entry->type & UUIDTYPESTR_MASK)) { + /* found, now check if expired */ + tim = time(NULL); + if ((tim - entry->creationtime) > CACHESECONDS) { + LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\"%s\"", entry->name); + /* remove item */ + if (entry->prev) { + /* 2nd to last in queue */ + entry->prev->next = entry->next; + if (entry->next) + /* not the last element */ + entry->next->prev = entry->prev; + } else { + /* queue head */ + if ((namecache[hash] = entry->next) != NULL) + namecache[hash]->prev = NULL; + } + free(entry->name); + free(entry->uuid); + free(entry); + return -1; + } else { + memcpy(uuid, entry->uuid, UUID_BINSIZE); + *type = entry->type; + return 0; + } + } + entry = entry->next; + } + + return -1; +} + +/* + * Caller must free allocated name + */ +int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) { + int ret; + unsigned char hash; + cacheduser_t *entry; + time_t tim; + + hash = hashuuid(uuidp); + + if (! uuidcache[hash]) + return -1; + + entry = uuidcache[hash]; + while (entry) { + ret = memcmp(entry->uuid, uuidp, UUID_BINSIZE); + if (ret == 0) { + tim = time(NULL); + if ((tim - entry->creationtime) > CACHESECONDS) { + LOG(log_debug, logtype_default, "search_cachebyuuid: expired: name:\'%s\' in queue {%d}", entry->name, hash); + if (entry->prev) { + /* 2nd to last in queue */ + entry->prev->next = entry->next; + if (entry->next) + /* not the last element */ + entry->next->prev = entry->prev; + } else { + /* queue head */ + if ((uuidcache[hash] = entry->next) != NULL) + uuidcache[hash]->prev = NULL; + } + free(entry->name); + free(entry->uuid); + free(entry); + return -1; + } else { + *name = malloc(strlen(entry->name)+1); + strcpy(*name, entry->name); + *type = entry->type; + return 0; + } + } + entry = entry->next; + } + + return -1; +} + +int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid _U_) { + int ret = 0; + char *name = NULL; + unsigned char *uuid = NULL; + cacheduser_t *cacheduser = NULL; + unsigned char hash; + + /* allocate mem and copy values */ + name = malloc(strlen(inname)+1); + if (!name) { + LOG(log_error, logtype_default, "add_cachebyuuid: mallor error"); + ret = -1; + goto cleanup; + } + + uuid = malloc(UUID_BINSIZE); + if (!uuid) { + LOG(log_error, logtype_default, "add_cachebyuuid: mallor error"); + ret = -1; + goto cleanup; + } + + cacheduser = malloc(sizeof(cacheduser_t)); + if (!cacheduser) { + LOG(log_error, logtype_default, "add_cachebyuuid: mallor error"); + ret = -1; + goto cleanup; + } + + strcpy(name, inname); + memcpy(uuid, inuuid, UUID_BINSIZE); + + /* fill in the cacheduser */ + cacheduser->name = name; + cacheduser->type = type; + cacheduser->uuid = uuid; + cacheduser->creationtime = time(NULL); + cacheduser->prev = NULL; + cacheduser->next = NULL; + + /* get hash */ + hash = hashuuid(uuid); + + /* insert cache entry into cache array at head of queue */ + if (uuidcache[hash] == NULL) { + /* this queue is empty */ + uuidcache[hash] = cacheduser; + } else { + cacheduser->next = uuidcache[hash]; + uuidcache[hash]->prev = cacheduser; + uuidcache[hash] = cacheduser; + } + +cleanup: + if (ret != 0) { + if (name) + free(name); + if (uuid) + free(uuid); + if (cacheduser) + free(cacheduser); + } + + return ret; +} diff --git a/libatalk/acl/cache.h b/libatalk/acl/cache.h new file mode 100644 index 0000000..8e33004 --- /dev/null +++ b/libatalk/acl/cache.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. + */ + +#ifndef LDAPCACHE_H +#define LDAPCACHE_H + +/* + * We need to cache all LDAP querie results, they just take too long. + * We do hashing with chaining. Two caches are needed: + * 1) name -> uuid, indexed by a hash(f(): hashstring) of the name + * 2) uuid -> name, indexed by a hash of the uuid(f(): hashuuid) + * Both hash funcs result in a value 0-255 with which we index a array. + * We malloc and free all elements as needed. + * The cache caches for CACHESECONDS. + */ + +#define CACHESECONDS 600 + +/******************************************************** + * Interface + ********************************************************/ + +extern int search_cachebyname( const char *name, uuidtype_t *type, unsigned char *uuid); +extern int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid); +extern int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type); +extern int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid); + +#endif /* LDAPCACHE_H */ diff --git a/libatalk/acl/ldap.c b/libatalk/acl/ldap.c new file mode 100644 index 0000000..e805a99 --- /dev/null +++ b/libatalk/acl/ldap.c @@ -0,0 +1,450 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_LDAP + +#include +#include +#include +#include +#include +#include +#define LDAP_DEPRECATED 1 +#include + +#include +#include +#include +#include /* For struct ldap_pref */ +#include + +typedef enum { + KEEPALIVE = 1 +} ldapcon_t; + +/******************************************************** + * LDAP config stuff. Filled by libatalk/acl/ldap_config.c + ********************************************************/ +int ldap_config_valid; + +char *ldap_server; +int ldap_auth_method; +char *ldap_auth_dn; +char *ldap_auth_pw; +char *ldap_userbase; +int ldap_userscope; +char *ldap_groupbase; +int ldap_groupscope; +char *ldap_uuid_attr; +char *ldap_uuid_string; +char *ldap_name_attr; +char *ldap_group_attr; +char *ldap_uid_attr; +char *ldap_userfilter; +char *ldap_groupfilter; +int ldap_uuid_encoding; + +struct ldap_pref ldap_prefs[] = { + /* pointer to pref, prefname, strorint, intfromarray, valid, valid_save */ + {&ldap_server, "ldap server", 0, 0, -1, -1}, + {&ldap_auth_method, "ldap auth method", 1, 1, -1, -1}, + {&ldap_auth_dn, "ldap auth dn", 0, 0, 0, 0}, + {&ldap_auth_pw, "ldap auth pw", 0, 0, 0, 0}, + {&ldap_userbase, "ldap userbase", 0, 0, -1, -1}, + {&ldap_userscope, "ldap userscope", 1 ,1, -1, -1}, + {&ldap_groupbase, "ldap groupbase", 0, 0, -1, -1}, + {&ldap_groupscope, "ldap groupscope", 1 ,1, -1, -1}, + {&ldap_uuid_attr, "ldap uuid attr", 0, 0, -1, -1}, + {&ldap_uuid_string, "ldap uuid string", 0, 0, 0, 0}, + {&ldap_name_attr, "ldap name attr", 0, 0, -1, -1}, + {&ldap_group_attr, "ldap group attr", 0, 0, -1, -1}, + {&ldap_uid_attr, "ldap uid attr", 0, 0, 0, 0}, + {&ldap_uuid_encoding, "ldap uuid encoding", 1, 1, 0, 0}, + {&ldap_userfilter, "ldap user filter", 0, 0, 0, 0}, + {&ldap_groupfilter, "ldap group filter", 0, 0, 0, 0}, + {&ldap_auth_pw, "ldap auth pw", 0, 0, 0, 0}, + {NULL, NULL, 0, 0, 0, 0} +}; + +struct pref_array prefs_array[] = { + {"ldap auth method", "none", LDAP_AUTH_NONE}, + {"ldap auth method", "simple", LDAP_AUTH_SIMPLE}, + {"ldap auth method", "sasl", LDAP_AUTH_SASL}, + {"ldap userscope", "base", LDAP_SCOPE_BASE}, + {"ldap userscope", "one", LDAP_SCOPE_ONELEVEL}, + {"ldap userscope", "sub", LDAP_SCOPE_SUBTREE}, + {"ldap groupscope", "base", LDAP_SCOPE_BASE}, + {"ldap groupscope", "one", LDAP_SCOPE_ONELEVEL}, + {"ldap groupscope", "sub", LDAP_SCOPE_SUBTREE}, + {"ldap uuid encoding", "ms-guid", LDAP_UUID_ENCODING_MSGUID}, + {"ldap uuid encoding", "string", LDAP_UUID_ENCODING_STRING}, + {NULL, NULL, 0} +}; + +/******************************************************** + * Static helper function + ********************************************************/ + +/* + * ldap_getattr_fromfilter_withbase_scope(): + * conflags: KEEPALIVE + * scope: LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE + * result: return unique search result here, allocated here, caller must free + * + * returns: -1 on error + * 0 nothing found + * 1 successfull search, result int 'result' + * + * All connection managment to the LDAP server is done here. Just set KEEPALIVE if you know + * you will be dispatching more than one search in a row, then don't set it with the last search. + * You MUST dispatch the queries timely, otherwise the LDAP handle might timeout. + */ +static int ldap_getattr_fromfilter_withbase_scope( const char *searchbase, + const char *filter, + char *attributes[], + int scope, + ldapcon_t conflags, + char **result) { + int ret; + int ldaperr; + int retrycount = 0; + int desired_version = LDAP_VERSION3; + static int ldapconnected = 0; + static LDAP *ld = NULL; + LDAPMessage* msg = NULL; + LDAPMessage* entry = NULL; + struct berval **attribute_values = NULL; + struct timeval timeout; + + LOG(log_maxdebug, logtype_afpd,"ldap: BEGIN"); + + timeout.tv_sec = 3; + timeout.tv_usec = 0; + + /* init LDAP if necessary */ +retry: + ret = 0; + + if (ld == NULL) { + LOG(log_maxdebug, logtype_default, "ldap: server: \"%s\"", + ldap_server); + if ((ld = ldap_init(ldap_server, LDAP_PORT)) == NULL ) { + LOG(log_error, logtype_default, "ldap: ldap_init error: %s", + strerror(errno)); + return -1; + } + if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version) != 0) { + /* LDAP_OPT_SUCCESS is not in the proposed standard, so we check for 0 + http://tools.ietf.org/id/draft-ietf-ldapext-ldap-c-api-05.txt */ + LOG(log_error, logtype_default, "ldap: ldap_set_option failed!"); + free(ld); + ld = NULL; + return -1; + } + } + + /* connect */ + if (!ldapconnected) { + if (LDAP_AUTH_NONE == ldap_auth_method) { + if (ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != LDAP_SUCCESS ) { + LOG(log_error, logtype_default, "ldap: ldap_bind failed, auth_method: \'%d\'", + ldap_auth_method); + free(ld); + ld = NULL; + return -1; + } + ldapconnected = 1; + + } else if (LDAP_AUTH_SIMPLE == ldap_auth_method) { + if (ldap_bind_s(ld, ldap_auth_dn, ldap_auth_pw, ldap_auth_method) != LDAP_SUCCESS ) { + LOG(log_error, logtype_default, + "ldap: ldap_bind failed: ldap_auth_dn: \'%s\', ldap_auth_pw: \'%s\', ldap_auth_method: \'%d\'", + ldap_auth_dn, ldap_auth_pw, ldap_auth_method); + free(ld); + ld = NULL; + return -1; + } + ldapconnected = 1; + } + } + + LOG(log_maxdebug, logtype_afpd, "ldap: start search: base: %s, filter: %s, attr: %s", + searchbase, filter, attributes[0]); + + /* start LDAP search */ + ldaperr = ldap_search_st(ld, searchbase, scope, filter, attributes, 0, &timeout, &msg); + LOG(log_maxdebug, logtype_default, "ldap: ldap_search_st returned: %s", + ldap_err2string(ldaperr)); + if (ldaperr != LDAP_SUCCESS) { + LOG(log_error, logtype_default, "ldap: ldap_search_st failed: %s, retrycount: %i", + ldap_err2string(ldaperr), retrycount); + ret = -1; + goto cleanup; + } + + /* parse search result */ + LOG(log_maxdebug, logtype_default, "ldap: got %d entries from ldap search", + ldap_count_entries(ld, msg)); + if ((ret = ldap_count_entries(ld, msg)) != 1) { + ret = 0; + goto cleanup; + } + + entry = ldap_first_entry(ld, msg); + if (entry == NULL) { + LOG(log_error, logtype_default, "ldap: ldap_first_entry error"); + ret = -1; + goto cleanup; + } + + attribute_values = ldap_get_values_len(ld, entry, attributes[0]); + if (attribute_values == NULL) { + LOG(log_error, logtype_default, "ldap: ldap_get_values_len error"); + ret = -1; + goto cleanup; + } + + LOG(log_maxdebug, logtype_afpd,"ldap: search result: %s: %s", + attributes[0], attribute_values[0]->bv_val); + + /* allocate and copy result */ + *result = calloc(1, attribute_values[0]->bv_len + 1); + memcpy(*result, attribute_values[0]->bv_val, attribute_values[0]->bv_len + 1); + + if (*result == NULL) { + LOG(log_error, logtype_default, "ldap: memcopy error: %s", strerror(errno)); + ret = -1; + goto cleanup; + } + +cleanup: + if (attribute_values) + ldap_value_free_len(attribute_values); + /* FIXME: is there another way to free entry ? */ + while (entry != NULL) + entry = ldap_next_entry(ld, entry); + if (msg) + ldap_msgfree(msg); + + if (ldapconnected) { + if ((ret == -1) || !(conflags & KEEPALIVE)) { + LOG(log_maxdebug, logtype_default,"ldap: unbind"); + if (ldap_unbind_s(ld) != 0) { + LOG(log_error, logtype_default, "ldap: unbind: %s\n", ldap_err2string(ldaperr)); + return -1; + } + ld = NULL; + ldapconnected = 0; + + /* In case of error we try twice */ + if (ret == -1) { + retrycount++; + if (retrycount < 2) + goto retry; + } + } + } + return ret; +} + +/*! + * Generate LDAP filter string for UUID query + + * @param[in] uuidstr the UUID as string + * @param[in] attr_filter optional attribute + * @returns pointer to static filter string + */ +static char *gen_uuid_filter(const char *uuidstr_in, const char *attr_filter) +{ + EC_INIT; + int len; + const char *uuidstr = uuidstr_in; + +#define MAX_FILTER_SIZE 512 + static char filter[MAX_FILTER_SIZE]; + char stripped[MAX_FILTER_SIZE]; + +#define LDAP_BIN_UUID_LEN 49 /* LDAP Binary Notation is \XX * 16 bytes of UUID + terminator = 49 */ + char ldap_bytes[LDAP_BIN_UUID_LEN]; + + if (ldap_uuid_encoding == LDAP_UUID_ENCODING_MSGUID) { + /* Convert to LDAP-safe binary encoding for direct query of AD objectGUID attribute */ + int i = 0, s = 0; + char c; + while ((c = uuidstr[i])) { + if((c >='a' && c <= 'f') + || (c >= 'A' && c <= 'F') + || (c >= '0' && c <= '9')) { + stripped[s++] = toupper(c); + } + i++; + } + + snprintf(ldap_bytes, LDAP_BIN_UUID_LEN, + "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c" + "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c", + /* Data1 (uint32) */ + stripped[6], stripped[7], stripped[4], stripped[5], + stripped[2], stripped[3], stripped[0], stripped[1], + /* Data2 (uint16) */ + stripped[10], stripped[11], stripped[8], stripped[9], + /* Data3 (uint16) */ + stripped[14], stripped[15], stripped[12], stripped[13], + /* Data4 (uint64) */ + stripped[16], stripped[17], stripped[18], stripped[19], + stripped[20], stripped[21], stripped[22], stripped[23], + stripped[24], stripped[25], stripped[26], stripped[27], + stripped[28], stripped[29], stripped[30], stripped[31]); + uuidstr = ldap_bytes; + } + + if (attr_filter) { + len = snprintf(filter, 256, "(&(%s=%s)(%s))", ldap_uuid_attr, uuidstr, attr_filter); + } else { + len = snprintf(filter, 256, "%s=%s", ldap_uuid_attr, uuidstr); + } + +EC_CLEANUP: + if (ret != 0) + return NULL; + return filter; +} + +/******************************************************** + * Interface + ********************************************************/ + +/*! + * Search UUID for name in LDAP + * + * Caller must free uuid_string when done with it + * + * @param name (r) name to search + * @param type (r) type of USER or GROUP + * @param uuid_string (w) result as pointer to allocated UUID-string + * + * @returns 0 on success, -1 on error or not found + */ +int ldap_getuuidfromname( const char *name, uuidtype_t type, char **uuid_string) { + int ret; + int len; + char filter[256]; /* this should really be enough. we dont want to malloc everything! */ + char *attributes[] = { ldap_uuid_attr, NULL}; + char *ldap_attr; + + if (!ldap_config_valid) + return -1; + + /* make filter */ + if (type == UUID_GROUP) + ldap_attr = ldap_group_attr; + else /* type hopefully == UUID_USER */ + ldap_attr = ldap_name_attr; + len = snprintf( filter, 256, "%s=%s", ldap_attr, name); + if (len >= 256 || len == -1) { + LOG(log_error, logtype_default, "ldap_getnamefromuuid: filter error:%d, \"%s\"", len, filter); + return -1; + } + + if (type == UUID_GROUP) { + ret = ldap_getattr_fromfilter_withbase_scope( ldap_groupbase, filter, attributes, ldap_groupscope, KEEPALIVE, uuid_string); + } else { /* type hopefully == UUID_USER */ + ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, ldap_userscope, KEEPALIVE, uuid_string); + } + + if (ret != 1) + return -1; + + if(ldap_uuid_encoding == LDAP_UUID_ENCODING_MSGUID) { + /* Convert byte array to UUID string (no dashes) */ + unsigned char* uuid_bytes = (unsigned char*) *uuid_string; + *uuid_string = malloc(37); + snprintf(*uuid_string, 37, + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + uuid_bytes[3], uuid_bytes[2], uuid_bytes[1], uuid_bytes[0], /* Data1 */ + uuid_bytes[5], uuid_bytes[4], /* Data2 */ + uuid_bytes[7], uuid_bytes[6], /* Data3 */ + uuid_bytes[8], uuid_bytes[9], /* Data4 - High Bytes */ + uuid_bytes[10], uuid_bytes[11], uuid_bytes[12], /* Data4 - Low Bytes */ + uuid_bytes[13], uuid_bytes[14], uuid_bytes[15]); + free(uuid_bytes); + LOG(log_error, logtype_default, "ldap_getnamefromuuid: uuid_string: %s", *uuid_string); + } + + return 0; +} + +/* + * LDAP search wrapper + * returns allocated storage in name, caller must free it + * returns 0 on success, -1 on error or not found + * + * @param uuidstr (r) uuid to search as ascii string + * @param name (w) return pointer to name as allocated string + * @param type (w) return type: USER or GROUP + * + * returns 0 on success, -1 on errror + */ +int ldap_getnamefromuuid( const char *uuidstr, char **name, uuidtype_t *type) { + EC_INIT; + char *filter; + char *attributes[] = { NULL, NULL}; + + if (!ldap_config_valid) + EC_FAIL; + + /* + * Search groups first as group acls are probably used more often. + * Note the special case of AD where users and groups are stored + * under the same subtree. + */ + + attributes[0] = ldap_group_attr; + EC_NULL( filter = gen_uuid_filter(uuidstr, ldap_groupfilter) ); + EC_NEG1( ret = ldap_getattr_fromfilter_withbase_scope( + ldap_groupbase, + filter, + attributes, + ldap_groupscope, + KEEPALIVE, + name) ); + if (ret == 1) { + *type = UUID_GROUP; + EC_EXIT_STATUS(0); + } + + attributes[0] = ldap_name_attr; + EC_NULL( filter = gen_uuid_filter(uuidstr, ldap_userfilter) ); + EC_NEG1( ret = ldap_getattr_fromfilter_withbase_scope( + ldap_userbase, + filter, + attributes, + ldap_userscope, + KEEPALIVE, + name) ); + if (ret == 1) { + *type = UUID_USER; + EC_EXIT_STATUS(0); + } + + EC_FAIL; + +EC_CLEANUP: + EC_EXIT; +} +#endif /* HAVE_LDAP */ diff --git a/libatalk/acl/ldap_config.c b/libatalk/acl/ldap_config.c new file mode 100644 index 0000000..9bf01c1 --- /dev/null +++ b/libatalk/acl/ldap_config.c @@ -0,0 +1,104 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_LDAP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void acl_ldap_freeconfig(void) +{ + for (int i = 0; ldap_prefs[i].name != NULL; i++) { + if (ldap_prefs[i].intfromarray == 0 && ldap_prefs[i].strorint == 0) { + free(*((char **)(ldap_prefs[i].pref))); + *((char **)(ldap_prefs[i].pref)) = NULL; + } + ldap_prefs[i].valid = ldap_prefs[i].valid_save; + } +} + +int acl_ldap_readconfig(dictionary *iniconfig) +{ + int i, j; + const char *val; + + i = 0; + /* now see if its a correct pref */ + for (i = 0; ldap_prefs[i].name != NULL; i++) { + if ((val = atalk_iniparser_getstring(iniconfig, INISEC_GLOBAL, ldap_prefs[i].name, NULL))) { + /* check if we have pre-defined values */ + if (ldap_prefs[i].intfromarray == 0) { + /* no, its just a string */ + ldap_prefs[i].valid = 0; + if (ldap_prefs[i].strorint) + /* store as int */ + *((int *)(ldap_prefs[i].pref)) = atoi(val); + else + /* store string as string */ + *((const char **)(ldap_prefs[i].pref)) = strdup(val); + } else { + /* ok, we have string to int mapping for this pref + eg. "none", "simple", "sasl" map to 0, 128, 129 */ + for (j = 0; prefs_array[j].pref != NULL; j++) { + if ((strcmp(prefs_array[j].pref, ldap_prefs[i].name) == 0) + && (strcmp(prefs_array[j].valuestring, val) == 0)) { + ldap_prefs[i].valid = 0; + *((int *)(ldap_prefs[i].pref)) = prefs_array[j].value; + break; + } + } + } + } + } + + /* check if the config is sane and complete */ + i = 0; + ldap_config_valid = 1; + + while(ldap_prefs[i].pref != NULL) { + if ( ldap_prefs[i].valid != 0) { + LOG(log_debug, logtype_afpd,"LDAP: Missing option: \"%s\"", ldap_prefs[i].name); + ldap_config_valid = 0; + break; + } + i++; + } + + if (ldap_config_valid) { + if (ldap_auth_method == LDAP_AUTH_NONE) + LOG(log_debug, logtype_afpd,"LDAP: Using anonymous bind."); + else if (ldap_auth_method == LDAP_AUTH_SIMPLE) + LOG(log_debug, logtype_afpd,"LDAP: Using simple bind."); + else { + ldap_config_valid = 0; + LOG(log_error, logtype_afpd,"LDAP: SASL not yet supported."); + } + } else + LOG(log_info, logtype_afpd,"LDAP: not used"); + return 0; +} +#endif /* HAVE_LDAP */ diff --git a/libatalk/acl/unix.c b/libatalk/acl/unix.c new file mode 100644 index 0000000..9b22511 --- /dev/null +++ b/libatalk/acl/unix.c @@ -0,0 +1,515 @@ +/* + Copyright (c) 2010 Frank Lahm + Copyright (c) 2011 Laura Mueller + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_ACLS + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_NFSV4_ACLS + +/* Get ACL. Allocates storage as needed. Caller must free. + * Returns no of ACEs or -1 on error. */ +int get_nfsv4_acl(const char *name, ace_t **retAces) +{ + int ace_count = -1; + ace_t *aces; + struct stat st; + + *retAces = NULL; + /* Only call acl() for regular files and directories, otherwise just return 0 */ + if (lstat(name, &st) != 0) { + LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): %s", getcwdpath(), name, strerror(errno)); + return -1; + } + + if (S_ISLNK(st.st_mode)) + /* sorry, no ACLs for symlinks */ + return 0; + + if ( ! (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) { + LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): special", getcwdpath(), name); + return 0; + } + + if ((ace_count = acl(name, ACE_GETACLCNT, 0, NULL)) == 0) { + LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): 0 ACEs", getcwdpath(), name); + return 0; + } + + if (ace_count == -1) { + LOG(log_debug, logtype_afpd, "get_nfsv4_acl: acl('%s/%s', ACE_GETACLCNT): ace_count %i, error: %s", + getcwdpath(), name, ace_count, strerror(errno)); + return -1; + } + + aces = malloc(ace_count * sizeof(ace_t)); + if (aces == NULL) { + LOG(log_error, logtype_afpd, "get_nfsv4_acl: malloc error"); + return -1; + } + + if ( (acl(name, ACE_GETACL, ace_count, aces)) == -1 ) { + LOG(log_error, logtype_afpd, "get_nfsv4_acl: acl(ACE_GETACL) error"); + free(aces); + return -1; + } + + LOG(log_debug9, logtype_afpd, "get_nfsv4_acl: file: %s -> No. of ACEs: %d", name, ace_count); + *retAces = aces; + + return ace_count; +} + +/* + Concatenate ACEs +*/ +ace_t *concat_aces(ace_t *aces1, int ace1count, ace_t *aces2, int ace2count) +{ + ace_t *new_aces; + int i, j; + + /* malloc buffer for new ACL */ + if ((new_aces = malloc((ace1count + ace2count) * sizeof(ace_t))) == NULL) { + LOG(log_error, logtype_afpd, "combine_aces: malloc %s", strerror(errno)); + return NULL; + } + + /* Copy ACEs from buf1 */ + for (i=0; i < ace1count; ) { + memcpy(&new_aces[i], &aces1[i], sizeof(ace_t)); + i++; + } + + j = i; + + /* Copy ACEs from buf2 */ + for (i=0; i < ace2count; ) { + memcpy(&new_aces[j], &aces2[i], sizeof(ace_t)); + i++; + j++; + } + return new_aces; +} + +/* + Remove any trivial ACE "in-place". Returns no of non-trivial ACEs +*/ +int strip_trivial_aces(ace_t **saces, int sacecount) +{ + int i,j; + int nontrivaces = 0; + ace_t *aces = *saces; + ace_t *new_aces; + + if (aces == NULL || sacecount <= 0) + return 0; + + /* Count non-trivial ACEs */ + for (i=0; i < sacecount; ) { + if ( ! (aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE))) + nontrivaces++; + i++; + } + /* malloc buffer for new ACL */ + if ((new_aces = malloc(nontrivaces * sizeof(ace_t))) == NULL) { + LOG(log_error, logtype_afpd, "strip_trivial_aces: malloc %s", strerror(errno)); + return -1; + } + + /* Copy non-trivial ACEs */ + for (i=0, j=0; i < sacecount; ) { + if ( ! (aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE))) { + memcpy(&new_aces[j], &aces[i], sizeof(ace_t)); + j++; + } + i++; + } + + free(aces); + *saces = new_aces; + + LOG(log_debug7, logtype_afpd, "strip_trivial_aces: non-trivial ACEs: %d", nontrivaces); + + return nontrivaces; +} + +/* + Remove non-trivial ACEs "in-place". Returns no of trivial ACEs. +*/ +int strip_nontrivial_aces(ace_t **saces, int sacecount) +{ + int i,j; + int trivaces = 0; + ace_t *aces = *saces; + ace_t *new_aces; + + /* Count trivial ACEs */ + for (i=0; i < sacecount; ) { + if ((aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE))) + trivaces++; + i++; + } + /* malloc buffer for new ACL */ + if ((new_aces = malloc(trivaces * sizeof(ace_t))) == NULL) { + LOG(log_error, logtype_afpd, "strip_nontrivial_aces: malloc %s", strerror(errno)); + return -1; + } + + /* Copy trivial ACEs */ + for (i=0, j=0; i < sacecount; ) { + if ((aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE))) { + memcpy(&new_aces[j], &aces[i], sizeof(ace_t)); + j++; + } + i++; + } + /* Free old ACEs */ + free(aces); + *saces = new_aces; + + LOG(log_debug7, logtype_afpd, "strip_nontrivial_aces: trivial ACEs: %d", trivaces); + + return trivaces; +} + +/*! + * Change mode of file preserving existing explicit ACEs + * + * nfsv4_chmod + * (1) reads objects ACL (acl1), may return 0 or -1 NFSv4 ACEs on eg UFS fs + * (2) removes all trivial ACEs from the ACL by calling strip_trivial_aces(), possibly + * leaving 0 ACEs in the ACL if there were only trivial ACEs as mapped from the mode + * (3) calls chmod() with mode, we're done if step (1) returned 0 for noaces + * (4) reads the changed ACL (acl2) which + * a) might still contain explicit ACEs (up to onnv132) + * b) will have any explicit ACE removed (starting with onnv145/Openindiana) + * (5) strip any explicit ACE from acl2 using strip_nontrivial_aces() + * (6) merge acl2 and acl2 + * (7) set the ACL merged ACL on the object + */ +int nfsv4_chmod(char *name, mode_t mode) +{ + int ret = -1; + int noaces, nnaces; + ace_t *oacl = NULL, *nacl = NULL, *cacl = NULL; + + LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o)", + getcwdpath(), name, mode); + + if ((noaces = get_nfsv4_acl(name, &oacl)) < 1) /* (1) */ + return chmod(name, mode); + + if ((noaces = strip_trivial_aces(&oacl, noaces)) == -1) /* (2) */ + goto exit; + + if (chmod(name, mode) != 0) /* (3) */ + goto exit; + + if ((nnaces = get_nfsv4_acl(name, &nacl)) == -1) {/* (4) */ + if (errno != EACCES) + goto exit; + become_root(); + nnaces = get_nfsv4_acl(name, &nacl); + unbecome_root(); + if (nnaces == -1) + goto exit; + } + + if ((nnaces = strip_nontrivial_aces(&nacl, nnaces)) == -1) /* (5) */ + goto exit; + + if ((cacl = concat_aces(oacl, noaces, nacl, nnaces)) == NULL) /* (6) */ + goto exit; + + if ((ret = acl(name, ACE_SETACL, noaces + nnaces, cacl)) != 0) { + if (errno != EACCES) { + LOG(log_error, logtype_afpd, "nfsv4_chmod: error setting acl: %s", strerror(errno)); + goto exit; + } + become_root(); + ret = acl(name, ACE_SETACL, noaces + nnaces, cacl); + unbecome_root(); + if (ret != 0) { + LOG(log_error, logtype_afpd, "nfsv4_chmod: error setting acl: %s", strerror(errno)); + goto exit; + } + } + +exit: + if (oacl) free(oacl); + if (nacl) free(nacl); + if (cacl) free(cacl); + + LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o): result: %d", + getcwdpath(), name, mode, ret); + + return ret; +} + +#endif /* HAVE_NFSV4_ACLS */ + +#ifdef HAVE_POSIX_ACLS + +/* This is a workaround for chmod() on filestystems supporting Posix 1003.1e draft 17 + * compliant ACLs. For objects with extented ACLs, eg objects with an ACL_MASK entry, + * chmod() manipulates ACL_MASK instead of ACL_GROUP_OBJ. As OS X isn't aware of + * this behavior calling FPSetFileDirParms may lead to unpredictable results. For + * more information see section 23.1.2 of Posix 1003.1e draft 17. + * + * posix_chmod() accepts the same arguments as chmod() and returns 0 in case of + * success or -1 in case something went wrong. + */ + +#define SEARCH_GROUP_OBJ 0x01 +#define SEARCH_MASK 0x02 + +int posix_chmod(const char *name, mode_t mode) { + int ret = 0; + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t entry; + acl_entry_t group_entry; + acl_tag_t tag; + acl_t acl; + u_char not_found = (SEARCH_GROUP_OBJ|SEARCH_MASK); /* used as flags */ + + LOG(log_maxdebug, logtype_afpd, "posix_chmod(\"%s\", mode: %04o) BEGIN", + fullpathname(name), mode); + + /* Call chmod() first because there might be some special bits to be set which + * aren't related to access control. + */ +#ifdef BSD4_4 + /* + * On FreeBSD chmod_acl() ends up in here too, but on + * FreeBSD sine ~9.1 with ZFS doesn't allow setting the g+s bit. + * Fixes PR #491. + */ + mode &= 0777; +#endif + ret = chmod(name, mode); + + if (ret) + goto done; + + /* Check if the underlying filesystem supports ACLs. */ + acl = acl_get_file(name, ACL_TYPE_ACCESS); + + if (acl) { + /* There is no need to keep iterating once we have found ACL_GROUP_OBJ and ACL_MASK. */ + while ((acl_get_entry(acl, entry_id, &entry) == 1) && not_found) { + entry_id = ACL_NEXT_ENTRY; + + ret = acl_get_tag_type(entry, &tag); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_chmod: Failed to get tag type."); + goto cleanup; + } + + switch (tag) { + case ACL_GROUP_OBJ: + group_entry = entry; + not_found &= ~SEARCH_GROUP_OBJ; + break; + + case ACL_MASK: + not_found &= ~SEARCH_MASK; + break; + + default: + break; + } + } + if (!not_found) { + /* The filesystem object has extented ACLs. We have to update ACL_GROUP_OBJ + * with the group permissions. + */ + acl_permset_t permset; + acl_perm_t perm = 0; + + ret = acl_get_permset(group_entry, &permset); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_chmod: Can't get permset."); + goto cleanup; + } + ret = acl_clear_perms(permset); + + if (ret) + goto cleanup; + + if (mode & S_IXGRP) + perm |= ACL_EXECUTE; + + if (mode & S_IWGRP) + perm |= ACL_WRITE; + + if (mode & S_IRGRP) + perm |= ACL_READ; + + ret = acl_add_perm(permset, perm); + + if (ret) + goto cleanup; + + ret = acl_set_permset(group_entry, permset); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_chmod: Can't set permset."); + goto cleanup; + } + /* also update ACL_MASK */ + ret = acl_calc_mask(&acl); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_chmod: acl_calc_mask failed."); + goto cleanup; + } + ret = acl_set_file(name, ACL_TYPE_ACCESS, acl); + } +cleanup: + acl_free(acl); + } +done: + LOG(log_maxdebug, logtype_afpd, "posix_chmod(\"%s\", mode: %04o): END: %d", + fullpathname(name), mode, ret); + return ret; +} + +/* + * posix_fchmod() accepts the same arguments as fchmod() and returns 0 in case of + * success or -1 in case something went wrong. + */ +int posix_fchmod(int fd, mode_t mode) { + int ret = 0; + int entry_id = ACL_FIRST_ENTRY; + acl_entry_t entry; + acl_entry_t group_entry; + acl_tag_t tag; + acl_t acl; + u_char not_found = (SEARCH_GROUP_OBJ|SEARCH_MASK); /* used as flags */ + + /* Call chmod() first because there might be some special bits to be set which + * aren't related to access control. + */ + ret = fchmod(fd, mode); + + if (ret) + goto done; + + /* Check if the underlying filesystem supports ACLs. */ + acl = acl_get_fd(fd); + + if (acl) { + /* There is no need to keep iterating once we have found ACL_GROUP_OBJ and ACL_MASK. */ + while ((acl_get_entry(acl, entry_id, &entry) == 1) && not_found) { + entry_id = ACL_NEXT_ENTRY; + + ret = acl_get_tag_type(entry, &tag); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_fchmod: Failed to get tag type."); + goto cleanup; + } + + switch (tag) { + case ACL_GROUP_OBJ: + group_entry = entry; + not_found &= ~SEARCH_GROUP_OBJ; + break; + + case ACL_MASK: + not_found &= ~SEARCH_MASK; + break; + + default: + break; + } + } + if (!not_found) { + /* The filesystem object has extented ACLs. We have to update ACL_GROUP_OBJ + * with the group permissions. + */ + acl_permset_t permset; + acl_perm_t perm = 0; + + ret = acl_get_permset(group_entry, &permset); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_fchmod: Can't get permset."); + goto cleanup; + } + ret = acl_clear_perms(permset); + + if (ret) + goto cleanup; + + if (mode & S_IXGRP) + perm |= ACL_EXECUTE; + + if (mode & S_IWGRP) + perm |= ACL_WRITE; + + if (mode & S_IRGRP) + perm |= ACL_READ; + + ret = acl_add_perm(permset, perm); + + if (ret) + goto cleanup; + + ret = acl_set_permset(group_entry, permset); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_fchmod: Can't set permset."); + goto cleanup; + } + /* also update ACL_MASK */ + ret = acl_calc_mask(&acl); + + if (ret) { + LOG(log_error, logtype_afpd, "posix_fchmod: acl_calc_mask failed."); + goto cleanup; + } + ret = acl_set_fd(fd, acl); + } +cleanup: + acl_free(acl); + } +done: + return ret; +} + +#endif /* HAVE_POSIX_ACLS */ + +#endif /* HAVE_ACLS */ diff --git a/libatalk/acl/uuid.c b/libatalk/acl/uuid.c new file mode 100644 index 0000000..ff58c3d --- /dev/null +++ b/libatalk/acl/uuid.c @@ -0,0 +1,304 @@ +/* + Copyright (c) 2008,2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "aclldap.h" +#include "cache.h" + +char *uuidtype[] = {"", "USER", "GROUP", "LOCAL"}; + +/******************************************************** + * Public helper function + ********************************************************/ + +static unsigned char local_group_uuid[] = {0xab, 0xcd, 0xef, + 0xab, 0xcd, 0xef, + 0xab, 0xcd, 0xef, + 0xab, 0xcd, 0xef}; + +static unsigned char local_user_uuid[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, + 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa}; + +void localuuid_from_id(unsigned char *buf, uuidtype_t type, unsigned int id) +{ + uint32_t tmp; + + switch (type) { + case UUID_GROUP: + memcpy(buf, local_group_uuid, 12); + break; + case UUID_USER: + default: + memcpy(buf, local_user_uuid, 12); + break; + } + + tmp = htonl(id); + memcpy(buf + 12, &tmp, 4); + + return; +} + +/* + * convert ascii string that can include dashes to binary uuid. + * caller must provide a buffer. + */ +void uuid_string2bin( const char *uuidstring, unsigned char *uuid) { + int nibble = 1; + int i = 0; + unsigned char c, val = 0; + + while (*uuidstring && i < UUID_BINSIZE) { + c = *uuidstring; + if (c == '-') { + uuidstring++; + continue; + } + else if (c <= '9') /* 0-9 */ + c -= '0'; + else if (c <= 'F') /* A-F */ + c -= 'A' - 10; + else if (c <= 'f') /* a-f */ + c-= 'a' - 10; + + if (nibble) + val = c * 16; + else + uuid[i++] = val + c; + + nibble ^= 1; + uuidstring++; + } + +} + +/*! + * Convert 16 byte binary uuid to neat ascii represantation including dashes. + * Use defined or default ascii mask for dash placement + * Returns pointer to static buffer. + */ +const char *uuid_bin2string(const unsigned char *uuid) { + static char uuidstring[64]; + const char *uuidmask; + int i = 0; + unsigned char c; + +#ifdef HAVE_LDAP + if (ldap_uuid_string) + uuidmask = ldap_uuid_string; + else +#endif + uuidmask = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + + LOG(log_debug, logtype_afpd, "uuid_bin2string{uuid}: mask: %s", uuidmask); + + while (i < strlen(uuidmask)) { + c = *uuid; + uuid++; + sprintf(uuidstring + i, "%02X", c); + i += 2; + if (uuidmask[i] == '-') + uuidstring[i++] = '-'; + } + uuidstring[i] = 0; + return uuidstring; +} + +/******************************************************** + * Interface + ********************************************************/ + +/* + * name: give me his name + * type: and type (UUID_USER or UUID_GROUP) + * uuid: pointer to uuid_t storage that the caller must provide + * returns 0 on success !=0 on errror + */ +int getuuidfromname( const char *name, uuidtype_t type, unsigned char *uuid) { + int ret = 0; + uuidtype_t mytype = type; + char nulluuid[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; +#ifdef HAVE_LDAP + char *uuid_string = NULL; +#endif + + ret = search_cachebyname(name, &mytype, uuid); + + if (ret == 0) { + /* found in cache */ + LOG(log_debug, logtype_afpd, + "getuuidfromname{cache}: name: %s, type%s: %s -> UUID: %s", + name, + (mytype & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "", + uuidtype[type & UUIDTYPESTR_MASK], + uuid_bin2string(uuid)); + if ((mytype & UUID_ENOENT) == UUID_ENOENT) + return -1; + } else { + /* if not found in cache */ +#ifdef HAVE_LDAP + if ((ret = ldap_getuuidfromname( name, type, &uuid_string)) == 0) { + uuid_string2bin( uuid_string, uuid); + LOG(log_debug, logtype_afpd, "getuuidfromname{LDAP}: name: %s, type: %s -> UUID: %s", + name, uuidtype[type & UUIDTYPESTR_MASK], uuid_bin2string(uuid)); + } else { + LOG(log_debug, logtype_afpd, "getuuidfromname(\"%s\",t:%u): no result from ldap search", + name, type); + } +#endif + if (ret != 0) { + /* Build a local UUID */ + if (type == UUID_USER) { + struct passwd *pwd; + if ((pwd = getpwnam(name)) == NULL) { + LOG(log_error, logtype_afpd, "getuuidfromname(\"%s\",t:%u): unknown user", + name, uuidtype[type & UUIDTYPESTR_MASK]); + mytype |= UUID_ENOENT; + memcpy(uuid, nulluuid, 16); + } else { + localuuid_from_id(uuid, UUID_USER, pwd->pw_uid); + ret = 0; + LOG(log_debug, logtype_afpd, "getuuidfromname{local}: name: %s, type: %s -> UUID: %s", + name, uuidtype[type & UUIDTYPESTR_MASK], uuid_bin2string(uuid)); + } + } else { + struct group *grp; + if ((grp = getgrnam(name)) == NULL) { + LOG(log_error, logtype_afpd, "getuuidfromname(\"%s\",t:%u): unknown user", + name, uuidtype[type & UUIDTYPESTR_MASK]); + mytype |= UUID_ENOENT; + memcpy(uuid, nulluuid, 16); + } else { + localuuid_from_id(uuid, UUID_GROUP, grp->gr_gid); + ret = 0; + LOG(log_debug, logtype_afpd, "getuuidfromname{local}: name: %s, type: %s -> UUID: %s", + name, uuidtype[type & UUIDTYPESTR_MASK], uuid_bin2string(uuid)); + } + } + } + add_cachebyname(name, uuid, mytype, 0); + } + +#ifdef HAVE_LDAP + if (uuid_string) free(uuid_string); +#endif + return ret; +} + + +/* + * uuidp: pointer to a uuid + * name: returns allocated buffer from ldap_getnamefromuuid + * type: returns USER, GROUP or LOCAL + * return 0 on success !=0 on errror + * + * Caller must free name appropiately. + */ +int getnamefromuuid(const uuidp_t uuidp, char **name, uuidtype_t *type) { + int ret; + uid_t uid; + gid_t gid; + uint32_t tmp; + struct passwd *pwd; + struct group *grp; + + if (search_cachebyuuid(uuidp, name, type) == 0) { + /* found in cache */ + LOG(log_debug, logtype_afpd, + "getnamefromuuid{cache}: UUID: %s -> name: %s, type%s: %s", + uuid_bin2string(uuidp), + *name, + (*type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "", + uuidtype[(*type) & UUIDTYPESTR_MASK]); + if ((*type & UUID_ENOENT) == UUID_ENOENT) + return -1; + return 0; + } + + /* not found in cache */ + + /* Check if UUID is a client local one */ + if (memcmp(uuidp, local_user_uuid, 12) == 0) { + *type = UUID_USER; + memcpy(&tmp, uuidp + 12, sizeof(uint32_t)); + uid = ntohl(tmp); + if ((pwd = getpwuid(uid)) == NULL) { + /* not found, add negative entry to cache */ + *name = NULL; + add_cachebyuuid(uuidp, "UUID_ENOENT", UUID_ENOENT, 0); + ret = -1; + } else { + *name = strdup(pwd->pw_name); + add_cachebyuuid(uuidp, *name, *type, 0); + ret = 0; + } + LOG(log_debug, logtype_afpd, + "getnamefromuuid{local}: UUID: %s -> name: %s, type:%s", + uuid_bin2string(uuidp), *name ? *name : "-", uuidtype[(*type) & UUIDTYPESTR_MASK]); + return ret; + } else if (memcmp(uuidp, local_group_uuid, 12) == 0) { + *type = UUID_GROUP; + memcpy(&tmp, uuidp + 12, sizeof(uint32_t)); + gid = ntohl(tmp); + if ((grp = getgrgid(gid)) == NULL) { + /* not found, add negative entry to cache */ + add_cachebyuuid(uuidp, "UUID_ENOENT", UUID_ENOENT, 0); + ret = -1; + } else { + *name = strdup(grp->gr_name); + add_cachebyuuid(uuidp, *name, *type, 0); + ret = 0; + } + return ret; + } + +#ifdef HAVE_LDAP + ret = ldap_getnamefromuuid(uuid_bin2string(uuidp), name, type); +#else + ret = -1; +#endif + + if (ret != 0) { + LOG(log_debug, logtype_afpd, "getnamefromuuid(%s): not found", + uuid_bin2string(uuidp)); + add_cachebyuuid(uuidp, "UUID_ENOENT", UUID_ENOENT, 0); + return -1; + } + + add_cachebyuuid(uuidp, *name, *type, 0); + + LOG(log_debug, logtype_afpd, "getnamefromuuid{LDAP}: UUID: %s -> name: %s, type:%s", + uuid_bin2string(uuidp), *name, uuidtype[(*type) & UUIDTYPESTR_MASK]); + + return 0; +} diff --git a/libatalk/adouble/Makefile.am b/libatalk/adouble/Makefile.am new file mode 100644 index 0000000..1ae2366 --- /dev/null +++ b/libatalk/adouble/Makefile.am @@ -0,0 +1,19 @@ +# Makefile.am for libatalk/adouble/ + +noinst_LTLIBRARIES = libadouble.la + +libadouble_la_SOURCES = \ + ad_attr.c \ + ad_conv.c \ + ad_date.c \ + ad_flush.c \ + ad_lock.c \ + ad_mmap.c \ + ad_open.c \ + ad_read.c \ + ad_recvfile.c \ + ad_sendfile.c \ + ad_size.c \ + ad_write.c + +noinst_HEADERS = ad_lock.h diff --git a/libatalk/adouble/Makefile.in b/libatalk/adouble/Makefile.in new file mode 100644 index 0000000..4ffed18 --- /dev/null +++ b/libatalk/adouble/Makefile.in @@ -0,0 +1,690 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/adouble/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/adouble +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libadouble_la_LIBADD = +am_libadouble_la_OBJECTS = ad_attr.lo ad_conv.lo ad_date.lo \ + ad_flush.lo ad_lock.lo ad_mmap.lo ad_open.lo ad_read.lo \ + ad_recvfile.lo ad_sendfile.lo ad_size.lo ad_write.lo +libadouble_la_OBJECTS = $(am_libadouble_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libadouble_la_SOURCES) +DIST_SOURCES = $(libadouble_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libadouble.la +libadouble_la_SOURCES = \ + ad_attr.c \ + ad_conv.c \ + ad_date.c \ + ad_flush.c \ + ad_lock.c \ + ad_mmap.c \ + ad_open.c \ + ad_read.c \ + ad_recvfile.c \ + ad_sendfile.c \ + ad_size.c \ + ad_write.c + +noinst_HEADERS = ad_lock.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/adouble/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/adouble/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libadouble.la: $(libadouble_la_OBJECTS) $(libadouble_la_DEPENDENCIES) $(EXTRA_libadouble_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libadouble_la_OBJECTS) $(libadouble_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_attr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_conv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_date.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_flush.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_lock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_mmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_open.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_read.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_recvfile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_sendfile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_size.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ad_write.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/adouble/ad_attr.c b/libatalk/adouble/ad_attr.c new file mode 100644 index 0000000..43d798b --- /dev/null +++ b/libatalk/adouble/ad_attr.c @@ -0,0 +1,176 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#define FILEIOFF_ATTR 14 +#define AFPFILEIOFF_ATTR 2 + +/* + Note: + the "shared" and "invisible" attributes are opaque and stored and + retrieved from the FinderFlags. This fixes Bug #2802236: + + */ +int ad_getattr(const struct adouble *ad, uint16_t *attr) +{ + uint16_t fflags; + *attr = 0; + + if (ad_getentryoff(ad, ADEID_AFPFILEI)) { + memcpy(attr, ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, 2); + + /* Now get opaque flags from FinderInfo */ + memcpy(&fflags, ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, 2); + if (fflags & htons(FINDERINFO_INVISIBLE)) + *attr |= htons(ATTRBIT_INVISIBLE); + else + *attr &= htons(~ATTRBIT_INVISIBLE); + /* + * This one is tricky, I actually got it wrong the first time: + * for directories bit 1<<1 is ATTRBIT_EXPFLDR and is NOT opaque ! + */ + if ( ! (ad->ad_adflags & ADFLAGS_DIR)) { + if (fflags & htons(FINDERINFO_ISHARED)) + *attr |= htons(ATTRBIT_MULTIUSER); + else + *attr &= htons(~ATTRBIT_MULTIUSER); + } + } + + *attr |= htons(ad->ad_open_forks); + + return 0; +} + +/* ----------------- */ +int ad_setattr(const struct adouble *ad, const uint16_t attribute) +{ + uint16_t fflags; + + /* we don't save open forks indicator */ + uint16_t attr = attribute & ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN); + + /* Proactively (10.4 does indeed try to set ATTRBIT_MULTIUSER (=ATTRBIT_EXPFLDR) + for dirs with SetFile -a M ) disable all flags not defined for dirs. */ + if (ad->ad_adflags & ADFLAGS_DIR) + attr &= ~(ATTRBIT_MULTIUSER | ATTRBIT_NOWRITE | ATTRBIT_NOCOPY); + + if (ad_getentryoff(ad, ADEID_AFPFILEI) && ad_getentryoff(ad, ADEID_FINDERI)) { + memcpy(ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, &attr, sizeof(attr)); + + /* Now set opaque flags in FinderInfo too */ + memcpy(&fflags, ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, 2); + if (attr & htons(ATTRBIT_INVISIBLE)) + fflags |= htons(FINDERINFO_INVISIBLE); + else + fflags &= htons(~FINDERINFO_INVISIBLE); + + /* See above comment in ad_getattr() */ + if (attr & htons(ATTRBIT_MULTIUSER)) { + if ( ! (ad->ad_adflags & ADFLAGS_DIR) ) + fflags |= htons(FINDERINFO_ISHARED); + } else + fflags &= htons(~FINDERINFO_ISHARED); + + memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &fflags, 2); + } + + return 0; +} + +/* -------------- + * save file/folder ID in AppleDoubleV2 netatalk private parameters + * return 1 if resource fork has been modified + */ +int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const uint32_t id, const cnid_t did, const void *stamp) +{ + uint32_t tmp; + + ad_setentrylen( adp, ADEID_PRIVID, sizeof(id)); + tmp = id; + if (adp->ad_vers == AD_VERSION_EA) + tmp = htonl(tmp); + memcpy(ad_entry( adp, ADEID_PRIVID ), &tmp, sizeof(tmp)); + + ad_setentrylen( adp, ADEID_PRIVDEV, sizeof(dev_t)); + if ((adp->ad_options & ADVOL_NODEV)) { + memset(ad_entry( adp, ADEID_PRIVDEV ), 0, sizeof(dev_t)); + } else { + memcpy(ad_entry( adp, ADEID_PRIVDEV ), &dev, sizeof(dev_t)); + } + + ad_setentrylen( adp, ADEID_PRIVINO, sizeof(ino_t)); + memcpy(ad_entry( adp, ADEID_PRIVINO ), &ino, sizeof(ino_t)); + + ad_setentrylen( adp, ADEID_DID, sizeof(did)); + memcpy(ad_entry( adp, ADEID_DID ), &did, sizeof(did)); + + ad_setentrylen( adp, ADEID_PRIVSYN, ADEDLEN_PRIVSYN); + memcpy(ad_entry( adp, ADEID_PRIVSYN ), stamp, ADEDLEN_PRIVSYN); + + return 1; +} + +/* ----------------------------- */ +uint32_t ad_getid (struct adouble *adp, const dev_t st_dev, const ino_t st_ino , const cnid_t did, const void *stamp _U_) +{ + uint32_t aint = 0; + dev_t dev; + ino_t ino; + cnid_t a_did; + + if (adp) { + if (sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)) { + memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t)); + memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t)); + memcpy(&a_did, ad_entry(adp, ADEID_DID), sizeof(cnid_t)); + + if (((adp->ad_options & ADVOL_NODEV) || (dev == st_dev)) + && ino == st_ino + && (!did || a_did == did) ) { + memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint)); + if (adp->ad_vers == AD_VERSION2) + return aint; + else + return ntohl(aint); + } + } + } + return 0; +} + +/* ----------------------------- */ +uint32_t ad_forcegetid (struct adouble *adp) +{ + uint32_t aint = 0; + + if (adp) { + memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint)); + if (adp->ad_vers == AD_VERSION2) + return aint; + else + return ntohl(aint); + } + return 0; +} + +/* ----------------- + * set resource fork filename attribute. + */ +int ad_setname(struct adouble *ad, const char *path) +{ + int len; + if ((len = strlen(path)) > ADEDLEN_NAME) + len = ADEDLEN_NAME; + if (path && ad_getentryoff(ad, ADEID_NAME)) { + ad_setentrylen( ad, ADEID_NAME, len); + memcpy(ad_entry( ad, ADEID_NAME ), path, len); + return 1; + } + return 0; +} diff --git a/libatalk/adouble/ad_conv.c b/libatalk/adouble/ad_conv.c new file mode 100644 index 0000000..43f4332 --- /dev/null +++ b/libatalk/adouble/ad_conv.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2012 Frank Lahm + * + * 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. + */ + +/*! + * @file + * Part of Netatalk's AppleDouble implementatation + * @sa include/atalk/adouble.h + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ad_lock.h" + +static char emptyfilad[32] = {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}; + +static char emptydirad[32] = {0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,1,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0}; + +static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol) +{ + EC_INIT; + struct adouble adv2; + struct adouble adea; + int adflags; + uint32_t ctime, mtime, afpinfo = 0; + char *emptyad; + + LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path)); + + switch (S_IFMT & sp->st_mode) { + case S_IFREG: + case S_IFDIR: + break; + default: + return 0; + } + + ad_init(&adea, vol); + ad_init_old(&adv2, AD_VERSION2, adea.ad_options); + + adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0; + + /* Open and lock adouble:v2 file */ + EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) ); + + EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) ); + EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) ); + + /* Check if it's a non-empty header */ + if (S_ISREG(sp->st_mode)) + emptyad = &emptyfilad[0]; + else + emptyad = &emptydirad[0]; + + if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0) + goto copy; + if (ad_getentryoff(&adv2, ADEID_FINDERI) + && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI) + && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0)) + goto copy; + if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) { + EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) ); + EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) ); + if ((ctime != mtime) || (mtime != sp->st_mtime)) + goto copy; + } + if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) { + if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0) + goto copy; + } + + LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret); + goto EC_CLEANUP; + +copy: + /* Create a adouble:ea meta EA */ + LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret); + EC_ZERO_LOGSTR( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE), + "ad_conv_v22ea_hf(\"%s\"): error creating metadata EA: %s", + fullpathname(path), strerror(errno)); + EC_ZERO_LOG( ad_copy_header(&adea, &adv2) ); + ad_flush(&adea); + +EC_CLEANUP: + EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) ); + EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) ); + LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret); + EC_EXIT; +} + +static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol) +{ + EC_INIT; + struct adouble adv2; + struct adouble adea; + + LOG(log_debug, logtype_ad,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path)); + + switch (S_IFMT & sp->st_mode) { + case S_IFREG: + break; + default: + return 0; + } + + if (S_ISDIR(sp->st_mode)) + return 0; + + ad_init(&adea, vol); + ad_init_old(&adv2, AD_VERSION2, adea.ad_options); + + /* Open and lock adouble:v2 file */ + EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) ); + + if (adv2.ad_rlen > 0) { + EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) ); + + /* Create a adouble:ea resource fork */ + EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_RF|ADFLAGS_RDWR|ADFLAGS_CREATE|ADFLAGS_SETSHRMD, 0666) ); + + EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) ); + adea.ad_rlen = adv2.ad_rlen; + ad_flush(&adea); + fchmod(ad_reso_fileno(&adea), sp->st_mode & 0666); + fchown(ad_reso_fileno(&adea), sp->st_uid, sp->st_gid); + } + +EC_CLEANUP: + EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) ); + EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) ); + LOG(log_debug, logtype_ad,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret); + EC_EXIT; +} + +static int ad_conv_v22ea(const char *path, const struct stat *sp, const struct vol *vol) +{ + EC_INIT; + const char *adpath; + int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0; + + become_root(); + + if (ad_conv_v22ea_hf(path, sp, vol) != 0) + goto delete; + if (ad_conv_v22ea_rf(path, sp, vol) != 0) + goto delete; + +delete: + EC_NULL( adpath = ad_path(path, adflags) ); + LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"", + path, fullpathname(adpath)); + + unlink(adpath); + +EC_CLEANUP: + if (errno == ENOENT) + EC_STATUS(0); + + unbecome_root(); + + EC_EXIT; +} + +/*! + * Remove hexencoded dots and slashes (":2e" and ":2f") + */ +static int ad_conv_dehex(const char *path, const struct stat *sp, const struct vol *vol, const char **newpathp) +{ + EC_INIT; + static char buf[MAXPATHLEN]; + int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0; + bstring newpath = NULL; + static bstring str2e = NULL; + static bstring str2f = NULL; + static bstring strdot = NULL; + static bstring strcolon = NULL; + char *newadpath = NULL; + + if (str2e == NULL) { + str2e = bfromcstr(":2e"); + str2f = bfromcstr(":2f"); + strdot = bfromcstr("."); + strcolon = bfromcstr(":"); + } + + LOG(log_debug, logtype_ad,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path)); + + *newpathp = NULL; + + if (((strstr(path, ":2e")) == NULL) && ((strstr(path, ":2f")) == NULL) ) + goto EC_CLEANUP; + + EC_NULL( newpath = bfromcstr(path) ); + + EC_ZERO( bfindreplace(newpath, str2e, strdot, 0) ); + EC_ZERO( bfindreplace(newpath, str2f, strcolon, 0) ); + + become_root(); + if (adflags != ADFLAGS_DIR) { + if ((newadpath = strdup(vol->ad_path(bdata(newpath), 0))) == NULL) { + unbecome_root(); + EC_FAIL; + } + rename(vol->ad_path(path, 0), newadpath); + } + rename(path, bdata(newpath)); + unbecome_root(); + + strlcpy(buf, bdata(newpath), sizeof(buf)); + *newpathp = buf; + +EC_CLEANUP: + if (newpath) + bdestroy(newpath); + if (newadpath) + free(newadpath); + EC_EXIT; +} + +/*! + * AppleDouble and encoding conversion on the fly + * + * @param path (r) path to file or directory + * @param sp (r) stat(path) + * @param vol (r) volume handle + * @param newpath (w) if encoding changed, new name. Can be NULL. + * + * @returns -1 on internal error, otherwise 0. newpath is NULL if no character conversion was done, + * otherwise newpath points to a static string with the converted name + */ +int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath) +{ + EC_INIT; + const char *p; + + LOG(log_debug, logtype_ad,"ad_convert(\"%s\"): BEGIN", fullpathname(path)); + + if (newpath) + *newpath = NULL; + + if (vol->v_flags & AFPVOL_RO) + EC_EXIT_STATUS(0); + + if ((vol->v_adouble == AD_VERSION_EA) && !(vol->v_flags & AFPVOL_NOV2TOEACONV)) + EC_ZERO( ad_conv_v22ea(path, sp, vol) ); + + if (vol->v_adouble == AD_VERSION_EA) { + EC_ZERO( ad_conv_dehex(path, sp, vol, &p) ); + if (p && newpath) + *newpath = p; + } + +EC_CLEANUP: + LOG(log_debug, logtype_ad,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret); + EC_EXIT; +} + diff --git a/libatalk/adouble/ad_date.c b/libatalk/adouble/ad_date.c new file mode 100644 index 0000000..304642d --- /dev/null +++ b/libatalk/adouble/ad_date.c @@ -0,0 +1,44 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +int ad_setdate(struct adouble *ad, + unsigned int dateoff, uint32_t date) +{ + int xlate = (dateoff & AD_DATE_UNIX); + + dateoff &= AD_DATE_MASK; + if (xlate) + date = AD_DATE_FROM_UNIX(date); + + if (!ad_getentryoff(ad, ADEID_FILEDATESI)) + return -1; + + if (dateoff > AD_DATE_ACCESS) + return -1; + memcpy(ad_entry(ad, ADEID_FILEDATESI) + dateoff, &date, sizeof(date)); + + return 0; +} + +int ad_getdate(const struct adouble *ad, + unsigned int dateoff, uint32_t *date) +{ + int xlate = (dateoff & AD_DATE_UNIX); + + dateoff &= AD_DATE_MASK; + if (!ad_getentryoff(ad, ADEID_FILEDATESI)) + return -1; + + if (dateoff > AD_DATE_ACCESS) + return -1; + memcpy(date, ad_entry(ad, ADEID_FILEDATESI) + dateoff, sizeof(uint32_t)); + + if (xlate) + *date = AD_DATE_TO_UNIX(*date); + return 0; +} diff --git a/libatalk/adouble/ad_flush.c b/libatalk/adouble/ad_flush.c new file mode 100644 index 0000000..f049876 --- /dev/null +++ b/libatalk/adouble/ad_flush.c @@ -0,0 +1,489 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * Copyright (c) 2010 Frank Lahm + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ad_lock.h" + +static const uint32_t set_eid[] = { + 0,1,2,3,4,5,6,7,8, + 9,10,11,12,13,14,15, + AD_DEV, AD_INO, AD_SYN, AD_ID +}; + +#define EID_DISK(a) (set_eid[a]) + +/* + * Prepare ad->ad_data buffer from struct adouble for writing on disk + */ +int ad_rebuild_adouble_header_v2(struct adouble *ad) +{ + uint32_t eid; + uint32_t temp; + uint16_t nent; + char *buf, *nentp; + + LOG(log_debug, logtype_ad, "ad_rebuild_adouble_header_v2"); + + buf = ad->ad_data; + + temp = htonl( ad->ad_magic ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_version ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + buf += sizeof( ad->ad_filler ); + + nentp = buf; + buf += sizeof( nent ); + for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) { + if (ad->ad_eid[ eid ].ade_off == 0) + continue; + temp = htonl( EID_DISK(eid) ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_eid[ eid ].ade_off ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_eid[ eid ].ade_len ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + nent++; + } + nent = htons( nent ); + memcpy(nentp, &nent, sizeof( nent )); + + return ad_getentryoff(ad, ADEID_RFORK); +} + +int ad_rebuild_adouble_header_ea(struct adouble *ad) +{ + uint32_t eid; + uint32_t temp; + uint16_t nent; + char *buf, *nentp; + + LOG(log_debug, logtype_ad, "ad_rebuild_adouble_header_ea"); + + buf = ad->ad_data; + + temp = htonl( ad->ad_magic ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_version ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + buf += sizeof( ad->ad_filler ); + + nentp = buf; + buf += sizeof( nent ); + for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) { + if ((ad->ad_eid[ eid ].ade_off == 0) || (eid == ADEID_RFORK)) + continue; + temp = htonl( EID_DISK(eid) ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_eid[ eid ].ade_off ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_eid[ eid ].ade_len ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + nent++; + } + nent = htons( nent ); + memcpy(nentp, &nent, sizeof( nent )); + + return AD_DATASZ_EA; +} + +/*! + * Prepare adbuf buffer from struct adouble for writing on disk + */ +int ad_rebuild_adouble_header_osx(struct adouble *ad, char *adbuf) +{ + uint32_t temp; + uint16_t nent; + char *buf; + + LOG(log_debug, logtype_ad, "ad_rebuild_adouble_header_osx"); + + buf = &adbuf[0]; + + temp = htonl( ad->ad_magic ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_version ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + memcpy(buf, AD_FILLER_NETATALK, strlen(AD_FILLER_NETATALK)); + buf += sizeof( ad->ad_filler ); + + nent = htons(ADEID_NUM_OSX); + memcpy(buf, &nent, sizeof( nent )); + buf += sizeof( nent ); + + /* FinderInfo */ + temp = htonl(EID_DISK(ADEID_FINDERI)); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl(ADEDOFF_FINDERI_OSX); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl(ADEDLEN_FINDERI); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + memcpy(adbuf + ADEDOFF_FINDERI_OSX, ad_entry(ad, ADEID_FINDERI), ADEDLEN_FINDERI); + + /* rfork */ + temp = htonl( EID_DISK(ADEID_RFORK) ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl(ADEDOFF_RFORK_OSX); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_rlen); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + return AD_DATASZ_OSX; +} + +/* ------------------- + * XXX copy only header with same size or comment + * doesn't work well for adouble with different version. + * + */ +int ad_copy_header(struct adouble *add, struct adouble *ads) +{ + uint32_t eid; + uint32_t len; + + for ( eid = 0; eid < ADEID_MAX; eid++ ) { + if ( ads->ad_eid[ eid ].ade_off == 0 || add->ad_eid[ eid ].ade_off == 0 ) + continue; + + len = ads->ad_eid[ eid ].ade_len; + if (len == 0) + continue; + + switch (eid) { + case ADEID_COMMENT: + case ADEID_RFORK: + continue; + default: + ad_setentrylen( add, eid, len ); + memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len ); + } + } + add->ad_rlen = ads->ad_rlen; + + if (((ads->ad_vers == AD_VERSION2) && (add->ad_vers == AD_VERSION_EA)) + || ((ads->ad_vers == AD_VERSION_EA) && (add->ad_vers == AD_VERSION2))) { + cnid_t id; + memcpy(&id, ad_entry(add, ADEID_PRIVID), sizeof(cnid_t)); + id = htonl(id); + memcpy(ad_entry(add, ADEID_PRIVID), &id, sizeof(cnid_t)); + } + return 0; +} + +static int ad_flush_hf(struct adouble *ad) +{ + EC_INIT; + int len; + int cwd = -1; + + LOG(log_debug, logtype_ad, "ad_flush_hf(%s)", adflags2logstr(ad->ad_adflags)); + + struct ad_fd *adf; + + switch (ad->ad_vers) { + case AD_VERSION2: + adf = ad->ad_mdp; + break; + case AD_VERSION_EA: + adf = &ad->ad_data_fork; + break; + default: + LOG(log_error, logtype_ad, "ad_flush: unexpected adouble version"); + return -1; + } + + if ((adf->adf_flags & O_RDWR) + || ((ad->ad_adflags & ADFLAGS_DIR) && (ad->ad_adflags & ADFLAGS_RDWR))) { + if (ad_getentryoff(ad, ADEID_RFORK)) { + if (ad->ad_rlen > 0xffffffff) + ad_setentrylen(ad, ADEID_RFORK, 0xffffffff); + else + ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen); + } + len = ad->ad_ops->ad_rebuild_header(ad); + + switch (ad->ad_vers) { + case AD_VERSION2: + if (adf_pwrite(ad->ad_mdp, ad->ad_data, len, 0) != len) { + if (errno == 0) + errno = EIO; + return( -1 ); + } + break; + case AD_VERSION_EA: + if (AD_META_OPEN(ad)) { + if (ad->ad_adflags & ADFLAGS_DIR) { + EC_NEG1_LOG( cwd = open(".", O_RDONLY) ); + EC_NEG1_LOG( fchdir(ad_data_fileno(ad)) ); + + ret = sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0); + + if (ret != 0) { + if (errno != EPERM) + EC_FAIL; + + if (!(ad->ad_options & ADVOL_FORCE_STICKY_XATTR)) + EC_FAIL; + + /* + * This may be a directory with a sticky bit + * set, which means even though we may have + * write access to the directory, only the + * owner is allowed to write xattrs + */ + + become_root(); + ret = sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0); + unbecome_root(); + + if (ret != 0) { + LOG(log_error, logtype_ad, "ad_flush_hf: %s", strerror(errno)); + EC_FAIL; + } + } + + EC_NEG1_LOG( fchdir(cwd) ); + EC_NEG1_LOG( close(cwd) ); + cwd = -1; + } else { + EC_ZERO_LOG( sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) ); + } + } + break; + default: + LOG(log_error, logtype_ad, "ad_flush: unexpected adouble version"); + return -1; + } + } + +EC_CLEANUP: + if (cwd != -1) { + if (fchdir(cwd) != 0) { + AFP_PANIC("ad_flush: cant fchdir"); + } + close(cwd); + } + EC_EXIT; +} + +/* Flush resofork adouble file if any (currently adouble:ea and #ifndef HAVE_EAFD eg Linux) */ +static int ad_flush_rf(struct adouble *ad) +{ + ssize_t len; + char adbuf[AD_DATASZ_OSX]; + +#ifdef HAVE_EAFD + return 0; +#endif + if (ad->ad_vers != AD_VERSION_EA) + return 0; + + LOG(log_debug, logtype_ad, "ad_flush_rf(%s)", adflags2logstr(ad->ad_adflags)); + + if ((ad->ad_rfp->adf_flags & O_RDWR)) { + if (ad_getentryoff(ad, ADEID_RFORK)) { + if (ad->ad_rlen > 0xffffffff) + ad_setentrylen(ad, ADEID_RFORK, 0xffffffff); + else + ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen); + } + len = ad_rebuild_adouble_header_osx(ad, &adbuf[0]); + + if (adf_pwrite(ad->ad_rfp, adbuf, len, 0) != len) { + if (errno == 0) + errno = EIO; + return -1; + } + } + return 0; +} + +int ad_flush(struct adouble *ad) +{ + EC_INIT; + + LOG(log_debug, logtype_ad, "ad_flush(%s)", adflags2logstr(ad->ad_adflags)); + + if (AD_META_OPEN(ad)) { + EC_ZERO( ad_flush_hf(ad) ); + } + + if (AD_RSRC_OPEN(ad)) { + EC_ZERO( ad_flush_rf(ad) ); + } + +EC_CLEANUP: + EC_EXIT; +} + +static int ad_data_closefd(struct adouble *ad) +{ + int ret = 0; + + if (ad_data_fileno(ad) == AD_SYMLINK) { + free(ad->ad_data_fork.adf_syml); + ad->ad_data_fork.adf_syml = NULL; + } else { + if (close(ad_data_fileno(ad)) < 0) + ret = -1; + } + ad_data_fileno(ad) = -1; + return ret; +} + +/*! + * Close a struct adouble freeing all resources + */ +int ad_close(struct adouble *ad, int adflags) +{ + int err = 0; + + if (ad == NULL) + return err; + + + LOG(log_debug, logtype_ad, + "ad_close(%s): BEGIN: {d: %d, m: %d, r: %d} " + "[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + adflags2logstr(adflags), + ad->ad_data_refcount, ad->ad_meta_refcount, ad->ad_reso_refcount, + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + if (adflags & (ADFLAGS_SETSHRMD | ADFLAGS_CHECK_OF)) { + /* sharemode locks are stored in the data fork, adouble:v2 needs this extra handling */ + adflags |= ADFLAGS_DF; + } + + if ((ad->ad_vers == AD_VERSION2) && (adflags & ADFLAGS_RF)) + adflags |= ADFLAGS_HF; + + if ((adflags & ADFLAGS_DF) && (ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == AD_SYMLINK)) { + if (ad->ad_data_refcount) + if (--ad->ad_data_refcount == 0) + adf_lock_free(&ad->ad_data_fork); + if (--ad->ad_data_fork.adf_refcount == 0) { + if (ad_data_closefd(ad) < 0) + err = -1; + } + } + + if ((adflags & ADFLAGS_HF) && (ad_meta_fileno(ad) != -1)) { + if (ad->ad_meta_refcount) + ad->ad_meta_refcount--; + if (!(--ad->ad_mdp->adf_refcount)) { + if (close( ad_meta_fileno(ad)) < 0) + err = -1; + ad_meta_fileno(ad) = -1; + } + } + + if (adflags & ADFLAGS_RF) { + /* HF is automatically opened when opening an RF, close it. */ + if ((ad->ad_vers == AD_VERSION2) && (ad_meta_fileno(ad) != -1)) { + if (ad->ad_meta_refcount) + ad->ad_meta_refcount--; + if (!(--ad->ad_mdp->adf_refcount)) { + if (close( ad_meta_fileno(ad)) < 0) + err = -1; + ad_meta_fileno(ad) = -1; + } + } + + if (ad->ad_reso_refcount) + if (--ad->ad_reso_refcount == 0) + adf_lock_free(ad->ad_rfp); + if (ad->ad_vers == AD_VERSION_EA) { + if ((ad_reso_fileno(ad) != -1) + && !(--ad->ad_rfp->adf_refcount)) { + if (close(ad->ad_rfp->adf_fd) < 0) + err = -1; + ad->ad_rlen = 0; + ad_reso_fileno(ad) = -1; + } + } + } + + LOG(log_debug, logtype_ad, + "ad_close(%s): END: %d {d: %d, m: %d, r: %d} " + "[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + adflags2logstr(adflags), err, + ad->ad_data_refcount, ad->ad_meta_refcount, ad->ad_reso_refcount, + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + return err; +} diff --git a/libatalk/adouble/ad_lock.c b/libatalk/adouble/ad_lock.c new file mode 100644 index 0000000..173adc4 --- /dev/null +++ b/libatalk/adouble/ad_lock.c @@ -0,0 +1,660 @@ +/* + * Copyright (c) 1998,1999 Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT for more information. + * + * Because fcntl locks are + * process-oriented, we need to keep around a list of file descriptors + * that refer to the same file. + * + * TODO: fix the race when reading/writing. + * keep a pool of both locks and reference counters around so that + * we can save on mallocs. we should also use a tree to keep things + * sorted. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "ad_lock.h" + +static const char *shmdstrfromoff(off_t off) +{ + switch (off) { + case AD_FILELOCK_OPEN_WR: + return "OPEN_WR_DATA"; + case AD_FILELOCK_OPEN_RD: + return "OPEN_RD_DATA"; + case AD_FILELOCK_RSRC_OPEN_WR: + return "OPEN_WR_RSRC"; + case AD_FILELOCK_RSRC_OPEN_RD: + return "OPEN_RD_RSRC"; + case AD_FILELOCK_DENY_WR: + return "DENY_WR_DATA"; + case AD_FILELOCK_DENY_RD: + return "DENY_RD_DATA"; + case AD_FILELOCK_RSRC_DENY_WR: + return "DENY_WR_RSRC"; + case AD_FILELOCK_RSRC_DENY_RD: + return "DENY_RD_RSRC"; + case AD_FILELOCK_OPEN_NONE: + return "OPEN_NONE_DATA"; + case AD_FILELOCK_RSRC_OPEN_NONE: + return "OPEN_NONE_RSRC"; + default: + return "-"; + } +} + +/* ----------------------- */ +static int set_lock(int fd, int cmd, struct flock *lock) +{ + EC_INIT; + + LOG(log_debug, logtype_ad, "set_lock(fd: %d, %s, %s, off: %jd (%s), len: %jd): BEGIN", + fd, cmd == F_SETLK ? "F_SETLK" : "F_GETLK", + lock->l_type == F_RDLCK ? "F_RDLCK" : lock->l_type == F_WRLCK ? "F_WRLCK" : "F_UNLCK", + (intmax_t)lock->l_start, + shmdstrfromoff(lock->l_start), + (intmax_t)lock->l_len); + + if (fd == AD_SYMLINK) { + if (cmd == F_GETLK) + lock->l_type = F_UNLCK; + return 0; + } + + EC_NEG1( fcntl(fd, cmd, lock) ); + +EC_CLEANUP: + EC_EXIT; +} + +/* ----------------------- */ +static int XLATE_FCNTL_LOCK(int type) +{ + switch(type) { + case ADLOCK_RD: + return F_RDLCK; + case ADLOCK_WR: + return F_WRLCK; + case ADLOCK_CLR: + return F_UNLCK; + } + return -1; +} + +/* ----------------------- */ +static int OVERLAP(off_t a, off_t alen, off_t b, off_t blen) +{ + return (!alen && a <= b) || + (!blen && b <= a) || + ( (a + alen > b) && (b + blen > a) ); +} + +/* allocation for lock regions. we allocate aggressively and shrink + * only in large chunks. */ +#define ARRAY_BLOCK_SIZE 10 +#define ARRAY_FREE_DELTA 100 + +/* remove a lock and compact space if necessary */ +static void adf_freelock(struct ad_fd *ad, const int i) +{ + adf_lock_t *lock = ad->adf_lock + i; + + if (--(*lock->refcount) < 1) { + free(lock->refcount); + lock->lock.l_type = F_UNLCK; + set_lock(ad->adf_fd, F_SETLK, &lock->lock); /* unlock */ + } + + ad->adf_lockcount--; + + /* move another lock into the empty space */ + if (i < ad->adf_lockcount) { + memcpy(lock, lock + ad->adf_lockcount - i, sizeof(adf_lock_t)); + } + + /* free extra cruft if we go past a boundary. we always want to + * keep at least some stuff around for allocations. this wastes + * a bit of space to save time on reallocations. */ + if ((ad->adf_lockmax > ARRAY_FREE_DELTA) && + (ad->adf_lockcount + ARRAY_FREE_DELTA < ad->adf_lockmax)) { + struct adf_lock_t *tmp; + + tmp = (struct adf_lock_t *) + realloc(ad->adf_lock, sizeof(adf_lock_t)* + (ad->adf_lockcount + ARRAY_FREE_DELTA)); + if (tmp) { + ad->adf_lock = tmp; + ad->adf_lockmax = ad->adf_lockcount + ARRAY_FREE_DELTA; + } + } +} + + +/* this needs to deal with the following cases: + * 1) free all UNIX byterange lock from any fork + * 2) free all locks of the requested fork + * + * i converted to using arrays of locks. everytime a lock + * gets removed, we shift all of the locks down. + */ +static void adf_unlock(struct adouble *ad, struct ad_fd *adf, const int fork, int unlckbrl) +{ + adf_lock_t *lock = adf->adf_lock; + int i; + + for (i = 0; i < adf->adf_lockcount; i++) { + if ((unlckbrl && lock[i].lock.l_start < AD_FILELOCK_BASE) + || lock[i].user == fork) { + /* we're really going to delete this lock. note: read locks + are the only ones that allow refcounts > 1 */ + adf_freelock(adf, i); + /* we shifted things down, so we need to backtrack */ + i--; + /* unlikely but realloc may have change adf_lock */ + lock = adf->adf_lock; + } + } +} + +/* relock any byte lock that overlaps off/len. unlock everything + * else. */ +static void adf_relockrange(struct ad_fd *ad, int fd, off_t off, off_t len) +{ + adf_lock_t *lock = ad->adf_lock; + int i; + + for (i = 0; i < ad->adf_lockcount; i++) { + if (OVERLAP(off, len, lock[i].lock.l_start, lock[i].lock.l_len)) + set_lock(fd, F_SETLK, &lock[i].lock); + } +} + + +/* find a byte lock that overlaps off/len for a particular open fork */ +static int adf_findlock(struct ad_fd *ad, + const int fork, const int type, + const off_t off, + const off_t len) +{ + adf_lock_t *lock = ad->adf_lock; + int i; + + for (i = 0; i < ad->adf_lockcount; i++) { + if ((((type & ADLOCK_RD) && (lock[i].lock.l_type == F_RDLCK)) || + ((type & ADLOCK_WR) && (lock[i].lock.l_type == F_WRLCK))) && + (lock[i].user == fork) && + OVERLAP(off, len, lock[i].lock.l_start, lock[i].lock.l_len)) { + return i; + } + } + return -1; +} + + +/* search other fork lock lists */ +static int adf_findxlock(struct ad_fd *ad, + const int fork, const int type, + const off_t off, + const off_t len) +{ + adf_lock_t *lock = ad->adf_lock; + int i; + + for (i = 0; i < ad->adf_lockcount; i++) { + if ((((type & ADLOCK_RD) && (lock[i].lock.l_type == F_RDLCK)) + || + ((type & ADLOCK_WR) && (lock[i].lock.l_type == F_WRLCK))) + && + (lock[i].user != fork) + && + OVERLAP(off, len, lock[i].lock.l_start, lock[i].lock.l_len)) + return i; + } + return -1; +} + +/* okay, this needs to do the following: + * 1) check current list of locks. error on conflict. + * 2) apply the lock. error on conflict with another process. + * 3) update the list of locks this file has. + * + * NOTE: this treats synchronization locks a little differently. we + * do the following things for those: + * 1) if the header file exists, all the locks go in the beginning + * of that. + * 2) if the header file doesn't exist, we stick the locks + * in the locations specified by AD_FILELOCK_RD/WR. + */ + +/* -------------- + translate a resource fork lock to an offset +*/ +static off_t rf2off(off_t off) +{ + off_t start = off; + if (off == AD_FILELOCK_OPEN_WR) + start = AD_FILELOCK_RSRC_OPEN_WR; + else if (off == AD_FILELOCK_OPEN_RD) + start = AD_FILELOCK_RSRC_OPEN_RD; + else if (off == AD_FILELOCK_DENY_RD) + start = AD_FILELOCK_RSRC_DENY_RD; + else if (off == AD_FILELOCK_DENY_WR) + start = AD_FILELOCK_RSRC_DENY_WR; + else if (off == AD_FILELOCK_OPEN_NONE) + start = AD_FILELOCK_RSRC_OPEN_NONE; + return start; +} + +/*! + * Test a lock + * + * (1) Test against our own locks array + * (2) Test fcntl lock, locks from other processes + * + * @param adf (r) handle + * @param off (r) offset + * @param len (r) lenght + * + * @returns 1 if there's an existing lock, 0 if there's no lock, + * -1 in case any error occured + */ +static int testlock(const struct ad_fd *adf, off_t off, off_t len) +{ + struct flock lock; + adf_lock_t *plock; + int i; + + lock.l_start = off; + + plock = adf->adf_lock; + lock.l_whence = SEEK_SET; + lock.l_len = len; + + /* (1) Do we have a lock ? */ + for (i = 0; i < adf->adf_lockcount; i++) { + if (OVERLAP(lock.l_start, 1, plock[i].lock.l_start, plock[i].lock.l_len)) + return 1; + } + + /* (2) Does another process have a lock? */ + lock.l_type = (adf->adf_flags & O_RDWR) ? F_WRLCK : F_RDLCK; + + if (set_lock(adf->adf_fd, F_GETLK, &lock) < 0) { + /* is that kind of error possible ?*/ + return (errno == EACCES || errno == EAGAIN) ? 1 : -1; + } + + if (lock.l_type == F_UNLCK) { + return 0; + } + return 1; +} + +#define LTYPE2STRBUFSIZ 128 +static const char *locktypetostr(int type) +{ + int first = 1; + static char buf[LTYPE2STRBUFSIZ]; + + buf[0] = 0; + + if (type == 0) { + strlcat(buf, "CLR", LTYPE2STRBUFSIZ); + first = 0; + return buf; + } + if (type & ADLOCK_RD) { + if (!first) + strlcat(buf, "|", LTYPE2STRBUFSIZ); + strlcat(buf, "RD", LTYPE2STRBUFSIZ); + first = 0; + } + if (type & ADLOCK_WR) { + if (!first) + strlcat(buf, "|", LTYPE2STRBUFSIZ); + strlcat(buf, "WR", LTYPE2STRBUFSIZ); + first = 0; + } + if (type & ADLOCK_UPGRADE) { + if (!first) + strlcat(buf, "|", LTYPE2STRBUFSIZ); + strlcat(buf, "UPG", LTYPE2STRBUFSIZ); + first = 0; + } + if (type & ADLOCK_FILELOCK) { + if (!first) + strlcat(buf, "|", LTYPE2STRBUFSIZ); + strlcat(buf, "FILELOCK", LTYPE2STRBUFSIZ); + first = 0; + } + + return buf; +} + +/****************************************************************************** + * Public functions + ******************************************************************************/ + +int ad_lock(struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t len, int fork) +{ + struct flock lock; + struct ad_fd *adf; + adf_lock_t *adflock; + int oldlock; + int i; + int type; + int ret = 0, fcntl_lock_err = 0; + + LOG(log_debug, logtype_ad, "ad_lock(%s, %s, off: %jd (%s), len: %jd): BEGIN", + eid == ADEID_DFORK ? "data" : "reso", + locktypetostr(locktype), + (intmax_t)off, + shmdstrfromoff(off), + (intmax_t)len); + + if ((locktype & ADLOCK_FILELOCK) && (len != 1)) + AFP_PANIC("lock API error"); + + type = locktype; + + if (eid == ADEID_DFORK) { + adf = &ad->ad_data_fork; + lock.l_start = off; + } else { /* rfork */ + if (type & ADLOCK_FILELOCK) { + adf = &ad->ad_data_fork; + lock.l_start = rf2off(off); + } else { + adf = ad->ad_rfp; + lock.l_start = off + ad_getentryoff(ad, ADEID_RFORK); + } + } + + /* NOTE: we can't write lock a read-only file. on those, we just + * make sure that we have a read lock set. that way, we at least prevent + * someone else from really setting a deny read/write on the file. + */ + if (!(adf->adf_flags & O_RDWR) && (type & ADLOCK_WR)) { + type = (type & ~ADLOCK_WR) | ADLOCK_RD; + } + + lock.l_type = XLATE_FCNTL_LOCK(type & ADLOCK_MASK); + lock.l_whence = SEEK_SET; + lock.l_len = len; + + /* byte_lock(len=-1) lock whole file */ + if (len == BYTELOCK_MAX) { + lock.l_len -= lock.l_start; /* otherwise EOVERFLOW error */ + } + + /* see if it's locked by another fork. + * NOTE: this guarantees that any existing locks must be at most + * read locks. we use ADLOCK_WR/RD because F_RD/WRLCK aren't + * guaranteed to be ORable. */ + if (adf_findxlock(adf, fork, ADLOCK_WR | + ((type & ADLOCK_WR) ? ADLOCK_RD : 0), + lock.l_start, lock.l_len) > -1) { + errno = EACCES; + ret = -1; + goto exit; + } + + /* look for any existing lock that we may have */ + i = adf_findlock(adf, fork, ADLOCK_RD | ADLOCK_WR, lock.l_start, lock.l_len); + adflock = (i < 0) ? NULL : adf->adf_lock + i; + + /* here's what we check for: + 1) we're trying to re-lock a lock, but we didn't specify an update. + 2) we're trying to free only part of a lock. + 3) we're trying to free a non-existent lock. */ + if ( (!adflock && (lock.l_type == F_UNLCK)) + || + (adflock + && !(type & ADLOCK_UPGRADE) + && ((lock.l_type != F_UNLCK) + || (adflock->lock.l_start != lock.l_start) + || (adflock->lock.l_len != lock.l_len) )) + ) { + errno = EINVAL; + ret = -1; + goto exit; + } + + + /* now, update our list of locks */ + /* clear the lock */ + if (lock.l_type == F_UNLCK) { + adf_freelock(adf, i); + goto exit; + } + + /* attempt to lock the file. */ + if (set_lock(adf->adf_fd, F_SETLK, &lock) < 0) { + ret = -1; + goto exit; + } + + /* we upgraded this lock. */ + if (adflock && (type & ADLOCK_UPGRADE)) { + memcpy(&adflock->lock, &lock, sizeof(lock)); + goto exit; + } + + /* it wasn't an upgrade */ + oldlock = -1; + if (lock.l_type == F_RDLCK) { + oldlock = adf_findxlock(adf, fork, ADLOCK_RD, lock.l_start, lock.l_len); + } + + /* no more space. this will also happen if lockmax == lockcount == 0 */ + if (adf->adf_lockmax == adf->adf_lockcount) { + adf_lock_t *tmp = (adf_lock_t *) + realloc(adf->adf_lock, sizeof(adf_lock_t)* + (adf->adf_lockmax + ARRAY_BLOCK_SIZE)); + if (!tmp) { + ret = fcntl_lock_err = -1; + goto exit; + } + adf->adf_lock = tmp; + adf->adf_lockmax += ARRAY_BLOCK_SIZE; + } + adflock = adf->adf_lock + adf->adf_lockcount; + + /* fill in fields */ + memcpy(&adflock->lock, &lock, sizeof(lock)); + adflock->user = fork; + if (oldlock > -1) { + adflock->refcount = (adf->adf_lock + oldlock)->refcount; + } else if ((adflock->refcount = calloc(1, sizeof(int))) == NULL) { + ret = fcntl_lock_err = 1; + goto exit; + } + + (*adflock->refcount)++; + adf->adf_lockcount++; + +exit: + if (ret != 0) { + if (fcntl_lock_err != 0) { + lock.l_type = F_UNLCK; + set_lock(adf->adf_fd, F_SETLK, &lock); + } + } + LOG(log_debug, logtype_ad, "ad_lock: END: %d", ret); + return ret; +} + +int ad_tmplock(struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t len, int fork) +{ + struct flock lock; + struct ad_fd *adf; + int err; + int type; + + LOG(log_debug, logtype_ad, "ad_tmplock(%s, %s, off: %jd (%s), len: %jd): BEGIN", + eid == ADEID_DFORK ? "data" : "reso", + locktypetostr(locktype), + (intmax_t)off, + shmdstrfromoff(off), + (intmax_t)len); + + lock.l_start = off; + type = locktype; + + if (eid == ADEID_DFORK) { + adf = &ad->ad_data_fork; + } else { + adf = &ad->ad_resource_fork; + if (adf->adf_fd == -1) { + /* there's no resource fork. return success */ + err = 0; + goto exit; + } + /* if ADLOCK_FILELOCK we want a lock from offset 0 + * it's used when deleting a file: + * in open we put read locks on meta datas + * in delete a write locks on the whole file + * so if the file is open by somebody else it fails + */ + if (!(type & ADLOCK_FILELOCK)) + lock.l_start += ad_getentryoff(ad, eid); + } + + if (!(adf->adf_flags & O_RDWR) && (type & ADLOCK_WR)) { + type = (type & ~ADLOCK_WR) | ADLOCK_RD; + } + + lock.l_type = XLATE_FCNTL_LOCK(type & ADLOCK_MASK); + lock.l_whence = SEEK_SET; + lock.l_len = len; + + /* see if it's locked by another fork. */ + if (fork && adf_findxlock(adf, fork, + ADLOCK_WR | ((type & ADLOCK_WR) ? ADLOCK_RD : 0), + lock.l_start, lock.l_len) > -1) { + errno = EACCES; + err = -1; + goto exit; + } + + /* okay, we might have ranges byte-locked. we need to make sure that + * we restore the appropriate ranges once we're done. so, we check + * for overlap on an unlock and relock. + * XXX: in the future, all the byte locks will be sorted and contiguous. + * we just want to upgrade all the locks and then downgrade them + * here. */ + err = set_lock(adf->adf_fd, F_SETLK, &lock); + if (!err && (lock.l_type == F_UNLCK)) + adf_relockrange(adf, adf->adf_fd, lock.l_start, len); + +exit: + LOG(log_debug, logtype_ad, "ad_tmplock: END: %d", err); + return err; +} + +/* --------------------- */ +void ad_unlock(struct adouble *ad, const int fork, int unlckbrl) +{ + LOG(log_debug, logtype_ad, "ad_unlock(unlckbrl: %d): BEGIN", unlckbrl); + + if (ad_data_fileno(ad) != -1) { + adf_unlock(ad, &ad->ad_data_fork, fork, unlckbrl); + } + if (ad_reso_fileno(ad) != -1) { + adf_unlock(ad, &ad->ad_resource_fork, fork, unlckbrl); + } + + LOG(log_debug, logtype_ad, "ad_unlock: END"); +} + +/*! + * Test for a share mode lock + * + * @param ad (rw) handle + * @param eid (r) datafork or ressource fork + * @param off (r) sharemode lock to test + * + * @returns 1 if there's an existing lock, 0 if there's no lock, + * -1 in case any error occured + */ +int ad_testlock(struct adouble *ad, int eid, const off_t off) +{ + int ret = 0; + off_t lock_offset; + + LOG(log_debug, logtype_ad, "ad_testlock(%s, off: %jd (%s): BEGIN", + eid == ADEID_DFORK ? "data" : "reso", + (intmax_t)off, + shmdstrfromoff(off)); + + if (eid == ADEID_DFORK) { + lock_offset = off; + } else { /* rfork */ + lock_offset = rf2off(off); + } + + ret = testlock(&ad->ad_data_fork, lock_offset, 1); + + LOG(log_debug, logtype_ad, "ad_testlock: END: %d", ret); + return ret; +} + +/*! + * Return if a file is open by another process. + * + * Optimized for the common case: + * - there's no locks held by another process (clients) + * - or we already know the answer and don't need to test (attrbits) + * + * @param ad (rw) handle + * @param attrbits (r) forks opened by us + * @returns bitflags ATTRBIT_DOPEN | ATTRBIT_ROPEN if + * other process has fork of file opened + */ +uint16_t ad_openforks(struct adouble *ad, uint16_t attrbits) +{ + uint16_t ret = 0; + off_t off; + off_t len; + + if (ad_data_fileno(ad) == -1) + return 0; + + if (!(attrbits & (ATTRBIT_DOPEN | ATTRBIT_ROPEN))) { + /* Test all 4 locks at once */ + off = AD_FILELOCK_OPEN_WR; + len = 4; + if (testlock(&ad->ad_data_fork, off, len) == 0) + return 0; + } + + /* either there's a lock or we already know one fork is open */ + + if (!(attrbits & ATTRBIT_DOPEN)) { + off = AD_FILELOCK_OPEN_WR; + ret = testlock(&ad->ad_data_fork, off, 2) > 0 ? ATTRBIT_DOPEN : 0; + } + + if (!(attrbits & ATTRBIT_ROPEN)) { + off = AD_FILELOCK_RSRC_OPEN_WR; + ret |= testlock(&ad->ad_data_fork, off, 2) > 0? ATTRBIT_ROPEN : 0; + } + + return ret; +} diff --git a/libatalk/adouble/ad_lock.h b/libatalk/adouble/ad_lock.h new file mode 100644 index 0000000..2d15da9 --- /dev/null +++ b/libatalk/adouble/ad_lock.h @@ -0,0 +1,29 @@ +#ifndef LIBATALK_ADOUBLE_AD_PRIVATE_H +#define LIBATALK_ADOUBLE_AD_PRIVATE_H 1 + +#include + +/* this is so that we can keep lists of fds referencing the same file + * around. that way, we can honor locks created by the same process + * with the same file. */ + +#define adf_lock_init(a) do { \ + (a)->adf_lockmax = 0; \ + (a)->adf_lockcount = 0; \ + (a)->adf_lock = NULL; \ + } while (0) + +#define adf_lock_free(a) do { \ + int i; \ + if (!(a)->adf_lock) \ + break; \ + for (i = 0; i < (a)->adf_lockcount; i++) { \ + adf_lock_t *lock = (a)->adf_lock + i; \ + if (--(*lock->refcount) < 1) \ + free(lock->refcount); \ + } \ + free((a)->adf_lock); \ + adf_lock_init(a); \ + } while (0) + +#endif /* libatalk/adouble/ad_private.h */ diff --git a/libatalk/adouble/ad_mmap.c b/libatalk/adouble/ad_mmap.c new file mode 100644 index 0000000..a93ab5a --- /dev/null +++ b/libatalk/adouble/ad_mmap.c @@ -0,0 +1,108 @@ +/* + * ad_mmap provides interfaces to memory mapped files. as this is the + * case, we don't have to deal w/ temporary buffers such as + * ad_data. the ad_mmap routines are designed to not interact w/ the + * ad_read/ad_write routines to avoid confusion. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef USE_MMAPPED_HEADERS +#include + +#include +#include + +#include "ad_lock.h" + +static void *ad_mmap(const size_t length, const int prot, + const int flags, const int fd, + const off_t offset) +{ + return mmap(0, length, prot, flags, fd, offset); +} + +/* this just sets things up for mmap. as mmap can handle offsets, + * we need to reset the file position before handing it off */ +void *ad_mmapread(struct adouble *ad, const u_int32_t eid, + const off_t off, const size_t buflen) +{ + /* data fork */ + if ( eid == ADEID_DFORK ) { + if ( lseek( ad->ad_df.adf_fd, 0, SEEK_SET ) < 0 ) { + perror( "df lseek" ); + return (void *) -1; + } + ad->ad_df.adf_off = 0; + return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_PRIVATE, + ad->ad_df.adf_fd, off); + + } + + /* resource fork */ + if ( lseek( ad->ad_hf.adf_fd, 0, SEEK_SET ) < 0 ) { + perror( "hf lseek" ); + return (void *) -1; + } + ad->ad_hf.adf_off = 0; + return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_PRIVATE, + ad->ad_hf.adf_fd, ad->ad_eid[eid].ade_off + off); +} + + +/* to do writeable mmaps correctly, we actually need to make sure that + * the file to be mapped is large enough. that's what all the initial + * mess is for. */ +void *ad_mmapwrite(struct adouble *ad, const u_int32_t eid, + off_t off, const int end, const size_t buflen) +{ + struct stat st; + + /* data fork */ + if ( eid == ADEID_DFORK ) { + if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) { + return (void *) -1; + } + + if ( end ) { + off = st.st_size - off; + } + + /* make sure the file is large enough */ + if (st.st_size < buflen + off) + ftruncate(ad->ad_df.adf_fd, buflen + off); + + if ( lseek( ad->ad_df.adf_fd, 0, SEEK_SET ) < 0 ) { + return (void *) -1; + } + ad->ad_df.adf_off = 0; + return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_SHARED, + ad->ad_df.adf_fd, off); + } + + + if ( fstat( ad->ad_hf.adf_fd, &st ) < 0 ) { + return (void *) -1; + } + + if ( end ) { + off = ad->ad_eid[ eid ].ade_len - off; + } + + off += ad->ad_eid[eid].ade_off; + + /* make sure the file is large enough */ + if (st.st_size < buflen + off) + ftruncate(ad->ad_hf.adf_fd, buflen + off); + + if ( lseek( ad->ad_hf.adf_fd, 0, SEEK_SET ) < 0 ) { + return (void *) -1; + } + ad->ad_hf.adf_off = 0; + return ad_mmap(buflen, PROT_READ | PROT_WRITE, MAP_SHARED, + ad->ad_hf.adf_fd, off); +} + +#endif diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c new file mode 100644 index 0000000..53ec4eb --- /dev/null +++ b/libatalk/adouble/ad_open.c @@ -0,0 +1,2086 @@ +/* + * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * Copyright (c) 2010 Frank Lahm + * + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + * + */ + +/*! + * @file + * Part of Netatalk's AppleDouble implementatation + * @sa include/atalk/adouble.h + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ad_lock.h" + +#define ADEDOFF_MAGIC (0) +#define ADEDOFF_VERSION (ADEDOFF_MAGIC + ADEDLEN_MAGIC) +#define ADEDOFF_FILLER (ADEDOFF_VERSION + ADEDLEN_VERSION) +#define ADEDOFF_NENTRIES (ADEDOFF_FILLER + ADEDLEN_FILLER) + +/* initial lengths of some of the fields */ +#define ADEDLEN_INIT 0 + +/* i stick things in a slightly different order than their eid order in + * case i ever want to separate RootInfo behaviour from the rest of the + * stuff. */ + +/* ad:v2 */ +#define ADEDOFF_NAME_V2 (AD_HEADER_LEN + ADEID_NUM_V2*AD_ENTRY_LEN) +#define ADEDOFF_COMMENT_V2 (ADEDOFF_NAME_V2 + ADEDLEN_NAME) +#define ADEDOFF_FILEDATESI (ADEDOFF_COMMENT_V2 + ADEDLEN_COMMENT) +#define ADEDOFF_FINDERI_V2 (ADEDOFF_FILEDATESI + ADEDLEN_FILEDATESI) +#define ADEDOFF_DID (ADEDOFF_FINDERI_V2 + ADEDLEN_FINDERI) +#define ADEDOFF_AFPFILEI (ADEDOFF_DID + ADEDLEN_DID) +#define ADEDOFF_SHORTNAME (ADEDOFF_AFPFILEI + ADEDLEN_AFPFILEI) +#define ADEDOFF_PRODOSFILEI (ADEDOFF_SHORTNAME + ADEDLEN_SHORTNAME) +#define ADEDOFF_PRIVDEV (ADEDOFF_PRODOSFILEI + ADEDLEN_PRODOSFILEI) +#define ADEDOFF_PRIVINO (ADEDOFF_PRIVDEV + ADEDLEN_PRIVDEV) +#define ADEDOFF_PRIVSYN (ADEDOFF_PRIVINO + ADEDLEN_PRIVINO) +#define ADEDOFF_PRIVID (ADEDOFF_PRIVSYN + ADEDLEN_PRIVSYN) +#define ADEDOFF_RFORK_V2 (ADEDOFF_PRIVID + ADEDLEN_PRIVID) + +/* ad:ea */ +#define ADEDOFF_FINDERI_EA (AD_HEADER_LEN + ADEID_NUM_EA * AD_ENTRY_LEN) +#define ADEDOFF_COMMENT_EA (ADEDOFF_FINDERI_EA + ADEDLEN_FINDERI) +#define ADEDOFF_FILEDATESI_EA (ADEDOFF_COMMENT_EA + ADEDLEN_COMMENT) +#define ADEDOFF_AFPFILEI_EA (ADEDOFF_FILEDATESI_EA + ADEDLEN_FILEDATESI) +#define ADEDOFF_PRIVDEV_EA (ADEDOFF_AFPFILEI_EA + ADEDLEN_AFPFILEI) +#define ADEDOFF_PRIVINO_EA (ADEDOFF_PRIVDEV_EA + ADEDLEN_PRIVDEV) +#define ADEDOFF_PRIVSYN_EA (ADEDOFF_PRIVINO_EA + ADEDLEN_PRIVINO) +#define ADEDOFF_PRIVID_EA (ADEDOFF_PRIVSYN_EA + ADEDLEN_PRIVSYN) + +/* this is to prevent changing timezones from causing problems with + localtime volumes. the screw-up is 30 years. we use a delta of 5 years */ +#define TIMEWARP_DELTA 157680000 + +struct entry { + uint32_t id, offset, len; +}; + +/* --------------------------- */ +static uid_t default_uid = -1; + +/* Forward declarations */ +static int ad_mkrf(const char *path); +static int ad_header_read(const char *path, struct adouble *ad, const struct stat *hst); +static int ad_header_upgrade(struct adouble *ad, const char *name); + +#ifdef HAVE_EAFD +static int ad_mkrf_ea(const char *path); +#endif +static int ad_header_read_ea(const char *path, struct adouble *ad, const struct stat *hst); +static int ad_header_upgrade_ea(struct adouble *ad, const char *name); +off_t ad_reso_size(const char *path, int adflags, struct adouble *ad); +static int ad_mkrf_osx(const char *path); + + +static struct adouble_fops ad_adouble = { + &ad_path, + &ad_mkrf, + &ad_rebuild_adouble_header_v2, + &ad_header_read, + &ad_header_upgrade, +}; + +static struct adouble_fops ad_adouble_ea = { +#ifdef HAVE_EAFD + &ad_path_ea, + &ad_mkrf_ea, +#else + &ad_path_osx, + &ad_mkrf_osx, +#endif + &ad_rebuild_adouble_header_ea, + &ad_header_read_ea, + &ad_header_upgrade_ea, +}; + +static const struct entry entry_order2[ADEID_NUM_V2 + 1] = { + {ADEID_NAME, ADEDOFF_NAME_V2, ADEDLEN_INIT}, + {ADEID_COMMENT, ADEDOFF_COMMENT_V2, ADEDLEN_INIT}, + {ADEID_FILEDATESI, ADEDOFF_FILEDATESI, ADEDLEN_FILEDATESI}, + {ADEID_FINDERI, ADEDOFF_FINDERI_V2, ADEDLEN_FINDERI}, + {ADEID_DID, ADEDOFF_DID, ADEDLEN_DID}, + {ADEID_AFPFILEI, ADEDOFF_AFPFILEI, ADEDLEN_AFPFILEI}, + {ADEID_SHORTNAME, ADEDOFF_SHORTNAME, ADEDLEN_INIT}, + {ADEID_PRODOSFILEI, ADEDOFF_PRODOSFILEI, ADEDLEN_PRODOSFILEI}, + {ADEID_PRIVDEV, ADEDOFF_PRIVDEV, ADEDLEN_INIT}, + {ADEID_PRIVINO, ADEDOFF_PRIVINO, ADEDLEN_INIT}, + {ADEID_PRIVSYN, ADEDOFF_PRIVSYN, ADEDLEN_INIT}, + {ADEID_PRIVID, ADEDOFF_PRIVID, ADEDLEN_INIT}, + {ADEID_RFORK, ADEDOFF_RFORK_V2, ADEDLEN_INIT}, + {0, 0, 0} +}; + +/* Using Extended Attributes */ +static const struct entry entry_order_ea[ADEID_NUM_EA + 1] = { + {ADEID_FINDERI, ADEDOFF_FINDERI_EA, ADEDLEN_FINDERI}, + {ADEID_COMMENT, ADEDOFF_COMMENT_EA, ADEDLEN_INIT}, + {ADEID_FILEDATESI, ADEDOFF_FILEDATESI_EA, ADEDLEN_FILEDATESI}, + {ADEID_AFPFILEI, ADEDOFF_AFPFILEI_EA, ADEDLEN_AFPFILEI}, + {ADEID_PRIVDEV, ADEDOFF_PRIVDEV_EA, ADEDLEN_INIT}, + {ADEID_PRIVINO, ADEDOFF_PRIVINO_EA, ADEDLEN_INIT}, + {ADEID_PRIVSYN, ADEDOFF_PRIVSYN_EA, ADEDLEN_INIT}, + {ADEID_PRIVID, ADEDOFF_PRIVID_EA, ADEDLEN_INIT}, + {0, 0, 0} +}; + +#define ADFLAGS2LOGSTRBUFSIZ 128 +const char *adflags2logstr(int adflags) +{ + int first = 1; + static char buf[ADFLAGS2LOGSTRBUFSIZ]; + + buf[0] = 0; + + if (adflags & ADFLAGS_DF) { + strlcat(buf, "DF", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_RF) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "RF", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_NORF) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "NORF", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_HF) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "HF", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_NOHF) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "NOHF", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_DIR) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "DIR", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_CHECK_OF) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "OF", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_SETSHRMD) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "SHRMD", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_RDWR) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_RDWR", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_RDONLY) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_RDONLY", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_CREATE) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_CREAT", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_EXCL) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_EXCL", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (adflags & ADFLAGS_TRUNC) { + if (!first) + strlcat(buf, "|", ADFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_TRUNC", ADFLAGS2LOGSTRBUFSIZ); + first = 0; + } + + return buf; +} + +#define OPENFLAGS2LOGSTRBUFSIZ 128 +const char *openflags2logstr(int oflags) +{ + int first = 1; + static char buf[OPENFLAGS2LOGSTRBUFSIZ]; + + buf[0] = 0; + + if ((oflags & O_RDONLY) || (oflags == O_RDONLY)) { + strlcat(buf, "O_RDONLY", OPENFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (oflags & O_RDWR) { + if (!first) + strlcat(buf, "|", OPENFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_RDWR", OPENFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (oflags & O_CREAT) { + if (!first) + strlcat(buf, "|", OPENFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_CREAT", OPENFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (oflags & O_TRUNC) { + if (!first) + strlcat(buf, "|", OPENFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_TRUNC", OPENFLAGS2LOGSTRBUFSIZ); + first = 0; + } + if (oflags & O_EXCL) { + if (!first) + strlcat(buf, "|", OPENFLAGS2LOGSTRBUFSIZ); + strlcat(buf, "O_EXCL", OPENFLAGS2LOGSTRBUFSIZ); + first = 0; + } + return buf; +} + +static uint32_t get_eid(uint32_t eid) +{ + if (eid <= 15) + return eid; + if (eid == AD_DEV) + return ADEID_PRIVDEV; + if (eid == AD_INO) + return ADEID_PRIVINO; + if (eid == AD_SYN) + return ADEID_PRIVSYN; + if (eid == AD_ID) + return ADEID_PRIVID; + + return 0; +} + + +/** + * Initialize offset pointers + */ +int ad_init_offsets(struct adouble *ad) +{ + const struct entry *eid; + + if (ad->ad_magic == AD_MAGIC) + return 0; + + ad->ad_magic = AD_MAGIC; + ad->ad_version = ad->ad_vers & 0x0f0000; + if (!ad->ad_version) { + ad->ad_version = AD_VERSION; + } + + memset(ad->ad_data, 0, sizeof(ad->ad_data)); + + if (ad->ad_vers == AD_VERSION2) + eid = entry_order2; + else if (ad->ad_vers == AD_VERSION_EA) + eid = entry_order_ea; + else + return -1; + + while (eid->id) { + ad->ad_eid[eid->id].ade_off = eid->offset; + ad->ad_eid[eid->id].ade_len = eid->len; + eid++; + } + + /* + * Ensure the resource fork offset is always set + */ +#ifndef HAVE_EAFD + if (ad->ad_vers == AD_VERSION_EA) + ad_setentryoff(ad, ADEID_RFORK, ADEDOFF_RFORK_OSX); +#endif + + return 0; +} + +/* ----------------------------------- */ +static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags) +{ + const struct entry *eid; + uint16_t ashort; + struct stat st; + + LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path); + + if (ad_init_offsets(ad) != 0) + return -1; + + /* set default creator/type fields */ + memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4); + memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4); + + /* make things invisible */ + if ((ad->ad_options & ADVOL_INVDOTS) + && (*path == '.') + && !((adflags & ADFLAGS_DIR) && (path[1] == 0)) + ) { + ashort = htons(ATTRBIT_INVISIBLE); + ad_setattr(ad, ashort); + ashort = htons(FINDERINFO_INVISIBLE); + memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort)); + } + + /* put something sane in the date fields */ + if (stp == NULL) { + stp = &st; + if (lstat(path, &st) != 0) + return -1; + } + ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, stp->st_mtime); + ad_setdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, stp->st_mtime); + ad_setdate(ad, AD_DATE_ACCESS | AD_DATE_UNIX, stp->st_mtime); + ad_setdate(ad, AD_DATE_BACKUP, AD_DATE_START); + + return 0; +} + +/** + * Read an AppleDouble buffer, returns 0 on success, -1 if an entry was malformatted + **/ +static int parse_entries(struct adouble *ad, char *buf, uint16_t nentries) +{ + uint32_t eid, len, off; + int ret = 0; + + /* now, read in the entry bits */ + for (; nentries > 0; nentries-- ) { + memcpy(&eid, buf, sizeof( eid )); + eid = get_eid(ntohl(eid)); + buf += sizeof( eid ); + memcpy(&off, buf, sizeof( off )); + off = ntohl( off ); + buf += sizeof( off ); + memcpy(&len, buf, sizeof( len )); + len = ntohl( len ); + buf += sizeof( len ); + + ad->ad_eid[eid].ade_off = off; + ad->ad_eid[eid].ade_len = len; + + if (!eid + || eid > ADEID_MAX + || off >= sizeof(ad->ad_data) + || ((eid != ADEID_RFORK) && (off + len > sizeof(ad->ad_data)))) + { + ret = -1; + LOG(log_warning, logtype_ad, "parse_entries: bogus eid: %u, off: %u, len: %u", + (uint)eid, (uint)off, (uint)len); + } + } + + return ret; +} + +/* this reads enough of the header so that we can figure out all of + * the entry lengths and offsets. once that's done, we just read/mmap + * the rest of the header in. + * + * NOTE: we're assuming that the resource fork is kept at the end of + * the file. also, mmapping won't work for the hfs fs until it + * understands how to mmap header files. */ +static int ad_header_read(const char *path, struct adouble *ad, const struct stat *hst) +{ + char *buf = ad->ad_data; + uint16_t nentries; + int len; + ssize_t header_len; + struct stat st; + + /* read the header */ + if ((header_len = adf_pread( ad->ad_mdp, buf, AD_DATASZ2, 0)) < 0) { + return -1; + } + if (header_len < AD_HEADER_LEN) { + errno = EIO; + return -1; + } + + memcpy(&ad->ad_magic, buf, sizeof( ad->ad_magic )); + memcpy(&ad->ad_version, buf + ADEDOFF_VERSION, sizeof( ad->ad_version )); + ad->ad_magic = ntohl( ad->ad_magic ); + ad->ad_version = ntohl( ad->ad_version ); + + if ((ad->ad_magic != AD_MAGIC) || (ad->ad_version != AD_VERSION2)) { + LOG(log_error, logtype_ad, "ad_open: can't parse AppleDouble header."); + errno = EIO; + return -1; + } + + memcpy(&nentries, buf + ADEDOFF_NENTRIES, sizeof( nentries )); + nentries = ntohs( nentries ); + + /* read in all the entry headers. if we have more than the + * maximum, just hope that the rfork is specified early on. */ + len = nentries*AD_ENTRY_LEN; + + if (len + AD_HEADER_LEN > sizeof(ad->ad_data)) + len = sizeof(ad->ad_data) - AD_HEADER_LEN; + + buf += AD_HEADER_LEN; + if (len > header_len - AD_HEADER_LEN) { + LOG(log_error, logtype_ad, "ad_header_read: can't read entry info."); + errno = EIO; + return -1; + } + + /* figure out all of the entry offsets and lengths. if we aren't + * able to read a resource fork entry, bail. */ + nentries = len / AD_ENTRY_LEN; + if (parse_entries(ad, buf, nentries) != 0) { + LOG(log_warning, logtype_ad, "ad_header_read(%s): malformed AppleDouble", + path ? fullpathname(path) : ""); + errno = EIO; + return -1; + } + if (!ad_getentryoff(ad, ADEID_RFORK) + || (ad_getentryoff(ad, ADEID_RFORK) > sizeof(ad->ad_data)) + ) { + LOG(log_error, logtype_ad, "ad_header_read: problem with rfork entry offset."); + errno = EIO; + return -1; + } + + if (ad_getentryoff(ad, ADEID_RFORK) > header_len) { + LOG(log_error, logtype_ad, "ad_header_read: can't read in entries."); + errno = EIO; + return -1; + } + + if (hst == NULL) { + hst = &st; + if (fstat(ad->ad_mdp->adf_fd, &st) < 0) { + return 1; /* fail silently */ + } + } + + ad->ad_rlen = hst->st_size - ad_getentryoff(ad, ADEID_RFORK); + + return 0; +} + +/* error here means it's not ad ._ adouble:osx file and thus we return 1 */ +int ad_valid_header_osx(const char *path) +{ + EC_INIT; + int fd = -1; + struct adouble adosx; + char *buf = &adosx.ad_data[0]; + ssize_t header_len; + + LOG(log_debug, logtype_ad, "ad_valid_header_osx(\"%s\"): BEGIN", fullpathname(path)); + + EC_NEG1( fd = open(path, O_RDONLY) ); + + /* read the header */ + EC_NEG1( header_len = read(fd, buf, AD_DATASZ_OSX) ); + + if (header_len < AD_HEADER_LEN) + EC_FAIL; + + memcpy(&adosx.ad_magic, buf, sizeof(adosx.ad_magic)); + memcpy(&adosx.ad_version, buf + ADEDOFF_VERSION, sizeof(adosx.ad_version)); + adosx.ad_magic = ntohl(adosx.ad_magic); + adosx.ad_version = ntohl(adosx.ad_version); + + if ((adosx.ad_magic != AD_MAGIC) || (adosx.ad_version != AD_VERSION2)) { + LOG(log_warning, logtype_ad, "ad_valid_header_osx(\"%s\"): not an adouble:osx file", fullpathname(path)); + EC_FAIL; + } + + if (strncmp(buf + ADEDOFF_FILLER, + AD_FILLER_NETATALK, + strlen(AD_FILLER_NETATALK)) != 0) + /* + * It's a split fork created by OS X, it's not our "own" ._ file + * and thus not a valid header in this context. + * We allow enumeration and access. + */ + EC_FAIL; + +EC_CLEANUP: + LOG(log_debug, logtype_ad, "ad_valid_header_osx(\"%s\"): END: %d", fullpathname(path), ret); + if (fd != -1) + close(fd); + if (ret != 0) + return 1; + return 0; +} + +/** + * Convert from Apple's ._ file to Netatalk + * + * Apple's AppleDouble may contain a FinderInfo entry longer then 32 bytes + * containing packed xattrs. Netatalk can't deal with that, so we + * simply discard the packed xattrs. + * + * As we call ad_open() which might result in a recursion, just to be sure + * use static variable in_conversion to check for that. + * + * Returns -1 in case an error occured, 0 if no conversion was done, 1 otherwise + **/ +static int ad_convert_osx(const char *path, struct adouble *ad) +{ + EC_INIT; + static bool in_conversion = false; + char *map; + int finderlen = ad_getentrylen(ad, ADEID_FINDERI); + ssize_t origlen; + + if (in_conversion || finderlen == ADEDLEN_FINDERI) + return 0; + in_conversion = true; + + LOG(log_debug, logtype_ad, "Converting OS X AppleDouble %s, FinderInfo length: %d", + fullpathname(path), finderlen); + + origlen = ad_getentryoff(ad, ADEID_RFORK) + ad_getentrylen(ad, ADEID_RFORK); + + map = mmap(NULL, origlen, PROT_READ | PROT_WRITE, MAP_SHARED, ad_reso_fileno(ad), 0); + if (map == MAP_FAILED) { + LOG(log_error, logtype_ad, "mmap AppleDouble: %s\n", strerror(errno)); + EC_FAIL; + } + + memmove(map + ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI, + map + ad_getentryoff(ad, ADEID_RFORK), + ad_getentrylen(ad, ADEID_RFORK)); + + ad_setentrylen(ad, ADEID_FINDERI, ADEDLEN_FINDERI); + ad->ad_rlen = ad_getentrylen(ad, ADEID_RFORK); + ad_setentryoff(ad, ADEID_RFORK, ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI); + + EC_ZERO_LOG( ftruncate(ad_reso_fileno(ad), + ad_getentryoff(ad, ADEID_RFORK) + + ad_getentrylen(ad, ADEID_RFORK)) ); + + (void)ad_rebuild_adouble_header_osx(ad, map); + munmap(map, origlen); + + /* Create a metadata EA if one doesn't exit */ + if (strlen(path) < 3) + EC_EXIT_STATUS(0); + struct adouble adea; + ad_init_old(&adea, AD_VERSION_EA, ad->ad_options); + + if (ad_open(&adea, path + 2, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) < 0) { + LOG(log_error, logtype_ad, "create metadata: %s\n", strerror(errno)); + EC_FAIL; + } + if (adea.ad_mdp->adf_flags & O_CREAT) { + memcpy(ad_entry(&adea, ADEID_FINDERI), + ad_entry(ad, ADEID_FINDERI), + ADEDLEN_FINDERI); + ad_flush(&adea); + } + ad_close(&adea, ADFLAGS_HF); + +EC_CLEANUP: + in_conversion = false; + if (ret != 0) + return -1; + return 1; +} + +/* Read an ._ file, only uses the resofork, finderinfo is taken from EA */ +static int ad_header_read_osx(const char *path, struct adouble *ad, const struct stat *hst) +{ + EC_INIT; + struct adouble adosx; + char *buf; + uint16_t nentries; + int len; + ssize_t header_len; + struct stat st; + int retry_read = 0; + +reread: + LOG(log_debug, logtype_ad, "ad_header_read_osx: %s", path ? fullpathname(path) : ""); + ad_init_old(&adosx, AD_VERSION_EA, ad->ad_options); + buf = &adosx.ad_data[0]; + memset(buf, 0, sizeof(adosx.ad_data)); + adosx.ad_rfp->adf_fd = ad_reso_fileno(ad); + + /* read the header */ + EC_NEG1( header_len = adf_pread(ad->ad_rfp, buf, AD_DATASZ_OSX, 0) ); + + if (header_len < AD_HEADER_LEN) { + errno = EIO; + return -1; + } + + memcpy(&adosx.ad_magic, buf, sizeof(adosx.ad_magic)); + memcpy(&adosx.ad_version, buf + ADEDOFF_VERSION, sizeof(adosx.ad_version)); + adosx.ad_magic = ntohl(adosx.ad_magic); + adosx.ad_version = ntohl(adosx.ad_version); + + if ((adosx.ad_magic != AD_MAGIC) || (adosx.ad_version != AD_VERSION2)) { + LOG(log_error, logtype_ad, "ad_header_read_osx: can't parse AppleDouble header"); + errno = EIO; + return -1; + } + + memcpy(&nentries, buf + ADEDOFF_NENTRIES, sizeof( nentries )); + nentries = ntohs(nentries); + len = nentries * AD_ENTRY_LEN; + + if (len + AD_HEADER_LEN > sizeof(adosx.ad_data)) + len = sizeof(adosx.ad_data) - AD_HEADER_LEN; + + buf += AD_HEADER_LEN; + if (len > header_len - AD_HEADER_LEN) { + LOG(log_error, logtype_ad, "ad_header_read_osx: can't read entry info."); + errno = EIO; + return -1; + } + + nentries = len / AD_ENTRY_LEN; + if (parse_entries(&adosx, buf, nentries) != 0) { + LOG(log_warning, logtype_ad, "ad_header_read(%s): malformed AppleDouble", + path ? fullpathname(path) : ""); + } + + if (ad_getentrylen(&adosx, ADEID_FINDERI) != ADEDLEN_FINDERI) { + LOG(log_warning, logtype_ad, "Convert OS X to Netatalk AppleDouble: %s", + path ? fullpathname(path) : ""); + + if (retry_read > 0) { + LOG(log_error, logtype_ad, "ad_header_read_osx: %s, giving up", path ? fullpathname(path) : ""); + errno = EIO; + EC_FAIL; + } + retry_read++; + if (ad_convert_osx(path, &adosx) == 1) { + goto reread; + } + errno = EIO; + EC_FAIL; + } + + if (ad_getentryoff(&adosx, ADEID_RFORK) == 0 + || ad_getentryoff(&adosx, ADEID_RFORK) > sizeof(ad->ad_data) + || ad_getentryoff(&adosx, ADEID_RFORK) > header_len + ) { + LOG(log_error, logtype_ad, "ad_header_read_osx: problem with rfork entry offset."); + errno = EIO; + return -1; + } + + if (hst == NULL) { + hst = &st; + EC_NEG1( fstat(ad_reso_fileno(ad), &st) ); + } + + ad_setentryoff(ad, ADEID_RFORK, ad_getentryoff(&adosx, ADEID_RFORK)); + ad->ad_rlen = hst->st_size - ad_getentryoff(ad, ADEID_RFORK); + +EC_CLEANUP: + EC_EXIT; +} + +static int ad_header_read_ea(const char *path, struct adouble *ad, const struct stat *hst _U_) +{ + EC_INIT; + uint16_t nentries; + int len; + ssize_t header_len; + char *buf = ad->ad_data; + + if (ad_meta_fileno(ad) != -1) + header_len = sys_fgetxattr(ad_meta_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA); + else + header_len = sys_getxattr(path, AD_EA_META, ad->ad_data, AD_DATASZ_EA); + if (header_len < 1) { + LOG(log_debug, logtype_ad, "ad_header_read_ea: %s", strerror(errno)); + EC_FAIL; + } + + if (header_len < AD_DATASZ_EA) { + LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): short metadata EA", fullpathname(path)); + errno = EINVAL; + EC_FAIL; + } + + memcpy(&ad->ad_magic, buf, sizeof( ad->ad_magic )); + memcpy(&ad->ad_version, buf + ADEDOFF_VERSION, sizeof( ad->ad_version )); + + ad->ad_magic = ntohl( ad->ad_magic ); + ad->ad_version = ntohl( ad->ad_version ); + + if ((ad->ad_magic != AD_MAGIC) || (ad->ad_version != AD_VERSION2)) { + LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): wrong magic or version", fullpathname(path)); + errno = EINVAL; + EC_FAIL; + } + + memcpy(&nentries, buf + ADEDOFF_NENTRIES, sizeof( nentries )); + nentries = ntohs( nentries ); + if (nentries != ADEID_NUM_EA) { + LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): invalid number of entries: %d", fullpathname(path), nentries); + errno = EINVAL; + EC_FAIL; + } + + /* Now parse entries */ + if (parse_entries(ad, buf + AD_HEADER_LEN, nentries)) { + LOG(log_warning, logtype_ad, "ad_header_read(%s): malformed AppleDouble", + path ? fullpathname(path) : ""); + errno = EINVAL; + EC_FAIL; + } + + if (nentries != ADEID_NUM_EA + || !ad_entry(ad, ADEID_FINDERI) + || !ad_entry(ad, ADEID_COMMENT) + || !ad_entry(ad, ADEID_FILEDATESI) + || !ad_entry(ad, ADEID_AFPFILEI) + || !ad_entry(ad, ADEID_PRIVDEV) + || !ad_entry(ad, ADEID_PRIVINO) + || !ad_entry(ad, ADEID_PRIVSYN) + || !ad_entry(ad, ADEID_PRIVID)) { + LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): invalid metadata EA", fullpathname(path)); + errno = EINVAL; + EC_FAIL; + } + + /* + * Ensure the resource fork offset is always set + */ +#ifndef HAVE_EAFD + if (ad->ad_vers == AD_VERSION_EA) + ad_setentryoff(ad, ADEID_RFORK, ADEDOFF_RFORK_OSX); +#endif + +EC_CLEANUP: + if (ret != 0 && errno == EINVAL) { + become_root(); + (void)sys_removexattr(path, AD_EA_META); + unbecome_root(); + LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): deleted invalid metadata EA", fullpathname(path), nentries); + errno = ENOENT; + } + EC_EXIT; +} + +/*! + * Takes a path to an AppleDouble file and creates the parrent .AppleDouble directory + * + * Example: + * path: "/path/.AppleDouble/file" + * => mkdir("/path/.AppleDouble/") (in ad_mkdir()) + */ +static int ad_mkrf(const char *path) +{ + char *slash; + /* + * Probably .AppleDouble doesn't exist, try to mkdir it. + */ + if (NULL == ( slash = strrchr( path, '/' )) ) { + return -1; + } + *slash = '\0'; + errno = 0; + if ( ad_mkdir( path, 0777 ) < 0 ) { + return -1; + } + *slash = '/'; + return 0; +} + +#ifdef HAVE_EAFD +static int ad_mkrf_ea(const char *path _U_) +{ + AFP_PANIC("ad_mkrf_ea: dont use"); + return 0; +} +#endif + +static int ad_mkrf_osx(const char *path _U_) +{ + return 0; +} + +/* ---------------- + if we are root change path user/ group + It can be a native function for BSD cf. FAQ.Q10 + path: pathname to chown + stbuf: parent directory inode + + use fstat and fchown or lchown with linux? +*/ +#define EMULATE_SUIDDIR + +static int ad_chown(const char *path, struct stat *stbuf) +{ + int ret = 0; +#ifdef EMULATE_SUIDDIR + uid_t id; + + if (default_uid != (uid_t)-1) { + /* we are root (admin) */ + id = (default_uid)?default_uid:stbuf->st_uid; + ret = lchown( path, id, stbuf->st_gid ); + } +#endif + return ret; +} + +#define DEFMASK 07700 /* be conservative */ + +/* ---------------- + return access right and inode of path parent directory +*/ +static int ad_mode_st(const char *path, mode_t *mode, struct stat *stbuf) +{ + if (*mode == 0) { + return -1; + } + if (ad_stat(path, stbuf) != 0) { + *mode &= DEFMASK; + return -1; + } + *mode &= stbuf->st_mode; + return 0; +} + +/* --------------------------- */ +static int ad_header_upgrade(struct adouble *ad _U_, const char *name _U_) +{ + return 0; +} + +static int ad_header_upgrade_ea(struct adouble *ad _U_, const char *name _U_) +{ + AFP_PANIC("ad_header_upgrade_ea: dont use"); + return 0; +} + +/*! + * Error handling for adouble header(=metadata) file open error + * + * We're called because opening ADFLAGS_HF caused an error. + * 1. In case ad_open is called with ADFLAGS_NOHF the error is suppressed. + * 2. Open non-existent ressource fork, this will just result in first read return EOF + * 3. If ad_open was called with ADFLAGS_DF we may have opened the datafork and thus + * ought to close it before returning with an error condition. + */ +static int ad_error(struct adouble *ad, int adflags) +{ + int err = errno; + if (adflags & ADFLAGS_NOHF) { /* 1 */ + return 0; + } + if ((adflags & ADFLAGS_RDONLY) && (adflags & ADFLAGS_RF) && (errno == ENOENT)) /* 2 */ + return 0; + if (adflags & (ADFLAGS_DF | ADFLAGS_SETSHRMD | ADFLAGS_CHECK_OF)) { /* 3 */ + ad_close( ad, ADFLAGS_DF ); + err = errno; + } + return -1 ; +} + +/*! + * Map ADFLAGS to open() flags + * + * @param adfile (r) the file you really want to open: ADFLAGS_DF or ADFLAGS_HF + * @param adflags (r) flags from ad_open(..., adflags, ...) + * @returns mapped flags suitable for calling open() + */ +static int ad2openflags(const struct adouble *ad, int adfile, int adflags) +{ + int oflags = 0; + + if (adflags & ADFLAGS_RDWR) + oflags |= O_RDWR; + if (adflags & ADFLAGS_RDONLY) { + if (((adfile == ADFLAGS_DF || adfile == ADFLAGS_RF) && (adflags & ADFLAGS_SETSHRMD)) + /* need rw access for locks */ + || ((adfile == ADFLAGS_HF) && (ad->ad_vers == AD_VERSION2))) + /* need rw access for adouble file for the case: + 1) openfork(data+meta:O_RDONLY), 2) openfork(reso(=meta):O_RDWR) */ + oflags |= O_RDWR; + else + oflags |= O_RDONLY; + } + if (adflags & ADFLAGS_CREATE) + oflags |= O_CREAT; + if (adflags & ADFLAGS_EXCL) + oflags |= O_EXCL; + if (adflags & ADFLAGS_TRUNC) + oflags |= O_TRUNC; + + if (!(ad->ad_options & ADVOL_FOLLO_SYML)) + oflags |= O_NOFOLLOW; + + return oflags; +} + +static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble *ad) +{ + EC_INIT; + struct stat st_dir; + int oflags; + mode_t admode; + int st_invalid = -1; + ssize_t lsz; + + LOG(log_debug, logtype_ad, + "ad_open_df(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), adflags2logstr(adflags), + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + if (ad_data_fileno(ad) != -1) { + /* the file is already open, but we want write access: */ + if ((adflags & ADFLAGS_RDWR) + /* and it was denied the first time: */ + && (ad->ad_data_fork.adf_flags & O_RDONLY)) { + errno = EACCES; + return -1; + } + /* it's not new anymore */ + ad->ad_data_fork.adf_flags &= ~( O_TRUNC | O_CREAT ); + ad->ad_data_fork.adf_refcount++; + goto EC_CLEANUP; + } + + oflags = ad2openflags(ad, ADFLAGS_DF, adflags); + + admode = mode; + if ((adflags & ADFLAGS_CREATE)) { + st_invalid = ad_mode_st(path, &admode, &st_dir); + if ((ad->ad_options & ADVOL_UNIXPRIV)) + admode = mode; + } + + ad->ad_data_fork.adf_fd = open(path, oflags, admode); + + if (ad->ad_data_fork.adf_fd == -1) { + switch (errno) { + case EACCES: + case EPERM: + case EROFS: + if ((adflags & ADFLAGS_SETSHRMD) && (adflags & ADFLAGS_RDONLY)) { + oflags &= ~O_RDWR; + oflags |= O_RDONLY; + EC_NEG1( ad->ad_data_fork.adf_fd = open(path, oflags, admode) ); + break; + } + return -1; + case OPEN_NOFOLLOW_ERRNO: + ad->ad_data_fork.adf_syml = malloc(MAXPATHLEN+1); + if ((lsz = readlink(path, ad->ad_data_fork.adf_syml, MAXPATHLEN)) <= 0) { + free(ad->ad_data_fork.adf_syml); + EC_FAIL; + } + ad->ad_data_fork.adf_syml[lsz] = 0; + ad->ad_data_fork.adf_fd = AD_SYMLINK; + break; + default: + EC_FAIL; + } + } + + if (!st_invalid) + ad_chown(path, &st_dir); /* just created, set owner if admin (root) */ + + ad->ad_data_fork.adf_flags = oflags; + adf_lock_init(&ad->ad_data_fork); + ad->ad_data_fork.adf_refcount++; + +EC_CLEANUP: + LOG(log_debug, logtype_ad, + "ad_open_df(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), adflags2logstr(adflags), ret, + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + EC_EXIT; +} + +static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adouble *ad) +{ + EC_INIT; + struct stat st_dir; + struct stat st_meta; + struct stat *pst = NULL; + const char *ad_p; + int oflags, nocreatflags, opened = 0; + mode_t admode; + int st_invalid = -1; + + LOG(log_debug, logtype_ad, + "ad_open_hf_v2(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), adflags2logstr(adflags), + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + if (ad_meta_fileno(ad) != -1) { + /* the file is already open, but we want write access: */ + if ((adflags & ADFLAGS_RDWR) && + /* and it was already denied: */ + (ad->ad_mdp->adf_flags & O_RDONLY)) { + errno = EACCES; + EC_FAIL; + } + ad_refresh(path, ad); + /* it's not new anymore */ + ad->ad_mdp->adf_flags &= ~( O_TRUNC | O_CREAT ); + ad->ad_mdp->adf_refcount++; + goto EC_CLEANUP; + } + + ad_p = ad->ad_ops->ad_path(path, adflags); + oflags = ad2openflags(ad, ADFLAGS_HF, adflags); + LOG(log_debug, logtype_ad,"ad_open_hf_v2(\"%s\"): open flags: %s", + fullpathname(path), openflags2logstr(oflags)); + nocreatflags = oflags & ~(O_CREAT | O_EXCL); + + ad_meta_fileno(ad) = open(ad_p, nocreatflags); + + if (ad_meta_fileno(ad) != -1) { + ad->ad_mdp->adf_flags = nocreatflags; + } else { + switch (errno) { + case EACCES: + case EPERM: + case EROFS: + if ((adflags & ADFLAGS_RDONLY) && (adflags & ADFLAGS_SETSHRMD)) { + nocreatflags &= ~O_RDWR; + nocreatflags |= O_RDONLY; + EC_NEG1( ad_meta_fileno(ad) = open(ad_p, nocreatflags) ); + ad->ad_mdp->adf_flags = nocreatflags; + break; + } + EC_FAIL; + case ENOENT: + if (!(oflags & O_CREAT)) + EC_FAIL; + /* + * We're expecting to create a new adouble header file here + */ + LOG(log_debug, logtype_ad, "ad_open(\"%s\"): creating adouble file", + fullpathname(path)); + admode = mode; + errno = 0; + st_invalid = ad_mode_st(ad_p, &admode, &st_dir); + if ((ad->ad_options & ADVOL_UNIXPRIV)) + admode = mode; + admode = ad_hf_mode(admode); + if (errno == ENOENT) { + EC_NEG1_LOG( ad->ad_ops->ad_mkrf(ad_p) ); + admode = mode; + st_invalid = ad_mode_st(ad_p, &admode, &st_dir); + if ((ad->ad_options & ADVOL_UNIXPRIV)) + admode = mode; + admode = ad_hf_mode(admode); + } + + /* retry with O_CREAT */ + EC_NEG1( ad_meta_fileno(ad) = open(ad_p, oflags, admode) ); + ad->ad_mdp->adf_flags = oflags; + /* just created, set owner if admin owner (root) */ + if (!st_invalid) + ad_chown(ad_p, &st_dir); + break; + default: + EC_FAIL; + } + } + + /* Now we've got a new opened fd, we need to check that in the error case */ + opened = 1; + + if (!(ad->ad_mdp->adf_flags & O_CREAT)) { + /* check for 0 length files, treat them as new. */ + if (fstat(ad->ad_mdp->adf_fd, &st_meta) == 0) { + if (st_meta.st_size == 0) + ad->ad_mdp->adf_flags |= O_TRUNC; + else + /* we have valid data in st_meta stat structure, reused it in ad_header_read */ + pst = &st_meta; + } + } + + adf_lock_init(ad->ad_mdp); + ad->ad_mdp->adf_refcount = 1; + + if ((ad->ad_mdp->adf_flags & ( O_TRUNC | O_CREAT ))) { + /* This is a new adouble header file, create it */ + EC_NEG1_LOG( new_ad_header(ad, path, pst, adflags) ); + ad_flush(ad); + } else { + /* Read the adouble header in and parse it.*/ + EC_NEG1_LOG( ad->ad_ops->ad_header_read(path, ad, pst) ); + } + +EC_CLEANUP: + if (ret != 0 && opened && ad_meta_fileno(ad) != -1) { + close(ad_meta_fileno(ad)); + ad_meta_fileno(ad) = -1; + ad->ad_mdp->adf_refcount = 0; + } + LOG(log_debug, logtype_ad, + "ad_open_hf_v2(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), adflags2logstr(adflags), ret, + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + EC_EXIT; +} + +static int ad_open_hf_ea(const char *path, int adflags, int mode, struct adouble *ad) +{ + EC_INIT; + int oflags; + int opened = 0; + + LOG(log_debug, logtype_ad, + "ad_open_hf_ea(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), adflags2logstr(adflags), + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + oflags = ad2openflags(ad, ADFLAGS_DF, adflags) & ~(O_CREAT | O_TRUNC); + + if (ad_meta_fileno(ad) == AD_SYMLINK) + goto EC_CLEANUP; + + if (ad_meta_fileno(ad) != -1) { + /* the file is already open, but we want write access: */ + if ((oflags & O_RDWR) && + /* and it was already denied: */ + (ad->ad_mdp->adf_flags & O_RDONLY)) { + LOG(log_error, logtype_ad, "ad_open_hf_ea(%s): rw request for ro file: %s", + fullpathname(path), strerror(errno)); + errno = EACCES; + EC_FAIL; + } + /* it's not new anymore */ + ad->ad_mdp->adf_flags &= ~( O_TRUNC | O_CREAT ); + } else { + if (oflags & O_RDWR) { + /* Fo a RDONLY adouble we just use sys_lgetxattr instead if sys_fgetxattr */ + if (adflags & ADFLAGS_DIR) + /* For directories we open the directory RDONYL so we can later fchdir() */ + oflags = (oflags & ~O_RDWR) | O_RDONLY; + LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): opening base file for meta adouble EA", path); + EC_NEG1(ad_meta_fileno(ad) = open(path, oflags)); + opened = 1; + ad->ad_mdp->adf_flags = oflags; + } + } + + /* Read the adouble header in and parse it.*/ + if (ad->ad_ops->ad_header_read(path, ad, NULL) != 0) { + if (!(adflags & ADFLAGS_CREATE)) { + LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): can't read metadata EA", path); + errno = ENOENT; + EC_FAIL; + } + if ((adflags & ADFLAGS_CREATE) && (ad->ad_options & ADVOL_RO)) { + errno = EROFS; + EC_FAIL; + } + + LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): creating metadata EA", path); + + /* It doesnt exist, EPERM or another error */ + if (!(errno == ENOATTR || errno == ENOENT)) { + LOG(log_error, logtype_ad, "ad_open_hf_ea: unexpected: %s", strerror(errno)); + EC_FAIL; + } + + /* Create one */ + EC_NEG1_LOG(new_ad_header(ad, path, NULL, adflags)); + ad->ad_mdp->adf_flags |= O_CREAT; /* mark as just created */ + ad_flush(ad); + LOG(log_debug, logtype_ad, "ad_open_hf_ea(\"%s\"): created metadata EA", path); + } + + if (ad_meta_fileno(ad) != -1) + ad->ad_mdp->adf_refcount++; + ad->ad_rlen = ad_reso_size(path, adflags, ad); + +EC_CLEANUP: + if (ret != 0 && opened && ad_meta_fileno(ad) != -1) { + close(ad_meta_fileno(ad)); + ad_meta_fileno(ad) = -1; + ad->ad_mdp->adf_refcount = 0; + } + LOG(log_debug, logtype_ad, + "ad_open_hf_ea(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), adflags2logstr(adflags), ret, + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + EC_EXIT; +} + +static int ad_open_hf(const char *path, int adflags, int mode, struct adouble *ad) +{ + int ret = 0; + + ad->ad_meta_refcount++; + + switch (ad->ad_vers) { + case AD_VERSION2: + ret = ad_open_hf_v2(path, adflags, mode, ad); + break; + case AD_VERSION_EA: + ret = ad_open_hf_ea(path, adflags, mode, ad); + break; + default: + ret = -1; + break; + } + + if (ret != 0) { + ad->ad_meta_refcount--; + ret = ad_error(ad, adflags); + } + + return ret; +} + +/*! + * Get resofork length for adouble:ea, parameter 'ad' may be NULL + */ +off_t ad_reso_size(const char *path, int adflags, struct adouble *ad) +{ + EC_INIT; + struct stat st; + off_t rlen; + + if (adflags & ADFLAGS_DIR) + EC_FAIL; + + LOG(log_debug, logtype_ad, "ad_reso_size(\"%s\"): BEGIN", path); + +#ifdef HAVE_EAFD + ssize_t easz; + + if (ad && ad_reso_fileno(ad) != -1) { + EC_NEG1( fstat(ad_reso_fileno(ad), &st) ); + rlen = st.st_size; + } else if (ad && ad_meta_fileno(ad) != -1) { + EC_NEG1( (rlen = sys_fgetxattr(ad_meta_fileno(ad), AD_EA_RESO, NULL, 0)) ); + } else { + EC_NEG1( (rlen = sys_lgetxattr(path, AD_EA_RESO, NULL, 0)) ); + } + +#else + const char *rfpath; + EC_NULL_LOG( rfpath = ad_path_osx(path, adflags)); + EC_ZERO( lstat(rfpath, &st)); + if (st.st_size > ADEDOFF_RFORK_OSX) + rlen = st.st_size - ADEDOFF_RFORK_OSX; + else + rlen = 0; +#endif + + LOG(log_debug, logtype_ad, "ad_reso_size(\"%s\"): size: %zd", path, rlen); + +EC_CLEANUP: + if (ret != 0) + rlen = 0; + return rlen; +} + +static int ad_open_rf_v2(const char *path, int adflags, int mode, struct adouble *ad) +{ + EC_INIT; + + /* + * ad_open_hf_v2() does the work, but if it failed and adflags are ADFLAGS_NOHF | ADFLAGS_RF + * ad_open_hf_v2() didn't give an error, but we're supposed to return a reso fork fd + */ + + LOG(log_debug, logtype_ad, "ad_open_rf_v2(\"%s\"): BEGIN", fullpathname(path)); + + if (!AD_META_OPEN(ad) && !(adflags & (ADFLAGS_NORF | ADFLAGS_RDONLY))) + EC_FAIL; + if (AD_META_OPEN(ad)) + ad->ad_reso_refcount++; + +EC_CLEANUP: + LOG(log_debug, logtype_ad, "ad_open_rf_v2(\"%s\"): END: %d", fullpathname(path), ret); + EC_EXIT; +} + +static int ad_open_rf_ea(const char *path, int adflags, int mode, struct adouble *ad) +{ + EC_INIT; + int oflags; + int opened = 0; + int closeflags = adflags & (ADFLAGS_DF | ADFLAGS_HF); +#ifndef HAVE_EAFD + const char *rfpath; + struct stat st; +#endif + + LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): BEGIN", fullpathname(path)); + + oflags = ad2openflags(ad, ADFLAGS_RF, adflags) & ~O_CREAT; + + if (ad_reso_fileno(ad) != -1) { + /* the file is already open, but we want write access: */ + if ((oflags & O_RDWR) + /* and it was already denied: */ + && (ad->ad_rfp->adf_flags & O_RDONLY)) { + errno = EACCES; + EC_FAIL; + } + ad->ad_rfp->adf_flags &= ~( O_TRUNC | O_CREAT ); + ad->ad_reso_refcount++; + ad->ad_rfp->adf_refcount++; + EC_NEG1_LOG( ad->ad_rlen = ad_reso_size(path, adflags, ad)); + goto EC_CLEANUP; + } +#ifdef HAVE_EAFD + if (ad_meta_fileno(ad) < 0) + EC_FAIL; + if ((ad_reso_fileno(ad) = sys_getxattrfd(ad_meta_fileno(ad), AD_EA_RESO, oflags)) == -1) { + if (!(adflags & ADFLAGS_CREATE)) { + switch (errno) { + case EACCES: + case EPERM: + case EROFS: + if (!(adflags & ADFLAGS_RDONLY)) { + LOG(log_error, logtype_ad, "ad_open_rf_ea(\"%s\"): \"%s\"", fullpathname(path), strerror(errno)); + EC_FAIL; + } + oflags &= ~O_RDWR; + oflags |= O_RDONLY; + if ((ad_reso_fileno(ad) = sys_getxattrfd(ad_meta_fileno(ad), AD_EA_RESO, oflags)) == -1) { + LOG(log_error, logtype_ad, "ad_open_rf_ea(\"%s\"): \"%s\"", fullpathname(path), strerror(errno)); + EC_FAIL; + } + break; + case ENOENT: + EC_EXIT_STATUS(0); + default: + LOG(log_error, logtype_ad, "ad_open_rf_ea(\"%s\"): \"%s\"", fullpathname(path), strerror(errno)); + EC_FAIL; + } + } else { + oflags |= O_CREAT; + EC_NEG1_LOG( ad_reso_fileno(ad) = sys_getxattrfd(ad_meta_fileno(ad), + AD_EA_RESO, oflags, 0666) ); + } + } +#else + EC_NULL_LOG( rfpath = ad->ad_ops->ad_path(path, adflags) ); + if ((ad_reso_fileno(ad) = open(rfpath, oflags)) == -1) { + if (!(adflags & ADFLAGS_CREATE)) { + switch (errno) { + case EACCES: + case EPERM: + case EROFS: + if (!(adflags & ADFLAGS_RDONLY)) { + LOG(log_error, logtype_ad, "ad_open_rf_ea(\"%s\"): \"%s\"", fullpathname(rfpath), strerror(errno)); + EC_FAIL; + } + oflags &= ~O_RDWR; + oflags |= O_RDONLY; + if ((ad_reso_fileno(ad) = open(rfpath, oflags)) == -1) { + LOG(log_error, logtype_ad, "ad_open_rf_ea(\"%s\"): \"%s\"", fullpathname(rfpath), strerror(errno)); + EC_FAIL; + } + break; + case ENOENT: + EC_EXIT_STATUS(0); + default: + LOG(log_error, logtype_ad, "ad_open_rf_ea(\"%s\"): \"%s\"", fullpathname(rfpath), strerror(errno)); + EC_FAIL; + } + } else { + oflags |= O_CREAT; + EC_NEG1_LOG( ad_reso_fileno(ad) = open(rfpath, oflags, mode) ); + LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): created adouble rfork: \"%s\"", + path, rfpath); + } + } +#endif + opened = 1; + ad->ad_rfp->adf_refcount = 1; + ad->ad_rfp->adf_flags = oflags; + ad->ad_reso_refcount++; + +#ifndef HAVE_EAFD + EC_ZERO_LOG( fstat(ad_reso_fileno(ad), &st) ); + if (ad->ad_rfp->adf_flags & O_CREAT) { + /* This is a new adouble header file, create it */ + LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): created adouble rfork, initializing: \"%s\"", + path, rfpath); + EC_NEG1_LOG( new_ad_header(ad, path, NULL, adflags) ); + LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): created adouble rfork, flushing: \"%s\"", + path, rfpath); + ad_flush(ad); + } else { + /* Read the adouble header */ + LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): reading adouble rfork: \"%s\"", + path, rfpath); + EC_NEG1_LOG( ad_header_read_osx(rfpath, ad, &st) ); + } +#endif + + ad->ad_rlen = ad_reso_size(path, adflags, ad); + +EC_CLEANUP: + if (ret != 0) { + if (opened && (ad_reso_fileno(ad) != -1)) { + close(ad_reso_fileno(ad)); + ad_reso_fileno(ad) = -1; + ad->ad_reso_refcount--; + ad->ad_rfp->adf_refcount = 0; + } + if (adflags & ADFLAGS_NORF) { + ret = 0; + } else { + int err = errno; + (void)ad_close(ad, closeflags); + errno = err; + } + ad->ad_rlen = 0; + } + + LOG(log_debug, logtype_ad, "ad_open_rf(\"%s\"): END: %d", fullpathname(path), ret); + + EC_EXIT; +} + +/*! + * Open ressource fork + */ +static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad) +{ + int ret = 0; + + switch (ad->ad_vers) { + case AD_VERSION2: + ret = ad_open_rf_v2(path, adflags, mode, ad); + break; + case AD_VERSION_EA: + ret = ad_open_rf_ea(path, adflags, mode, ad); + break; + default: + ret = -1; + break; + } + + return ret; +} + +/*********************************************************************************** + * API functions + ********************************************************************************* */ + +off_t ad_getentryoff(const struct adouble *ad, int eid) +{ + if (ad->ad_vers == AD_VERSION2) + return ad->ad_eid[eid].ade_off; + + switch (eid) { + case ADEID_DFORK: + return 0; + case ADEID_RFORK: +#ifdef HAVE_EAFD + return 0; +#else + return ad->ad_eid[eid].ade_off; +#endif + default: + return ad->ad_eid[eid].ade_off; + } + /* deadc0de */ + AFP_PANIC("What am I doing here?"); +} + +const char *ad_path_ea( const char *path, int adflags _U_) +{ + return path; +} + +const char *ad_path_osx(const char *path, int adflags _U_) +{ + static char pathbuf[ MAXPATHLEN + 1]; + char c, *slash, buf[MAXPATHLEN + 1]; + + if (!strcmp(path,".")) { + /* fixme */ + getcwd(buf, MAXPATHLEN); + } + else { + strlcpy(buf, path, MAXPATHLEN +1); + } + if (NULL != ( slash = strrchr( buf, '/' )) ) { + c = *++slash; + *slash = '\0'; + strlcpy( pathbuf, buf, MAXPATHLEN +1); + *slash = c; + } else { + pathbuf[ 0 ] = '\0'; + slash = buf; + } + strlcat( pathbuf, "._", MAXPATHLEN +1); + strlcat( pathbuf, slash, MAXPATHLEN +1); + return pathbuf; +} + +/* + * Put the .AppleDouble where it needs to be: + * + * / a/.AppleDouble/b + * a/b + * \ b/.AppleDouble/.Parent + * + * FIXME: should do something for pathname > MAXPATHLEN + */ +const char *ad_path( const char *path, int adflags) +{ + static char pathbuf[ MAXPATHLEN + 1]; + const char *slash; + size_t l ; + + if ( adflags & ADFLAGS_DIR ) { + l = strlcpy( pathbuf, path, sizeof(pathbuf)); + + if ( l && l < MAXPATHLEN) { + pathbuf[l++] = '/'; + } + strlcpy(pathbuf +l, ".AppleDouble/.Parent", sizeof(pathbuf) -l); + } else { + if (NULL != ( slash = strrchr( path, '/' )) ) { + slash++; + l = slash - path; + /* XXX we must return NULL here and test in the caller */ + if (l > MAXPATHLEN) + l = MAXPATHLEN; + memcpy( pathbuf, path, l); + } else { + l = 0; + slash = path; + } + l += strlcpy( pathbuf +l, ".AppleDouble/", sizeof(pathbuf) -l); + strlcpy( pathbuf + l, slash, sizeof(pathbuf) -l); + } + + return( pathbuf ); +} + +/* ------------------------- + * Support inherited protection modes for AppleDouble files. The supplied + * mode is ANDed with the parent directory's mask value in lieu of "umask", + * and that value is returned. + */ +char *ad_dir(const char *path) +{ + static char modebuf[ MAXPATHLEN + 1]; + char *slash; + /* + * For a path with directories in it, remove the final component + * (path or subdirectory name) to get the name we want to stat. + * For a path which is just a filename, use "." instead. + */ + slash = strrchr( path, '/' ); + if (slash) { + size_t len; + + len = slash - path; + if (len >= MAXPATHLEN) { + errno = ENAMETOOLONG; + return NULL; /* can't do it */ + } + memcpy( modebuf, path, len ); + modebuf[len] = '\0'; + /* is last char a '/' ? */ + if (slash[1] == 0) { + slash = modebuf+ len; + /* remove them */ + while (modebuf < slash && slash[-1] == '/') { + --slash; + } + if (modebuf == slash) { + goto use_cur; + } + *slash = '\0'; + while (modebuf < slash && *slash != '/') { + --slash; + } + if (modebuf == slash) { + goto use_cur; + } + *slash = '\0'; /* remove pathname component */ + } + return modebuf; + } +use_cur: + modebuf[0] = '.'; /* use current directory */ + modebuf[1] = '\0'; + return modebuf; +} + +int ad_setfuid(const uid_t id) +{ + default_uid = id; + return 0; +} + +/* ---------------- */ +uid_t ad_getfuid(void) +{ + return default_uid; +} + +/* ---------------- + stat path parent directory +*/ +int ad_stat(const char *path, struct stat *stbuf) +{ + char *p; + + p = ad_dir(path); + if (!p) + return -1; + return stat( p, stbuf ); +} + +/* ---------------- + return access right of path parent directory +*/ +int ad_mode( const char *path, mode_t mode) +{ + struct stat stbuf; + ad_mode_st(path, &mode, &stbuf); + return mode; +} + +/* + * Use mkdir() with mode bits taken from ad_mode(). + */ +int ad_mkdir( const char *path, mode_t mode) +{ + int ret; + int st_invalid; + struct stat stbuf; + + LOG(log_debug, logtype_ad, "ad_mkdir(\"%s\", %04o) {cwd: \"%s\"}", + path, mode, getcwdpath()); + + st_invalid = ad_mode_st(path, &mode, &stbuf); + ret = mkdir( path, mode ); + if (ret || st_invalid) + return ret; + ad_chown(path, &stbuf); + + return ret; +} + +static void ad_init_func(struct adouble *ad) +{ + switch (ad->ad_vers) { + case AD_VERSION2: + ad->ad_ops = &ad_adouble; + ad->ad_rfp = &ad->ad_resource_fork; + ad->ad_mdp = &ad->ad_resource_fork; + break; + case AD_VERSION_EA: + ad->ad_ops = &ad_adouble_ea; + ad->ad_rfp = &ad->ad_resource_fork; + ad->ad_mdp = &ad->ad_data_fork; + break; + default: + AFP_PANIC("ad_init: unknown AD version"); + } + + + ad_data_fileno(ad) = -1; + ad_reso_fileno(ad) = -1; + ad_meta_fileno(ad) = -1; + ad->ad_refcount = 1; + ad->ad_rlen = 0; + return; +} + +void ad_init_old(struct adouble *ad, int flags, int options) +{ + memset(ad, 0, sizeof(struct adouble)); + ad->ad_vers = flags; + ad->ad_options = options; + ad_init_func(ad); +} + +void ad_init(struct adouble *ad, const struct vol * restrict vol) +{ + memset(ad, 0, sizeof(struct adouble)); + ad->ad_vers = vol->v_adouble; + ad->ad_options = vol->v_ad_options; + ad_init_func(ad); +} + +/*! + * Open data-, metadata(header)- or ressource fork + * + * ad_open(struct adouble *ad, const char *path, int adflags, int flags) + * ad_open(struct adouble *ad, const char *path, int adflags, int flags, mode_t mode) + * + * You must call ad_init() before ad_open, usually you'll just call it like this: \n + * @code + * struct adoube ad; + * ad_init(&ad, vol->v_adouble, vol->v_ad_options); + * @endcode + * + * Open a files data fork, metadata fork or ressource fork. + * + * @param ad (rw) pointer to struct adouble + * @param path (r) Path to file or directory + * @param adflags (r) Flags specifying which fork to open, can be or'd: + * ADFLAGS_DF: open data fork + * ADFLAGS_RF: open ressource fork + * ADFLAGS_HF: open header (metadata) file + * ADFLAGS_NOHF: it's not an error if header file couldn't be opened + * ADFLAGS_NORF: it's not an error if reso fork couldn't be opened + * ADFLAGS_DIR: if path is a directory you MUST or ADFLAGS_DIR to adflags + * + * Access mode for the forks: + * ADFLAGS_RDONLY: open read only + * ADFLAGS_RDWR: open read write + * + * Creation flags: + * ADFLAGS_CREATE: create if not existing + * ADFLAGS_TRUNC: truncate + * + * Special flags: + * ADFLAGS_CHECK_OF: check for open forks from us and other afpd's + * ADFLAGS_SETSHRMD: this adouble struct will be used to set sharemode locks. + * This basically results in the files being opened RW instead of RDONLY. + * @param mode (r) mode used with O_CREATE + * + * The open mode flags (rw vs ro) have to take into account all the following requirements: + * - we remember open fds for files because me must avoid a single close releasing fcntl locks for other + * fds of the same file + * + * BUGS: + * + * * on Solaris (HAVE_EAFD) ADFLAGS_RF doesn't work without + * ADFLAGS_HF, because it checks whether ad_meta_fileno() is already + * openend. As a workaround pass ADFLAGS_SETSHRMD. + * + * @returns 0 on success, any other value indicates an error + */ +int ad_open(struct adouble *ad, const char *path, int adflags, ...) +{ + EC_INIT; + va_list args; + mode_t mode = 0; + + LOG(log_debug, logtype_ad, + "ad_open(\"%s\", %s): BEGIN {d: %d, m: %d, r: %d}" + "[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), adflags2logstr(adflags), + ad->ad_data_refcount, ad->ad_meta_refcount, ad->ad_reso_refcount, + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + if (adflags & ADFLAGS_CHECK_OF) + /* Checking for open forks requires sharemode lock support (ie RDWR instead of RDONLY) */ + adflags |= ADFLAGS_SETSHRMD; + + if (adflags & ADFLAGS_SETSHRMD) + /* sharemode locks are stored in the data fork */ + adflags |= ADFLAGS_DF; + + if (ad->ad_vers == AD_VERSION2) { + if (adflags & ADFLAGS_RF) + adflags |= ADFLAGS_HF; + if (adflags & ADFLAGS_NORF) + adflags |= ADFLAGS_NOHF; + } + + if (ad->ad_inited != AD_INITED) { + ad->ad_adflags = adflags; + ad->ad_inited = AD_INITED; + } else { + ad->ad_open_forks = ((ad->ad_data_fork.adf_refcount > 0) ? ATTRBIT_DOPEN : 0); + if (ad->ad_resource_fork.adf_refcount > 0) + ad->ad_open_forks |= ATTRBIT_ROPEN; + } + + va_start(args, adflags); + if (adflags & ADFLAGS_CREATE) + mode = (sizeof(mode_t) < sizeof(int) ? va_arg (args, int) : va_arg (args, mode_t)); + va_end(args); + + if (adflags & ADFLAGS_DF) { + ad->ad_data_refcount++; + if (ad_open_df(path, adflags, mode, ad) != 0) { + ad->ad_data_refcount--; + EC_FAIL; + } + } + + if (adflags & ADFLAGS_HF) { + if (ad_open_hf(path, adflags, mode, ad) != 0) { + EC_FAIL; + } + } + + if (adflags & ADFLAGS_RF) { + if (ad_open_rf(path, adflags, mode, ad) != 0) { + EC_FAIL; + } + } + + if (adflags & ADFLAGS_CHECK_OF) { + ad->ad_open_forks |= ad_openforks(ad, ad->ad_open_forks); + } + +EC_CLEANUP: + LOG(log_debug, logtype_ad, + "ad_open(\"%s\"): END: %d {d: %d, m: %d, r: %d}" + "[dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]", + fullpathname(path), ret, + ad->ad_data_refcount, ad->ad_meta_refcount, ad->ad_reso_refcount, + ad_data_fileno(ad), ad->ad_data_fork.adf_refcount, + ad_meta_fileno(ad), ad->ad_mdp->adf_refcount, + ad_reso_fileno(ad), ad->ad_rfp->adf_refcount); + + EC_EXIT; +} + +/*! + * @brief open metadata, possibly as root + * + * Return only metadata but try very hard ie at first try as user, then try as root. + * + * @param name name of file/dir + * @param flags ADFLAGS_DIR: name is a directory \n + * ADFLAGS_CHECK_OF: test if name is open by us or another afpd process + * + * @param adp pointer to struct adouble + */ +int ad_metadata(const char *name, int flags, struct adouble *adp) +{ + int ret, err, oflags; + + /* Sanitize flags */ + oflags = (flags & (ADFLAGS_CHECK_OF | ADFLAGS_DIR)) | ADFLAGS_HF | ADFLAGS_RDONLY; + + if ((ret = ad_open(adp, name, oflags)) < 0 && errno == EACCES) { + become_root(); + ret = ad_open(adp, name, oflags); + unbecome_root(); + err = errno; + errno = err; + } + + return ret; +} + +/* + * @brief openat like wrapper for ad_metadata + */ +int ad_metadataat(int dirfd, const char *name, int flags, struct adouble *adp) +{ + int ret = 0; + int cwdfd = -1; + + if (dirfd != -1) { + if (((cwdfd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) { + ret = -1; + goto exit; + } + } + + if (ad_metadata(name, flags, adp) < 0) { + ret = -1; + goto exit; + } + + if (dirfd != -1) { + + if (fchdir(cwdfd) != 0) { + LOG(log_error, logtype_ad, "ad_openat: cant chdir back, exiting"); + exit(EXITERR_SYS); + } + } + +exit: + if (cwdfd != -1) + close(cwdfd); + + return ret; + +} + +int ad_refresh(const char *path, struct adouble *ad) +{ + switch (ad->ad_vers) { + case AD_VERSION2: + if (ad_meta_fileno(ad) == -1) + return -1; + return ad->ad_ops->ad_header_read(NULL, ad, NULL); + break; + case AD_VERSION_EA: +#ifdef HAVE_EAFD + if (AD_META_OPEN(ad)) { + if (ad_data_fileno(ad) == -1) + return -1; + // TODO: read meta EA + } + + if (AD_RSRC_OPEN(ad)) { + if (ad_reso_fileno(ad) == -1) + return -1; + struct stat st; + if (fstat(ad_reso_fileno(ad), &st) == -1) + return -1; + ad->ad_rlen = st.st_size; + } +#else + if (AD_META_OPEN(ad)) { + if (ad_data_fileno(ad) == -1) + return -1; + // TODO: read meta EA + } + if (AD_RSRC_OPEN(ad)) { + if (ad_reso_fileno(ad) == -1) + return -1; + if (ad_header_read_osx(path, ad, NULL) < 0) + return -1; + } +#endif + return ad->ad_ops->ad_header_read(path, ad, NULL); + break; + default: + return -1; + break; + } + +} + +int ad_openat(struct adouble *ad, + int dirfd, /* dir fd openat like */ + const char *path, + int adflags, ...) +{ + EC_INIT; + int cwdfd = -1; + va_list args; + mode_t mode = 0; + + if (dirfd != -1) { + if (((cwdfd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) + EC_FAIL; + } + + va_start(args, adflags); + if (adflags & ADFLAGS_CREATE) + mode = (sizeof(mode_t) < sizeof(int) ? va_arg (args, int) : va_arg (args, mode_t)); + va_end(args); + + EC_NEG1( ad_open(ad, path, adflags, mode) ); + + if (dirfd != -1) { + if (fchdir(cwdfd) != 0) { + AFP_PANIC("ad_openat: cant chdir back"); + } + } + +EC_CLEANUP: + if (cwdfd != -1) + close(cwdfd); + + return ret; +} + +/* build a resource fork mode from the data fork mode: + * remove X mode and extend header to RW if R or W (W if R for locking), + */ +mode_t ad_hf_mode(mode_t mode) +{ + mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); + /* fnctl lock need write access */ + if ((mode & S_IRUSR)) + mode |= S_IWUSR; + if ((mode & S_IRGRP)) + mode |= S_IWGRP; + if ((mode & S_IROTH)) + mode |= S_IWOTH; + + /* if write mode set add read mode */ + if ((mode & S_IWUSR)) + mode |= S_IRUSR; + if ((mode & S_IWGRP)) + mode |= S_IRGRP; + if ((mode & S_IWOTH)) + mode |= S_IROTH; + + return mode; +} diff --git a/libatalk/adouble/ad_read.c b/libatalk/adouble/ad_read.c new file mode 100644 index 0000000..852a6e9 --- /dev/null +++ b/libatalk/adouble/ad_read.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1990,1991 Regents of The University of Michigan. + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation, and that the name of The University + * of Michigan not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. This software is supplied as is without expressed or + * implied warranties of any kind. + * + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +ssize_t adf_pread(struct ad_fd *ad_fd, void *buf, size_t count, off_t offset) +{ + ssize_t cc; + +#ifndef HAVE_PREAD + if ( ad_fd->adf_off != offset ) { + if ( lseek( ad_fd->adf_fd, offset, SEEK_SET ) < 0 ) { + return -1; + } + ad_fd->adf_off = offset; + } + if (( cc = read( ad_fd->adf_fd, buf, count )) < 0 ) { + return -1; + } + ad_fd->adf_off += cc; +#else + cc = pread(ad_fd->adf_fd, buf, count, offset ); +#endif + return cc; +} + +/* XXX: locks have to be checked before each stream of consecutive + * ad_reads to prevent a denial in the middle from causing + * problems. */ +ssize_t ad_read( struct adouble *ad, const uint32_t eid, off_t off, char *buf, const size_t buflen) +{ + ssize_t cc; + off_t r_off = 0; + + /* We're either reading the data fork (and thus the data file) + * or we're reading anything else (and thus the header file). */ + if ( eid == ADEID_DFORK ) { + if (ad->ad_data_fork.adf_syml !=0 ) { + /* It's a symlink, we already have the target in adf_syml */ + cc = strlen(ad->ad_data_fork.adf_syml); + if (buflen < cc) + /* Request buffersize is too small, force AFPERR_PARAM */ + return -1; + memcpy(buf, ad->ad_data_fork.adf_syml, cc); + } else { + cc = adf_pread(&ad->ad_data_fork, buf, buflen, off); + } + } else { + if (! AD_RSRC_OPEN(ad)) + /* resource fork is not open ( cf etc/afp/fork.c) */ + return 0; + + if (ad->ad_vers == AD_VERSION_EA) { +#ifdef HAVE_EAFD + r_off = off; +#else + r_off = off + ADEDOFF_RFORK_OSX; +#endif + } else { + r_off = ad_getentryoff(ad, eid) + off; + } + + if (( cc = adf_pread( &ad->ad_resource_fork, buf, buflen, r_off )) < 0 ) + return( -1 ); + } + + return( cc ); +} diff --git a/libatalk/adouble/ad_recvfile.c b/libatalk/adouble/ad_recvfile.c new file mode 100644 index 0000000..1703ee8 --- /dev/null +++ b/libatalk/adouble/ad_recvfile.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) Jeremy Allison 2007 + * Copyright (c) 2013 Ralph Boehme + * All rights reserved. See COPYRIGHT. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef WITH_RECVFILE + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int ad_recvfile_init(const struct adouble *ad, int eid, off_t *off) +{ + int fd; + + if (eid == ADEID_DFORK) { + fd = ad_data_fileno(ad); + } else { + *off += ad_getentryoff(ad, eid); + fd = ad_reso_fileno(ad); + } + + return fd; +} + +/* + * If tofd is -1, drain the incoming socket of count bytes without writing to the outgoing fd, + * if a write fails we do the same. + * + * Returns -1 on short reads from fromfd (read error) and sets errno. + * + * Returns number of bytes written to 'tofd' or thrown away if 'tofd == -1'. + * return != count then sets errno. + * Returns count if complete success. + */ + +#define TRANSFER_BUF_SIZE (128*1024) + +static ssize_t default_sys_recvfile(int fromfd, + int tofd, + off_t offset, + size_t count) +{ + int saved_errno = 0; + size_t total = 0; + size_t bufsize = MIN(TRANSFER_BUF_SIZE, count); + size_t total_written = 0; + char *buffer = NULL; + + if (count == 0) { + return 0; + } + + LOG(log_maxdebug, logtype_dsi, "default_recvfile: from = %d, to = %d, offset = %.0f, count = %lu\n", + fromfd, tofd, (double)offset, (unsigned long)count); + + if ((buffer = malloc(bufsize)) == NULL) + return -1; + + while (total < count) { + size_t num_written = 0; + ssize_t read_ret; + size_t toread = MIN(bufsize,count - total); + + /* Read from socket - ignore EINTR. */ + read_ret = read(fromfd, buffer, toread); + if (read_ret <= 0) { + /* EOF or socket error. */ + free(buffer); + return -1; + } + + num_written = 0; + + while (num_written < read_ret) { + ssize_t write_ret; + + if (tofd == -1) { + write_ret = read_ret; + } else { + /* Write to file - ignore EINTR. */ + write_ret = pwrite(tofd, buffer + num_written, read_ret - num_written, offset); + if (write_ret <= 0) { + /* write error - stop writing. */ + tofd = -1; + saved_errno = errno; + continue; + } + } + num_written += (size_t)write_ret; + total_written += (size_t)write_ret; + } + total += read_ret; + } + + free(buffer); + if (saved_errno) { + /* Return the correct write error. */ + errno = saved_errno; + } + return (ssize_t)total_written; +} + +#ifdef HAVE_SPLICE +static int waitfordata(int socket) +{ + fd_set readfds; + int maxfd = socket + 1; + int ret; + + FD_ZERO(&readfds); + + while (1) { + FD_ZERO(&readfds); + FD_SET(socket, &readfds); + if ((ret = select(maxfd, &readfds, NULL, NULL, NULL)) <= 0) { + if (ret == -1 && errno == EINTR) + continue; + LOG(log_error, logtype_dsi, "waitfordata: unexpected select return: %d %s", + ret, ret < 0 ? strerror(errno) : ""); + return -1; + } + if (FD_ISSET(socket, &readfds)) + return 0; + return -1; + } + +} + +/* + * Try and use the Linux system call to do this. + * Remember we only return -1 if the socket read + * failed. Else we return the number of bytes + * actually written. We always read count bytes + * from the network in the case of return != -1. + */ +static ssize_t sys_recvfile(int fromfd, int tofd, off_t offset, size_t count, int splice_size) +{ + static int pipefd[2] = { -1, -1 }; + static bool try_splice_call = true; + size_t total_written = 0; + loff_t splice_offset = offset; + + LOG(log_debug, logtype_dsi, "sys_recvfile: from = %d, to = %d, offset = %.0f, count = %lu", + fromfd, tofd, (double)offset, (unsigned long)count); + + if (count == 0) + return 0; + + /* + * Older Linux kernels have splice for sendfile, + * but it fails for recvfile. Ensure we only try + * this once and always fall back to the userspace + * implementation if recvfile splice fails. JRA. + */ + + if (!try_splice_call) { + errno = ENOSYS; + return -1; + } + + if ((pipefd[0] == -1) && (pipe(pipefd) == -1)) { + try_splice_call = false; + errno = ENOSYS; + return -1; + } + + while (count > 0) { + int nread, to_write; + + nread = splice(fromfd, NULL, pipefd[1], NULL, MIN(count, splice_size), SPLICE_F_MOVE | SPLICE_F_NONBLOCK); + + if (nread == -1) { + if (errno == EINTR) + continue; + if (errno == EAGAIN) { + if (waitfordata(fromfd) != -1) + continue; + return -1; + } + if (total_written == 0 && (errno == EBADF || errno == EINVAL)) { + LOG(log_warning, logtype_dsi, "splice() doesn't work for recvfile"); + try_splice_call = false; + errno = ENOSYS; + return -1; + } + break; + } + + to_write = nread; + while (to_write > 0) { + int thistime; + thistime = splice(pipefd[0], NULL, tofd, &splice_offset, to_write, SPLICE_F_MOVE); + if (thistime == -1) + return -1; + to_write -= thistime; + } + + total_written += nread; + count -= nread; + } + +done: + LOG(log_maxdebug, logtype_dsi, "sys_recvfile: total_written: %zu", total_written); + + return total_written; +} +#else + +/***************************************************************** + No recvfile system call - use the default 128 chunk implementation. +*****************************************************************/ + +ssize_t sys_recvfile(int fromfd, int tofd, off_t offset, size_t count) +{ + return default_sys_recvfile(fromfd, tofd, offset, count); +} +#endif + +/* read from a socket and write to an adouble file */ +ssize_t ad_recvfile(struct adouble *ad, int eid, int sock, off_t off, size_t len, int splice_size) +{ + ssize_t cc; + int fd; + off_t off_fork = off; + + fd = ad_recvfile_init(ad, eid, &off_fork); + if ((cc = sys_recvfile(sock, fd, off_fork, len, splice_size)) != len) + return -1; + + if ((eid != ADEID_DFORK) && (off > ad_getentrylen(ad, eid))) + ad_setentrylen(ad, eid, off); + + return cc; +} +#endif diff --git a/libatalk/adouble/ad_sendfile.c b/libatalk/adouble/ad_sendfile.c new file mode 100644 index 0000000..2730644 --- /dev/null +++ b/libatalk/adouble/ad_sendfile.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + * + * NOTE: the following uses the fact that sendfile() only exists on + * machines with SA_RESTART behaviour. this is all very machine specific. + * + * sendfile chainsaw from samba. + Unix SMB/Netbios implementation. + Version 2.2.x / 3.0.x + sendfile implementations. + Copyright (C) Jeremy Allison 2002. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef WITH_SENDFILE +#include +#include +#include +#include + +#include +#include + +#include "ad_lock.h" + +#if defined(SENDFILE_FLAVOR_LINUX) +#include + +ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) +{ + return sendfile(tofd, fromfd, offset, count); +} + +#elif defined(SENDFILE_FLAVOR_SOLARIS) +#include + +ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) +{ + return sendfile(tofd, fromfd, offset, count); +} + +#elif defined(SENDFILE_FLAVOR_BSD ) +#include +#include +#include +ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) +{ + off_t len; + int ret; + + ret = sendfile(fromfd, tofd, *offset, count, NULL, &len, 0); + + *offset += len; + + if (ret != 0) + return -1; + return len; +} + +#else + +ssize_t sys_sendfile(int out_fd, int in_fd, off_t *_offset, size_t count) +{ + /* No sendfile syscall. */ + errno = ENOSYS; + return -1; +} +#endif + +/* ------------------------------- */ +int ad_readfile_init(const struct adouble *ad, + const int eid, off_t *off, + const int end) +{ + int fd; + + if (end) + *off = ad_size(ad, eid) - *off; + + if (eid == ADEID_DFORK) { + fd = ad_data_fileno(ad); + } else { + *off += ad_getentryoff(ad, eid); + fd = ad_reso_fileno(ad); + } + + return fd; +} +#endif diff --git a/libatalk/adouble/ad_size.c b/libatalk/adouble/ad_size.c new file mode 100644 index 0000000..6b4ed96 --- /dev/null +++ b/libatalk/adouble/ad_size.c @@ -0,0 +1,33 @@ +/* + * + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + * + * if we could depend upon inline functions, this would be one. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +off_t ad_size(const struct adouble *ad, const uint32_t eid) +{ + if (eid == ADEID_DFORK) { + struct stat st; + + if (ad->ad_data_fork.adf_syml) + return strlen(ad->ad_data_fork.adf_syml); + + if (fstat(ad_data_fileno(ad), &st) < 0) + return 0; + return st.st_size; + } +#if 0 + return ad_getentrylen(ad, eid); +#endif + return ad->ad_rlen; +} diff --git a/libatalk/adouble/ad_write.c b/libatalk/adouble/ad_write.c new file mode 100644 index 0000000..4ae1cf6 --- /dev/null +++ b/libatalk/adouble/ad_write.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 1990,1995 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* XXX: locking has to be checked before each stream of consecutive + * ad_writes to prevent a lock in the middle from causing problems. + */ + +ssize_t adf_pwrite(struct ad_fd *ad_fd, const void *buf, size_t count, off_t offset) +{ + ssize_t cc; + +#ifndef HAVE_PWRITE + if ( ad_fd->adf_off != offset ) { + if ( lseek( ad_fd->adf_fd, offset, SEEK_SET ) < 0 ) { + return -1; + } + ad_fd->adf_off = offset; + } + cc = write( ad_fd->adf_fd, buf, count ); + if ( cc < 0 ) { + return -1; + } + ad_fd->adf_off += cc; +#else + cc = pwrite(ad_fd->adf_fd, buf, count, offset ); +#endif + return cc; +} + +/* end is always 0 */ +ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const char *buf, size_t buflen) +{ + EC_INIT; + struct stat st; + ssize_t cc; + off_t r_off; + + if (ad_data_fileno(ad) == AD_SYMLINK) { + errno = EACCES; + return -1; + } + + LOG(log_debug, logtype_ad, "ad_write: off: %ju, size: %zu, eabuflen: %zu", + (uintmax_t)off, buflen, ad->ad_rlen); + + if ( eid == ADEID_DFORK ) { + if ( end ) { + if ( fstat( ad_data_fileno(ad), &st ) < 0 ) { + return( -1 ); + } + off = st.st_size - off; + } + cc = adf_pwrite(&ad->ad_data_fork, buf, buflen, off); + } else if ( eid == ADEID_RFORK ) { + if (end) { + if (fstat( ad_reso_fileno(ad), &st ) < 0) + return(-1); + off = st.st_size - off - ad_getentryoff(ad, eid); + } + if (ad->ad_vers == AD_VERSION_EA) { +#ifdef HAVE_EAFD + r_off = off; +#else + r_off = ADEDOFF_RFORK_OSX + off; +#endif + } else { + r_off = ad_getentryoff(ad, eid) + off; + } + cc = adf_pwrite(&ad->ad_resource_fork, buf, buflen, r_off); + + if ( ad->ad_rlen < off + cc ) + ad->ad_rlen = off + cc; + } else { + return -1; /* we don't know how to write if it's not a ressource or data fork */ + } + + if (ret != 0) + return ret; + return( cc ); +} + +/* + * the caller set the locks + * ftruncate is undefined when the file length is smaller than 'size' + */ +int sys_ftruncate(int fd, off_t length) +{ + +#ifndef HAVE_PWRITE +off_t curpos; +#endif +int err; +struct stat st; +char c = 0; + + if (!ftruncate(fd, length)) { + return 0; + } + /* maybe ftruncate doesn't work if we try to extend the size */ + err = errno; + +#ifndef HAVE_PWRITE + /* we only care about file pointer if we don't use pwrite */ + if ((off_t)-1 == (curpos = lseek(fd, 0, SEEK_CUR)) ) { + errno = err; + return -1; + } +#endif + + if ( fstat( fd, &st ) < 0 ) { + errno = err; + return -1; + } + + if (st.st_size > length) { + errno = err; + return -1; + } + + if (lseek(fd, length -1, SEEK_SET) != length -1) { + errno = err; + return -1; + } + + if (1 != write( fd, &c, 1 )) { + /* return the write errno */ + return -1; + } + +#ifndef HAVE_PWRITE + if (curpos != lseek(fd, curpos, SEEK_SET)) { + errno = err; + return -1; + } +#endif + + return 0; +} + +/* ------------------------ */ +int ad_rtruncate(struct adouble *ad, const char *uname, const off_t size) +{ + EC_INIT; + + /* + * We can't delete 0 byte size resource forks either, because a + * fork may reference the adouble handle with an open fd for the + * file, which means we would only delete the directory entry, not + * the file. Subsequently all code that works with fork handles + * finds the fork open, so eg flushing a fork (ad_flush()) will + * recreate ._ files. The correct place to delete 0 byte sized + * resource forks is in of_closefork(). + */ + + EC_NEG1( sys_ftruncate(ad_reso_fileno(ad), size + ad->ad_eid[ ADEID_RFORK ].ade_off) ); + + ad->ad_rlen = size; + +EC_CLEANUP: + if (ret != 0) + LOG(log_error, logtype_ad, "ad_rtruncate(\"%s\"): %s", + fullpathname(uname), strerror(errno)); + EC_EXIT; +} + +int ad_dtruncate(struct adouble *ad, const off_t size) +{ + if (sys_ftruncate(ad_data_fileno(ad), size) < 0) { + LOG(log_error, logtype_ad, "sys_ftruncate(fd: %d): %s", + ad_data_fileno(ad), strerror(errno)); + return -1; + } + + return 0; +} + +/* ----------------------- */ +static int copy_all(const int dfd, const void *buf, + size_t buflen) +{ + ssize_t cc; + + while (buflen > 0) { + if ((cc = write(dfd, buf, buflen)) < 0) { + switch (errno) { + case EINTR: + continue; + default: + return -1; + } + } + buflen -= cc; + } + + return 0; +} + +/* -------------------------- + * copy only the fork data stream +*/ +int copy_fork(int eid, struct adouble *add, struct adouble *ads) +{ + ssize_t cc; + int err = 0; + char filebuf[8192]; + int sfd, dfd; + + if (eid == ADEID_DFORK) { + sfd = ad_data_fileno(ads); + dfd = ad_data_fileno(add); + } + else { + sfd = ad_reso_fileno(ads); + dfd = ad_reso_fileno(add); + } + + if ((off_t)-1 == lseek(sfd, ad_getentryoff(ads, eid), SEEK_SET)) + return -1; + + if ((off_t)-1 == lseek(dfd, ad_getentryoff(add, eid), SEEK_SET)) + return -1; + +#if 0 /* ifdef SENDFILE_FLAVOR_LINUX */ + /* doesn't work With 2.6 FIXME, only check for EBADFD ? */ + off_t offset = 0; + size_t size; + struct stat st; + #define BUF 128*1024*1024 + + if (fstat(sfd, &st) == 0) { + + while (1) { + if ( offset >= st.st_size) { + return 0; + } + size = (st.st_size -offset > BUF)?BUF:st.st_size -offset; + if ((cc = sys_sendfile(dfd, sfd, &offset, size)) < 0) { + switch (errno) { + case ENOSYS: + case EINVAL: /* there's no guarantee that all fs support sendfile */ + goto no_sendfile; + default: + return -1; + } + } + } + } + no_sendfile: + lseek(sfd, offset, SEEK_SET); +#endif + + while (1) { + if ((cc = read(sfd, filebuf, sizeof(filebuf))) < 0) { + if (errno == EINTR) + continue; + err = -1; + break; + } + + if (!cc || ((err = copy_all(dfd, filebuf, cc)) < 0)) { + break; + } + } + return err; +} diff --git a/libatalk/bstring/Makefile.am b/libatalk/bstring/Makefile.am new file mode 100644 index 0000000..39f78c3 --- /dev/null +++ b/libatalk/bstring/Makefile.am @@ -0,0 +1,6 @@ +# Makefile.am for libatalk/adouble/ + +noinst_LTLIBRARIES = libbstring.la + +libbstring_la_SOURCES = bstrlib.c bstradd.c + diff --git a/libatalk/bstring/Makefile.in b/libatalk/bstring/Makefile.in new file mode 100644 index 0000000..ffb7610 --- /dev/null +++ b/libatalk/bstring/Makefile.in @@ -0,0 +1,662 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/adouble/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/bstring +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libbstring_la_LIBADD = +am_libbstring_la_OBJECTS = bstrlib.lo bstradd.lo +libbstring_la_OBJECTS = $(am_libbstring_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libbstring_la_SOURCES) +DIST_SOURCES = $(libbstring_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libbstring.la +libbstring_la_SOURCES = bstrlib.c bstradd.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/bstring/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/bstring/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libbstring.la: $(libbstring_la_OBJECTS) $(libbstring_la_DEPENDENCIES) $(EXTRA_libbstring_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libbstring_la_OBJECTS) $(libbstring_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bstradd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bstrlib.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/bstring/bstradd.c b/libatalk/bstring/bstradd.c new file mode 100644 index 0000000..98e1a15 --- /dev/null +++ b/libatalk/bstring/bstradd.c @@ -0,0 +1,206 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. +*/ + +/*! + * @file + * Additional functions for bstrlib + */ + +#include +#include +#include +#include +#include +#include + +#include + +/* Optionally include a mechanism for debugging memory */ + +#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG) +#include "memdbg.h" +#endif + +#ifndef bstr__alloc +#define bstr__alloc(x) malloc (x) +#endif + +#ifndef bstr__free +#define bstr__free(p) free (p) +#endif + +#ifndef bstr__realloc +#define bstr__realloc(p,x) realloc ((p), (x)) +#endif + +#ifndef bstr__memcpy +#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l)) +#endif + +#ifndef bstr__memmove +#define bstr__memmove(d,s,l) memmove ((d), (s), (l)) +#endif + +#ifndef bstr__memset +#define bstr__memset(d,c,l) memset ((d), (c), (l)) +#endif + +#ifndef bstr__memcmp +#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l)) +#endif + +#ifndef bstr__memchr +#define bstr__memchr(s,c,l) memchr ((s), (c), (l)) +#endif + +/************************************************************************* + * Stuff for making bstrings referencing c-strings + ************************************************************************/ + +/*! + * @brief Create a bstring referencing "str" + * + * This is usefull if a well know code path uses string, often doing strlen on string. + * By converting to bstring which carries the strlen, the repeated computation can be avoided. + */ +bstring brefcstr (char *str) { + bstring b; + size_t j; + + if (str == NULL) + return NULL; + j = strlen(str); + + b = (bstring)bstr__alloc(sizeof(struct tagbstring)); + if (NULL == b) + return NULL; + + b->slen = (int) j; + b->mlen = -1; + b->data = (unsigned char *)str; + + return b; +} + +/*! + * @brief Free up the bstring, WITHOUT freeing the pointed to c-string! + */ +int bunrefcstr (bstring b) { + if (b == NULL || b->slen < 0 || b->mlen > 0 || b->data == NULL) + return BSTR_ERR; + + /* In case there is any stale usage, there is one more chance to + notice this error. */ + + b->slen = -1; + b->mlen = -__LINE__; + b->data = NULL; + + bstr__free (b); + return BSTR_OK; +} + +/************************************************************************* + * stuff for bstrList + ************************************************************************/ + +/*! + * @brief Create an empty list with preallocated storage for at least 'min' members + */ +struct bstrList *bstrListCreateMin(int min) +{ + struct bstrList *sl = NULL; + + if ((sl = bstrListCreate()) == NULL) + return NULL; + + if ((bstrListAlloc(sl, min)) != BSTR_OK) { + bstrListDestroy(sl); + return NULL; + } + + return sl; +} + +/*! + * @brief Push a bstring to the end of a list + */ +int bstrListPush(struct bstrList *sl, bstring bs) +{ + if (sl->qty == sl->mlen) { + if ((bstrListAlloc(sl, sl->qty + 1)) != BSTR_OK) + return BSTR_ERR; + } + + sl->entry[sl->qty] = bs; + sl->qty++; + return BSTR_OK; +} + +/*! + * @brief Pop a bstring from the end of a list + */ +bstring bstrListPop(struct bstrList *sl) +{ + return NULL; +} + +/*! + * @brief Inverse bjoin + */ +bstring bjoinInv(const struct bstrList * bl, const_bstring sep) { + bstring b; + int i, j, c, v; + + if (bl == NULL || bl->qty < 0) + return NULL; + if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) + return NULL; + + for (i = 0, c = 1; i < bl->qty; i++) { + v = bl->entry[i]->slen; + if (v < 0) + return NULL;/* Invalid input */ + c += v; + if (c < 0) + return NULL;/* Wrap around ?? */ + } + + if (sep != NULL) + c += (bl->qty - 1) * sep->slen; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (NULL == b) + return NULL; /* Out of memory */ + b->data = (unsigned char *) bstr__alloc (c); + if (b->data == NULL) { + bstr__free (b); + return NULL; + } + + b->mlen = c; + b->slen = c-1; + + for (i = bl->qty - 1, c = 0, j = 0; i >= 0; i--, j++) { + if (j > 0 && sep != NULL) { + bstr__memcpy (b->data + c, sep->data, sep->slen); + c += sep->slen; + } + v = bl->entry[i]->slen; + bstr__memcpy (b->data + c, bl->entry[i]->data, v); + c += v; + } + b->data[c] = (unsigned char) '\0'; + return b; +} diff --git a/libatalk/bstring/bstrlib.c b/libatalk/bstring/bstrlib.c new file mode 100644 index 0000000..29e113e --- /dev/null +++ b/libatalk/bstring/bstrlib.c @@ -0,0 +1,2956 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2008, and is covered by the BSD open source + * license and the GPL. Refer to the accompanying documentation for details + * on usage and license. + */ + +/* + * bstrlib.c + * + * This file is the core module for implementing the bstring functions. + */ + +#include +#include +#include +#include +#include +#include + +#include + +/* Optionally include a mechanism for debugging memory */ + +#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG) +#include "memdbg.h" +#endif + +#ifndef bstr__alloc +#define bstr__alloc(x) malloc (x) +#endif + +#ifndef bstr__free +#define bstr__free(p) free (p) +#endif + +#ifndef bstr__realloc +#define bstr__realloc(p,x) realloc ((p), (x)) +#endif + +#ifndef bstr__memcpy +#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l)) +#endif + +#ifndef bstr__memmove +#define bstr__memmove(d,s,l) memmove ((d), (s), (l)) +#endif + +#ifndef bstr__memset +#define bstr__memset(d,c,l) memset ((d), (c), (l)) +#endif + +#ifndef bstr__memcmp +#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l)) +#endif + +#ifndef bstr__memchr +#define bstr__memchr(s,c,l) memchr ((s), (c), (l)) +#endif + +/* Just a length safe wrapper for memmove. */ + +#define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); } + +/* Compute the snapped size for a given requested size. By snapping to powers + of 2 like this, repeated reallocations are avoided. */ +static int snapUpSize (int i) { + if (i < 8) { + i = 8; + } else { + unsigned int j; + j = (unsigned int) i; + + j |= (j >> 1); + j |= (j >> 2); + j |= (j >> 4); + j |= (j >> 8); /* Ok, since int >= 16 bits */ +#if (UINT_MAX != 0xffff) + j |= (j >> 16); /* For 32 bit int systems */ +#if (UINT_MAX > 0xffffffffUL) + j |= (j >> 32); /* For 64 bit int systems */ +#endif +#endif + /* Least power of two greater than i */ + j++; + if ((int) j >= i) i = (int) j; + } + return i; +} + +/* int balloc (bstring b, int len) + * + * Increase the size of the memory backing the bstring b to at least len. + */ +int balloc (bstring b, int olen) { + int len; + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 || + b->mlen < b->slen || olen <= 0) { + return BSTR_ERR; + } + + if (olen >= b->mlen) { + unsigned char * x; + + if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK; + + /* Assume probability of a non-moving realloc is 0.125 */ + if (7 * b->mlen < 8 * b->slen) { + + /* If slen is close to mlen in size then use realloc to reduce + the memory defragmentation */ + + reallocStrategy:; + + x = (unsigned char *) bstr__realloc (b->data, (size_t) len); + if (x == NULL) { + + /* Since we failed, try allocating the tighest possible + allocation */ + + if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) { + return BSTR_ERR; + } + } + } else { + + /* If slen is not close to mlen then avoid the penalty of copying + the extra bytes that are allocated, but not considered part of + the string */ + + if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) { + + /* Perhaps there is no available memory for the two + allocations to be in memory at once */ + + goto reallocStrategy; + + } else { + if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen); + bstr__free (b->data); + } + } + b->data = x; + b->mlen = len; + b->data[b->slen] = (unsigned char) '\0'; + } + + return BSTR_OK; +} + +/* int ballocmin (bstring b, int len) + * + * Set the size of the memory backing the bstring b to len or b->slen+1, + * whichever is larger. Note that repeated use of this function can degrade + * performance. + */ +int ballocmin (bstring b, int len) { + unsigned char * s; + + if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 || + b->mlen < b->slen || len <= 0) { + return BSTR_ERR; + } + + if (len < b->slen + 1) len = b->slen + 1; + + if (len != b->mlen) { + s = (unsigned char *) bstr__realloc (b->data, (size_t) len); + if (NULL == s) return BSTR_ERR; + s[b->slen] = (unsigned char) '\0'; + b->data = s; + b->mlen = len; + } + + return BSTR_OK; +} + +/* bstring bfromcstr (const char * str) + * + * Create a bstring which contains the contents of the '\0' terminated char * + * buffer str. + */ +bstring bfromcstr (const char * str) { +bstring b; +int i; +size_t j; + + if (str == NULL) return NULL; + j = (strlen) (str); + i = snapUpSize ((int) (j + (2 - (j != 0)))); + if (i <= (int) j) return NULL; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (NULL == b) return NULL; + b->slen = (int) j; + if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { + bstr__free (b); + return NULL; + } + + bstr__memcpy (b->data, str, j+1); + return b; +} + +/* bstring bfromcstralloc (int mlen, const char * str) + * + * Create a bstring which contains the contents of the '\0' terminated char * + * buffer str. The memory buffer backing the string is at least len + * characters in length. + */ +bstring bfromcstralloc (int mlen, const char * str) { +bstring b; +int i; +size_t j; + + if (str == NULL) return NULL; + j = (strlen) (str); + i = snapUpSize ((int) (j + (2 - (j != 0)))); + if (i <= (int) j) return NULL; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b == NULL) return NULL; + b->slen = (int) j; + if (i < mlen) i = mlen; + + if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { + bstr__free (b); + return NULL; + } + + bstr__memcpy (b->data, str, j+1); + return b; +} + +/* bstring blk2bstr (const void * blk, int len) + * + * Create a bstring which contains the content of the block blk of length + * len. + */ +bstring blk2bstr (const void * blk, int len) { +bstring b; +int i; + + if (blk == NULL || len < 0) return NULL; + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b == NULL) return NULL; + b->slen = len; + + i = len + (2 - (len != 0)); + i = snapUpSize (i); + + b->mlen = i; + + b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen); + if (b->data == NULL) { + bstr__free (b); + return NULL; + } + + if (len > 0) bstr__memcpy (b->data, blk, (size_t) len); + b->data[len] = (unsigned char) '\0'; + + return b; +} + +/* char * bstr2cstr (const_bstring s, char z) + * + * Create a '\0' terminated char * buffer which is equal to the contents of + * the bstring s, except that any contained '\0' characters are converted + * to the character in z. This returned value should be freed with a + * bcstrfree () call, by the calling application. + */ +char * bstr2cstr (const_bstring b, char z) { +int i, l; +char * r; + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + l = b->slen; + r = (char *) bstr__alloc ((size_t) (l + 1)); + if (r == NULL) return r; + + for (i=0; i < l; i ++) { + r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i])); + } + + r[l] = (unsigned char) '\0'; + + return r; +} + +/* int bcstrfree (char * s) + * + * Frees a C-string generated by bstr2cstr (). This is normally unnecessary + * since it just wraps a call to bstr__free (), however, if bstr__alloc () + * and bstr__free () have been redefined as a macros within the bstrlib + * module (via defining them in memdbg.h after defining + * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std + * library functions, then this allows a correct way of freeing the memory + * that allows higher level code to be independent from these macro + * redefinitions. + */ +int bcstrfree (char * s) { + if (s) { + bstr__free (s); + return BSTR_OK; + } + return BSTR_ERR; +} + +/* int bconcat (bstring b0, const_bstring b1) + * + * Concatenate the bstring b1 to the bstring b0. + */ +int bconcat (bstring b0, const_bstring b1) { +int len, d; +bstring aux = (bstring) b1; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR; + + d = b0->slen; + len = b1->slen; + if ((d | (b0->mlen - d) | len | (d + len)) < 0) return BSTR_ERR; + + if (b0->mlen <= d + len + 1) { + ptrdiff_t pd = b1->data - b0->data; + if (0 <= pd && pd < b0->mlen) { + if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; + } + if (balloc (b0, d + len + 1) != BSTR_OK) { + if (aux != b1) bdestroy (aux); + return BSTR_ERR; + } + } + + bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len); + b0->data[d + len] = (unsigned char) '\0'; + b0->slen = d + len; + if (aux != b1) bdestroy (aux); + return BSTR_OK; +} + +/* int bconchar (bstring b, char c) +/ * + * Concatenate the single character c to the bstring b. + */ +int bconchar (bstring b, char c) { +int d; + + if (b == NULL) return BSTR_ERR; + d = b->slen; + if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + b->data[d] = (unsigned char) c; + b->data[d + 1] = (unsigned char) '\0'; + b->slen++; + return BSTR_OK; +} + +/* int bcatcstr (bstring b, const char * s) + * + * Concatenate a char * string to a bstring. + */ +int bcatcstr (bstring b, const char * s) { +char * d; +int i, l; + + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen + || b->mlen <= 0 || s == NULL) return BSTR_ERR; + + /* Optimistically concatenate directly */ + l = b->mlen - b->slen; + d = (char *) &b->data[b->slen]; + for (i=0; i < l; i++) { + if ((*d++ = *s++) == '\0') { + b->slen += i; + return BSTR_OK; + } + } + b->slen += i; + + /* Need to explicitely resize and concatenate tail */ + return bcatblk (b, (const void *) s, (int) strlen (s)); +} + +/* int bcatblk (bstring b, const void * s, int len) + * + * Concatenate a fixed length buffer to a bstring. + */ +int bcatblk (bstring b, const void * s, int len) { +int nl; + + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen + || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR; + + if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */ + if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR; + + bBlockCopy (&b->data[b->slen], s, (size_t) len); + b->slen = nl; + b->data[nl] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* bstring bstrcpy (const_bstring b) + * + * Create a copy of the bstring b. + */ +bstring bstrcpy (const_bstring b) { +bstring b0; +int i,j; + + /* Attempted to copy an invalid string? */ + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + b0 = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b0 == NULL) { + /* Unable to allocate memory for string header */ + return NULL; + } + + i = b->slen; + j = snapUpSize (i + 1); + + b0->data = (unsigned char *) bstr__alloc (j); + if (b0->data == NULL) { + j = i + 1; + b0->data = (unsigned char *) bstr__alloc (j); + if (b0->data == NULL) { + /* Unable to allocate memory for string data */ + bstr__free (b0); + return NULL; + } + } + + b0->mlen = j; + b0->slen = i; + + if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i); + b0->data[b0->slen] = (unsigned char) '\0'; + + return b0; +} + +/* int bassign (bstring a, const_bstring b) + * + * Overwrite the string a with the contents of string b. + */ +int bassign (bstring a, const_bstring b) { + if (b == NULL || b->data == NULL || b->slen < 0) + return BSTR_ERR; + if (b->slen != 0) { + if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR; + bstr__memmove (a->data, b->data, b->slen); + } else { + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) + return BSTR_ERR; + } + a->data[b->slen] = (unsigned char) '\0'; + a->slen = b->slen; + return BSTR_OK; +} + +/* int bassignmidstr (bstring a, const_bstring b, int left, int len) + * + * Overwrite the string a with the middle of contents of string b + * starting from position left and running for a length len. left and + * len are clamped to the ends of b as with the function bmidstr. + */ +int bassignmidstr (bstring a, const_bstring b, int left, int len) { + if (b == NULL || b->data == NULL || b->slen < 0) + return BSTR_ERR; + + if (left < 0) { + len += left; + left = 0; + } + + if (len > b->slen - left) len = b->slen - left; + + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) + return BSTR_ERR; + + if (len > 0) { + if (balloc (a, len) != BSTR_OK) return BSTR_ERR; + bstr__memmove (a->data, b->data + left, len); + a->slen = len; + } else { + a->slen = 0; + } + a->data[a->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bassigncstr (bstring a, const char * str) + * + * Overwrite the string a with the contents of char * string str. Note that + * the bstring a must be a well defined and writable bstring. If an error + * occurs BSTR_ERR is returned however a may be partially overwritten. + */ +int bassigncstr (bstring a, const char * str) { +int i; +size_t len; + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0 || NULL == str) + return BSTR_ERR; + + for (i=0; i < a->mlen; i++) { + if ('\0' == (a->data[i] = str[i])) { + a->slen = i; + return BSTR_OK; + } + } + + a->slen = i; + len = strlen (str + i); + if (len > INT_MAX || i + len + 1 > INT_MAX || + 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR; + bBlockCopy (a->data + i, str + i, (size_t) len + 1); + a->slen += (int) len; + return BSTR_OK; +} + +/* int bassignblk (bstring a, const void * s, int len) + * + * Overwrite the string a with the contents of the block (s, len). Note that + * the bstring a must be a well defined and writable bstring. If an error + * occurs BSTR_ERR is returned and a is not overwritten. + */ +int bassignblk (bstring a, const void * s, int len) { + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1) + return BSTR_ERR; + if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR; + bBlockCopy (a->data, s, (size_t) len); + a->data[len] = (unsigned char) '\0'; + a->slen = len; + return BSTR_OK; +} + +/* int btrunc (bstring b, int n) + * + * Truncate the bstring to at most n characters. + */ +int btrunc (bstring b, int n) { + if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + if (b->slen > n) { + b->slen = n; + b->data[n] = (unsigned char) '\0'; + } + return BSTR_OK; +} + +#define upcase(c) (toupper ((unsigned char) c)) +#define downcase(c) (tolower ((unsigned char) c)) +#define wspace(c) (isspace ((unsigned char) c)) + +/* int btoupper (bstring b) + * + * Convert contents of bstring to upper case. + */ +int btoupper (bstring b) { +int i, len; + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + for (i=0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char) upcase (b->data[i]); + } + return BSTR_OK; +} + +/* int btolower (bstring b) + * + * Convert contents of bstring to lower case. + */ +int btolower (bstring b) { +int i, len; + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + for (i=0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char) downcase (b->data[i]); + } + return BSTR_OK; +} + +/* int bstricmp (const_bstring b0, const_bstring b1) + * + * Compare two strings without differentiating between case. The return + * value is the difference of the values of the characters where the two + * strings first differ after lower case transformation, otherwise 0 is + * returned indicating that the strings are equal. If the lengths are + * different, then a difference from 0 is given, but if the first extra + * character is '\0', then it is taken to be the value UCHAR_MAX+1. + */ +int bstricmp (const_bstring b0, const_bstring b1) { +int i, v, n; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN; + if ((n = b0->slen) > b1->slen) n = b1->slen; + else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK; + + for (i = 0; i < n; i ++) { + v = (char) downcase (b0->data[i]) + - (char) downcase (b1->data[i]); + if (0 != v) return v; + } + + if (b0->slen > n) { + v = (char) downcase (b0->data[n]); + if (v) return v; + return UCHAR_MAX + 1; + } + if (b1->slen > n) { + v = - (char) downcase (b1->data[n]); + if (v) return v; + return - (int) (UCHAR_MAX + 1); + } + return BSTR_OK; +} + +/* int bstrnicmp (const_bstring b0, const_bstring b1, int n) + * + * Compare two strings without differentiating between case for at most n + * characters. If the position where the two strings first differ is + * before the nth position, the return value is the difference of the values + * of the characters, otherwise 0 is returned. If the lengths are different + * and less than n characters, then a difference from 0 is given, but if the + * first extra character is '\0', then it is taken to be the value + * UCHAR_MAX+1. + */ +int bstrnicmp (const_bstring b0, const_bstring b1, int n) { +int i, v, m; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN; + m = n; + if (m > b0->slen) m = b0->slen; + if (m > b1->slen) m = b1->slen; + + if (b0->data != b1->data) { + for (i = 0; i < m; i ++) { + v = (char) downcase (b0->data[i]); + v -= (char) downcase (b1->data[i]); + if (v != 0) return b0->data[i] - b1->data[i]; + } + } + + if (n == m || b0->slen == b1->slen) return BSTR_OK; + + if (b0->slen > m) { + v = (char) downcase (b0->data[m]); + if (v) return v; + return UCHAR_MAX + 1; + } + + v = - (char) downcase (b1->data[m]); + if (v) return v; + return - (int) (UCHAR_MAX + 1); +} + +/* int biseqcaseless (const_bstring b0, const_bstring b1) + * + * Compare two strings for equality without differentiating between case. + * If the strings differ other than in case, 0 is returned, if the strings + * are the same, 1 is returned, if there is an error, -1 is returned. If + * the length of the strings are different, this function is O(1). '\0' + * termination characters are not treated in any special way. + */ +int biseqcaseless (const_bstring b0, const_bstring b1) { +int i, n; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR; + if (b0->slen != b1->slen) return BSTR_OK; + if (b0->data == b1->data || b0->slen == 0) return 1; + for (i=0, n=b0->slen; i < n; i++) { + if (b0->data[i] != b1->data[i]) { + unsigned char c = (unsigned char) downcase (b0->data[i]); + if (c != (unsigned char) downcase (b1->data[i])) return 0; + } + } + return 1; +} + +/* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) + * + * Compare beginning of string b0 with a block of memory of length len + * without differentiating between case for equality. If the beginning of b0 + * differs from the memory block other than in case (or if b0 is too short), + * 0 is returned, if the strings are the same, 1 is returned, if there is an + * error, -1 is returned. '\0' characters are not treated in any special + * way. + */ +int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) { +int i; + + if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) + return BSTR_ERR; + if (b0->slen < len) return BSTR_OK; + if (b0->data == (const unsigned char *) blk || len == 0) return 1; + + for (i = 0; i < len; i ++) { + if (b0->data[i] != ((const unsigned char *) blk)[i]) { + if (downcase (b0->data[i]) != + downcase (((const unsigned char *) blk)[i])) return 0; + } + } + return 1; +} + +/* + * int bltrimws (bstring b) + * + * Delete whitespace contiguous from the left end of the string. + */ +int bltrimws (bstring b) { +int i, len; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (len = b->slen, i = 0; i < len; i++) { + if (!wspace (b->data[i])) { + return bdelete (b, 0, i); + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* + * int brtrimws (bstring b) + * + * Delete whitespace contiguous from the right end of the string. + */ +int brtrimws (bstring b) { +int i; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace (b->data[i])) { + if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; + b->slen = i + 1; + return BSTR_OK; + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* + * int btrimws (bstring b) + * + * Delete whitespace contiguous from both ends of the string. + */ +int btrimws (bstring b) { +int i, j; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace (b->data[i])) { + if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; + b->slen = i + 1; + for (j = 0; wspace (b->data[j]); j++) {} + return bdelete (b, 0, j); + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* int biseq (const_bstring b0, const_bstring b1) + * + * Compare the string b0 and b1. If the strings differ, 0 is returned, if + * the strings are the same, 1 is returned, if there is an error, -1 is + * returned. If the length of the strings are different, this function is + * O(1). '\0' termination characters are not treated in any special way. + */ +int biseq (const_bstring b0, const_bstring b1) { + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return BSTR_ERR; + if (b0->slen != b1->slen) return BSTR_OK; + if (b0->data == b1->data || b0->slen == 0) return 1; + return !bstr__memcmp (b0->data, b1->data, b0->slen); +} + +/* int bisstemeqblk (const_bstring b0, const void * blk, int len) + * + * Compare beginning of string b0 with a block of memory of length len for + * equality. If the beginning of b0 differs from the memory block (or if b0 + * is too short), 0 is returned, if the strings are the same, 1 is returned, + * if there is an error, -1 is returned. '\0' characters are not treated in + * any special way. + */ +int bisstemeqblk (const_bstring b0, const void * blk, int len) { +int i; + + if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) + return BSTR_ERR; + if (b0->slen < len) return BSTR_OK; + if (b0->data == (const unsigned char *) blk || len == 0) return 1; + + for (i = 0; i < len; i ++) { + if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK; + } + return 1; +} + +/* int biseqcstr (const_bstring b, const char *s) + * + * Compare the bstring b and char * string s. The C string s must be '\0' + * terminated at exactly the length of the bstring b, and the contents + * between the two must be identical with the bstring b with no '\0' + * characters for the two contents to be considered equal. This is + * equivalent to the condition that their current contents will be always be + * equal when comparing them in the same format after converting one or the + * other. If the strings are equal 1 is returned, if they are unequal 0 is + * returned and if there is a detectable error BSTR_ERR is returned. + */ +int biseqcstr (const_bstring b, const char * s) { +int i; + if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; + for (i=0; i < b->slen; i++) { + if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK; + } + return s[i] == '\0'; +} + +/* int biseqcstrcaseless (const_bstring b, const char *s) + * + * Compare the bstring b and char * string s. The C string s must be '\0' + * terminated at exactly the length of the bstring b, and the contents + * between the two must be identical except for case with the bstring b with + * no '\0' characters for the two contents to be considered equal. This is + * equivalent to the condition that their current contents will be always be + * equal ignoring case when comparing them in the same format after + * converting one or the other. If the strings are equal, except for case, + * 1 is returned, if they are unequal regardless of case 0 is returned and + * if there is a detectable error BSTR_ERR is returned. + */ +int biseqcstrcaseless (const_bstring b, const char * s) { +int i; + if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; + for (i=0; i < b->slen; i++) { + if (s[i] == '\0' || + (b->data[i] != (unsigned char) s[i] && + downcase (b->data[i]) != (unsigned char) downcase (s[i]))) + return BSTR_OK; + } + return s[i] == '\0'; +} + +/* int bstrcmp (const_bstring b0, const_bstring b1) + * + * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned, + * otherwise a value less than or greater than zero, indicating that the + * string pointed to by b0 is lexicographically less than or greater than + * the string pointed to by b1 is returned. If the the string lengths are + * unequal but the characters up until the length of the shorter are equal + * then a value less than, or greater than zero, indicating that the string + * pointed to by b0 is shorter or longer than the string pointed to by b1 is + * returned. 0 is returned if and only if the two strings are the same. If + * the length of the strings are different, this function is O(n). Like its + * standard C library counter part strcmp, the comparison does not proceed + * past any '\0' termination characters encountered. + */ +int bstrcmp (const_bstring b0, const_bstring b1) { +int i, v, n; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return SHRT_MIN; + n = b0->slen; if (n > b1->slen) n = b1->slen; + if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0)) + return BSTR_OK; + + for (i = 0; i < n; i ++) { + v = ((char) b0->data[i]) - ((char) b1->data[i]); + if (v != 0) return v; + if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; + } + + if (b0->slen > n) return 1; + if (b1->slen > n) return -1; + return BSTR_OK; +} + +/* int bstrncmp (const_bstring b0, const_bstring b1, int n) + * + * Compare the string b0 and b1 for at most n characters. If there is an + * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and + * b1 were first truncated to at most n characters then bstrcmp was called + * with these new strings are paremeters. If the length of the strings are + * different, this function is O(n). Like its standard C library counter + * part strcmp, the comparison does not proceed past any '\0' termination + * characters encountered. + */ +int bstrncmp (const_bstring b0, const_bstring b1, int n) { +int i, v, m; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return SHRT_MIN; + m = n; + if (m > b0->slen) m = b0->slen; + if (m > b1->slen) m = b1->slen; + + if (b0->data != b1->data) { + for (i = 0; i < m; i ++) { + v = ((char) b0->data[i]) - ((char) b1->data[i]); + if (v != 0) return v; + if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; + } + } + + if (n == m || b0->slen == b1->slen) return BSTR_OK; + + if (b0->slen > m) return 1; + return -1; +} + +/* bstring bmidstr (const_bstring b, int left, int len) + * + * Create a bstring which is the substring of b starting from position left + * and running for a length len (clamped by the end of the bstring b.) If + * b is detectably invalid, then NULL is returned. The section described + * by (left, len) is clamped to the boundaries of b. + */ +bstring bmidstr (const_bstring b, int left, int len) { + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + if (left < 0) { + len += left; + left = 0; + } + + if (len > b->slen - left) len = b->slen - left; + + if (len <= 0) return bfromcstr (""); + return blk2bstr (b->data + left, len); +} + +/* int bdelete (bstring b, int pos, int len) + * + * Removes characters from pos to pos+len-1 inclusive and shifts the tail of + * the bstring starting from pos+len to pos. len must be positive for this + * call to have any effect. The section of the string described by (pos, + * len) is clamped to boundaries of the bstring b. + */ +int bdelete (bstring b, int pos, int len) { + /* Clamp to left side of bstring */ + if (pos < 0) { + len += pos; + pos = 0; + } + + if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 || + b->mlen < b->slen || b->mlen <= 0) + return BSTR_ERR; + if (len > 0 && pos < b->slen) { + if (pos + len >= b->slen) { + b->slen = pos; + } else { + bBlockCopy ((char *) (b->data + pos), + (char *) (b->data + pos + len), + b->slen - (pos+len)); + b->slen -= len; + } + b->data[b->slen] = (unsigned char) '\0'; + } + return BSTR_OK; +} + +/* int bdestroy (bstring b) + * + * Free up the bstring. Note that if b is detectably invalid or not writable + * then no action is performed and BSTR_ERR is returned. Like a freed memory + * allocation, dereferences, writes or any other action on b after it has + * been bdestroyed is undefined. + */ +int bdestroy (bstring b) { + if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen || + b->data == NULL) + return BSTR_ERR; + + bstr__free (b->data); + + /* In case there is any stale usage, there is one more chance to + notice this error. */ + + b->slen = -1; + b->mlen = -__LINE__; + b->data = NULL; + + bstr__free (b); + return BSTR_OK; +} + +/* int binstr (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * forward. If it is found then return with the first position where it is + * found, otherwise return BSTR_ERR. Note that this is just a brute force + * string searcher that does not attempt clever things like the Boyer-Moore + * search algorithm. Because of this there are many degenerate cases where + * this can take much longer than it needs to. + */ +int binstr (const_bstring b1, int pos, const_bstring b2) { +int j, ii, ll, lf; +unsigned char * d0; +unsigned char c0; +register unsigned char * d1; +register unsigned char c1; +register int i; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* No space to find such a string? */ + if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR; + + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) return 0; + + i = pos; + + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + + /* Peel off the b2->slen == 1 case */ + c0 = d0[0]; + if (1 == ll) { + for (;i < lf; i++) if (c0 == d1[i]) return i; + return BSTR_ERR; + } + + c1 = c0; + j = 0; + lf = b1->slen - 1; + + ii = -1; + if (i < lf) do { + /* Unrolled current character test */ + if (c1 != d1[i]) { + if (c1 != d1[1+i]) { + i += 2; + continue; + } + i++; + } + + /* Take note if this is the start of a potential match */ + if (0 == j) ii = i; + + /* Shift the test character down by one */ + j++; + i++; + + /* If this isn't past the last character continue */ + if (j < ll) { + c1 = d0[j]; + continue; + } + + N0:; + + /* If no characters mismatched, then we matched */ + if (i == ii+j) return ii; + + /* Shift back to the beginning */ + i -= j; + j = 0; + c1 = c0; + } while (i < lf); + + /* Deal with last case if unrolling caused a misalignment */ + if (i == lf && ll == j+1 && c1 == d1[i]) goto N0; + + return BSTR_ERR; +} + +/* int binstrr (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * backward. If it is found then return with the first position where it is + * found, otherwise return BSTR_ERR. Note that this is just a brute force + * string searcher that does not attempt clever things like the Boyer-Moore + * search algorithm. Because of this there are many degenerate cases where + * this can take much longer than it needs to. + */ +int binstrr (const_bstring b1, int pos, const_bstring b2) { +int j, i, l; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos && b2->slen == 0) return pos; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0; + + i = pos; + if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; + + /* If no space to find such a string then snap back */ + if (l + 1 <= i) i = l; + j = 0; + + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j]) { + j ++; + if (j >= l) return i; + } else { + i --; + if (i < 0) break; + j=0; + } + } + + return BSTR_ERR; +} + +/* int binstrcaseless (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * forward but without regard to case. If it is found then return with the + * first position where it is found, otherwise return BSTR_ERR. Note that + * this is just a brute force string searcher that does not attempt clever + * things like the Boyer-Moore search algorithm. Because of this there are + * many degenerate cases where this can take much longer than it needs to. + */ +int binstrcaseless (const_bstring b1, int pos, const_bstring b2) { +int j, i, l, ll; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + l = b1->slen - b2->slen + 1; + + /* No space to find such a string? */ + if (l <= pos) return BSTR_ERR; + + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) return BSTR_OK; + + i = pos; + j = 0; + + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { + j ++; + if (j >= ll) return i; + } else { + i ++; + if (i >= l) break; + j=0; + } + } + + return BSTR_ERR; +} + +/* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * backward but without regard to case. If it is found then return with the + * first position where it is found, otherwise return BSTR_ERR. Note that + * this is just a brute force string searcher that does not attempt clever + * things like the Boyer-Moore search algorithm. Because of this there are + * many degenerate cases where this can take much longer than it needs to. + */ +int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) { +int j, i, l; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos && b2->slen == 0) return pos; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK; + + i = pos; + if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; + + /* If no space to find such a string then snap back */ + if (l + 1 <= i) i = l; + j = 0; + + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { + j ++; + if (j >= l) return i; + } else { + i --; + if (i < 0) break; + j=0; + } + } + + return BSTR_ERR; +} + + +/* int bstrchrp (const_bstring b, int c, int pos) + * + * Search for the character c in b forwards from the position pos + * (inclusive). + */ +int bstrchrp (const_bstring b, int c, int pos) { +unsigned char * p; + + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; + p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos)); + if (p) return (int) (p - b->data); + return BSTR_ERR; +} + +/* int bstrrchrp (const_bstring b, int c, int pos) + * + * Search for the character c in b backwards from the position pos in string + * (inclusive). + */ +int bstrrchrp (const_bstring b, int c, int pos) { +int i; + + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; + for (i=pos; i >= 0; i--) { + if (b->data[i] == (unsigned char) c) return i; + } + return BSTR_ERR; +} + +#if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF) +#define LONG_LOG_BITS_QTY (3) +#define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY) +#define LONG_TYPE unsigned char + +#define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY) +struct charField { LONG_TYPE content[CFCLEN]; }; +#define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1)))) +#define setInCharField(cf,idx) { \ + unsigned int c = (unsigned int) (idx); \ + (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \ +} + +#else + +#define CFCLEN (1 << CHAR_BIT) +struct charField { unsigned char content[CFCLEN]; }; +#define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)]) +#define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0 + +#endif + +/* Convert a bstring to charField */ +static int buildCharField (struct charField * cf, const_bstring b) { +int i; + if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR; + memset ((void *) cf->content, 0, sizeof (struct charField)); + for (i=0; i < b->slen; i++) { + setInCharField (cf, b->data[i]); + } + return BSTR_OK; +} + +static void invertCharField (struct charField * cf) { +int i; + for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i]; +} + +/* Inner engine for binchr */ +static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) { +int i; + for (i=pos; i < len; i++) { + unsigned char c = (unsigned char) data[i]; + if (testInCharField (cf, c)) return i; + } + return BSTR_ERR; +} + +/* int binchr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the first position in b0 starting from pos or after, in which + * one of the characters in b1 is found and return it. If such a position + * does not exist in b0, then BSTR_ERR is returned. + */ +int binchr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen <= pos) return BSTR_ERR; + if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos); + if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; + return binchrCF (b0->data, b0->slen, pos, &chrs); +} + +/* Inner engine for binchrr */ +static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) { +int i; + for (i=pos; i >= 0; i--) { + unsigned int c = (unsigned int) data[i]; + if (testInCharField (cf, c)) return i; + } + return BSTR_ERR; +} + +/* int binchrr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the last position in b0 no greater than pos, in which one of + * the characters in b1 is found and return it. If such a position does not + * exist in b0, then BSTR_ERR is returned. + */ +int binchrr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL || + b0->slen < pos) return BSTR_ERR; + if (pos == b0->slen) pos--; + if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos); + if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; + return binchrrCF (b0->data, pos, &chrs); +} + +/* int bninchr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the first position in b0 starting from pos or after, in which + * none of the characters in b1 is found and return it. If such a position + * does not exist in b0, then BSTR_ERR is returned. + */ +int bninchr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen <= pos) return BSTR_ERR; + if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; + invertCharField (&chrs); + return binchrCF (b0->data, b0->slen, pos, &chrs); +} + +/* int bninchrr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the last position in b0 no greater than pos, in which none of + * the characters in b1 is found and return it. If such a position does not + * exist in b0, then BSTR_ERR is returned. + */ +int bninchrr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen < pos) return BSTR_ERR; + if (pos == b0->slen) pos--; + if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; + invertCharField (&chrs); + return binchrrCF (b0->data, pos, &chrs); +} + +/* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill) + * + * Overwrite the string b0 starting at position pos with the string b1. If + * the position pos is past the end of b0, then the character "fill" is + * appended as necessary to make up the gap between the end of b0 and pos. + * If b1 is NULL, it behaves as if it were a 0-length string. + */ +int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) { +int d, newlen; +ptrdiff_t pd; +bstring aux = (bstring) b1; + + if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data || + b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR; + if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR; + + d = pos; + + /* Aliasing case */ + if (NULL != aux) { + if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) { + if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; + } + d += aux->slen; + } + + /* Increase memory size if necessary */ + if (balloc (b0, d + 1) != BSTR_OK) { + if (aux != b1) bdestroy (aux); + return BSTR_ERR; + } + + newlen = b0->slen; + + /* Fill in "fill" character as necessary */ + if (pos > newlen) { + bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen)); + newlen = pos; + } + + /* Copy b1 to position pos in b0. */ + if (aux != NULL) { + bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen); + if (aux != b1) bdestroy (aux); + } + + /* Indicate the potentially increased size of b0 */ + if (d > newlen) newlen = d; + + b0->slen = newlen; + b0->data[newlen] = (unsigned char) '\0'; + + return BSTR_OK; +} + +/* int binsert (bstring b1, int pos, bstring b2, unsigned char fill) + * + * Inserts the string b2 into b1 at position pos. If the position pos is + * past the end of b1, then the character "fill" is appended as necessary to + * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert + * does not allow b2 to be NULL. + */ +int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) { +int d, l; +ptrdiff_t pd; +bstring aux = (bstring) b2; + + if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 || + b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR; + + /* Aliasing case */ + if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) { + if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; + } + + /* Compute the two possible end pointers */ + d = b1->slen + aux->slen; + l = pos + aux->slen; + if ((d|l) < 0) return BSTR_ERR; + + if (l > d) { + /* Inserting past the end of the string */ + if (balloc (b1, l + 1) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen)); + b1->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc (b1, d + 1) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + bBlockCopy (b1->data + l, b1->data + pos, d - l); + b1->slen = d; + } + bBlockCopy (b1->data + pos, aux->data, aux->slen); + b1->data[b1->slen] = (unsigned char) '\0'; + if (aux != b2) bdestroy (aux); + return BSTR_OK; +} + +/* int breplace (bstring b1, int pos, int len, bstring b2, + * unsigned char fill) + * + * Replace a section of a string from pos for a length len with the string b2. + * fill is used is pos > b1->slen. + */ +int breplace (bstring b1, int pos, int len, const_bstring b2, + unsigned char fill) { +int pl, ret; +ptrdiff_t pd; +bstring aux = (bstring) b2; + + if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL || + b2 == NULL || b1->data == NULL || b2->data == NULL || + b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen || + b1->mlen <= 0) return BSTR_ERR; + + /* Straddles the end? */ + if (pl >= b1->slen) { + if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret; + if (pos + b2->slen < b1->slen) { + b1->slen = pos + b2->slen; + b1->data[b1->slen] = (unsigned char) '\0'; + } + return ret; + } + + /* Aliasing case */ + if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) { + if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; + } + + if (aux->slen > len) { + if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + } + + if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len)); + bstr__memcpy (b1->data + pos, aux->data, aux->slen); + b1->slen += aux->slen - len; + b1->data[b1->slen] = (unsigned char) '\0'; + if (aux != b2) bdestroy (aux); + return BSTR_OK; +} + +/* int bfindreplace (bstring b, const_bstring find, const_bstring repl, + * int pos) + * + * Replace all occurrences of a find string with a replace string after a + * given point in a bstring. + */ + +typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2); + +static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) { +int i, ret, slen, mlen, delta, acc; +int * d; +int static_d[32]; +ptrdiff_t pd; +bstring auxf = (bstring) find; +bstring auxr = (bstring) repl; + + if (b == NULL || b->data == NULL || find == NULL || + find->data == NULL || repl == NULL || repl->data == NULL || + pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen || + b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR; + if (pos > b->slen - find->slen) return BSTR_OK; + + /* Alias with find string */ + pd = (ptrdiff_t) (find->data - b->data); + if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) { + if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR; + } + + /* Alias with repl string */ + pd = (ptrdiff_t) (repl->data - b->data); + if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) { + if (NULL == (auxr = bstrcpy (repl))) { + if (auxf != find) bdestroy (auxf); + return BSTR_ERR; + } + } + + delta = auxf->slen - auxr->slen; + + /* in-place replacement since find and replace strings are of equal + length */ + if (delta == 0) { + while ((pos = instr (b, pos, auxf)) >= 0) { + bstr__memcpy (b->data + pos, auxr->data, auxr->slen); + pos += auxf->slen; + } + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return BSTR_OK; + } + + /* shrinking replacement since auxf->slen > auxr->slen */ + if (delta > 0) { + acc = 0; + + while ((i = instr (b, pos, auxf)) >= 0) { + if (acc && i > pos) + bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); + if (auxr->slen) + bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen); + acc += delta; + pos = i + auxf->slen; + } + + if (acc) { + i = b->slen; + if (i > pos) + bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); + b->slen -= acc; + b->data[b->slen] = (unsigned char) '\0'; + } + + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return BSTR_OK; + } + + /* expanding replacement since find->slen < repl->slen. Its a lot + more complicated. */ + + mlen = 32; + d = (int *) static_d; /* Avoid malloc for trivial cases */ + acc = slen = 0; + + while ((pos = instr (b, pos, auxf)) >= 0) { + if (slen + 1 >= mlen) { + int sl; + int * t; + mlen += mlen; + sl = sizeof (int *) * mlen; + if (static_d == d) d = NULL; + if (sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) { + ret = BSTR_ERR; + goto done; + } + if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d)); + d = t; + } + d[slen] = pos; + slen++; + acc -= delta; + pos += auxf->slen; + if (pos < 0 || acc < 0) { + ret = BSTR_ERR; + goto done; + } + } + d[slen] = b->slen; + + if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) { + b->slen += acc; + for (i = slen-1; i >= 0; i--) { + int s, l; + s = d[i] + auxf->slen; + l = d[i+1] - s; + if (l) { + bstr__memmove (b->data + s + acc, b->data + s, l); + } + if (auxr->slen) { + bstr__memmove (b->data + s + acc - auxr->slen, + auxr->data, auxr->slen); + } + acc += delta; + } + b->data[b->slen] = (unsigned char) '\0'; + } + + done:; + if (static_d == d) d = NULL; + bstr__free (d); + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return ret; +} + +/* int bfindreplace (bstring b, const_bstring find, const_bstring repl, + * int pos) + * + * Replace all occurrences of a find string with a replace string after a + * given point in a bstring. + */ +int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) { + return findreplaceengine (b, find, repl, pos, binstr); +} + +/* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, + * int pos) + * + * Replace all occurrences of a find string, ignoring case, with a replace + * string after a given point in a bstring. + */ +int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) { + return findreplaceengine (b, find, repl, pos, binstrcaseless); +} + +/* int binsertch (bstring b, int pos, int len, unsigned char fill) + * + * Inserts the character fill repeatedly into b at position pos for a + * length len. If the position pos is past the end of b, then the + * character "fill" is appended as necessary to make up the gap between the + * end of b and the position pos + len. + */ +int binsertch (bstring b, int pos, int len, unsigned char fill) { +int d, l, i; + + if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || len < 0) return BSTR_ERR; + + /* Compute the two possible end pointers */ + d = b->slen + len; + l = pos + len; + if ((d|l) < 0) return BSTR_ERR; + + if (l > d) { + /* Inserting past the end of the string */ + if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR; + pos = b->slen; + b->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR; + for (i = d - 1; i >= l; i--) { + b->data[i] = b->data[i - len]; + } + b->slen = d; + } + + for (i=pos; i < l; i++) b->data[i] = fill; + b->data[b->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bpattern (bstring b, int len) + * + * Replicate the bstring, b in place, end to end repeatedly until it + * surpasses len characters, then chop the result to exactly len characters. + * This function operates in-place. The function will return with BSTR_ERR + * if b is NULL or of length 0, otherwise BSTR_OK is returned. + */ +int bpattern (bstring b, int len) { +int i, d; + + d = blength (b); + if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR; + if (len > 0) { + if (d == 1) return bsetstr (b, len, NULL, b->data[0]); + for (i = d; i < len; i++) b->data[i] = b->data[i - d]; + } + b->data[len] = (unsigned char) '\0'; + b->slen = len; + return BSTR_OK; +} + +#define BS_BUFF_SZ (1024) + +/* int breada (bstring b, bNread readPtr, void * parm) + * + * Use a finite buffer fread-like function readPtr to concatenate to the + * bstring b the entire contents of file-like source data in a roughly + * efficient way. + */ +int breada (bstring b, bNread readPtr, void * parm) { +int i, l, n; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || readPtr == NULL) return BSTR_ERR; + + i = b->slen; + for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) { + if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR; + l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm); + i += l; + b->slen = i; + if (i < n) break; + } + + b->data[i] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* bstring bread (bNread readPtr, void * parm) + * + * Use a finite buffer fread-like function readPtr to create a bstring + * filled with the entire contents of file-like source data in a roughly + * efficient way. + */ +bstring bread (bNread readPtr, void * parm) { +bstring buff; + + if (0 > breada (buff = bfromcstr (""), readPtr, parm)) { + bdestroy (buff); + return NULL; + } + return buff; +} + +/* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated to the end of the + * bstring b. The stream read is terminated by the passed in terminator + * parameter. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * function returns with a partial result in b. If there is an empty partial + * result, 1 is returned. If no characters are read, or there is some other + * detectable error, BSTR_ERR is returned. + */ +int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) { +int c, d, e; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; + d = 0; + e = b->mlen - 2; + + while ((c = getcPtr (parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + e = b->mlen - 2; + } + b->data[d] = (unsigned char) c; + d++; + if (c == terminator) break; + } + + b->data[d] = (unsigned char) '\0'; + b->slen = d; + + return d == 0 && c < 0; +} + +/* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated to the end of the + * bstring b. The stream read is terminated by the passed in terminator + * parameter. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * function returns with a partial result concatentated to b. If there is + * an empty partial result, 1 is returned. If no characters are read, or + * there is some other detectable error, BSTR_ERR is returned. + */ +int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) { +int c, d, e; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; + d = b->slen; + e = b->mlen - 2; + + while ((c = getcPtr (parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + e = b->mlen - 2; + } + b->data[d] = (unsigned char) c; + d++; + if (c == terminator) break; + } + + b->data[d] = (unsigned char) '\0'; + b->slen = d; + + return d == 0 && c < 0; +} + +/* bstring bgetstream (bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated into a bstring. + * The stream read is terminated by the passed in terminator function. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * result obtained thus far is returned. If no characters are read, or + * there is some other detectable error, NULL is returned. + */ +bstring bgetstream (bNgetc getcPtr, void * parm, char terminator) { +bstring buff; + + if (0 > bgetsa (buff = bfromcstr (""), getcPtr, parm, terminator) || 0 >= buff->slen) { + bdestroy (buff); + buff = NULL; + } + return buff; +} + +struct bStream { + bstring buff; /* Buffer for over-reads */ + void * parm; /* The stream handle for core stream */ + bNread readFnPtr; /* fread compatible fnptr for core stream */ + int isEOF; /* track file's EOF state */ + int maxBuffSz; +}; + +/* struct bStream * bsopen (bNread readPtr, void * parm) + * + * Wrap a given open stream (described by a fread compatible function + * pointer and stream handle) into an open bStream suitable for the bstring + * library streaming functions. + */ +struct bStream * bsopen (bNread readPtr, void * parm) { +struct bStream * s; + + if (readPtr == NULL) return NULL; + s = (struct bStream *) bstr__alloc (sizeof (struct bStream)); + if (s == NULL) return NULL; + s->parm = parm; + s->buff = bfromcstr (""); + s->readFnPtr = readPtr; + s->maxBuffSz = BS_BUFF_SZ; + s->isEOF = 0; + return s; +} + +/* int bsbufflength (struct bStream * s, int sz) + * + * Set the length of the buffer used by the bStream. If sz is zero, the + * length is not set. This function returns with the previous length. + */ +int bsbufflength (struct bStream * s, int sz) { +int oldSz; + if (s == NULL || sz < 0) return BSTR_ERR; + oldSz = s->maxBuffSz; + if (sz > 0) s->maxBuffSz = sz; + return oldSz; +} + +int bseof (const struct bStream * s) { + if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR; + return s->isEOF && (s->buff->slen == 0); +} + +/* void * bsclose (struct bStream * s) + * + * Close the bStream, and return the handle to the stream that was originally + * used to open the given stream. + */ +void * bsclose (struct bStream * s) { +void * parm; + if (s == NULL) return NULL; + s->readFnPtr = NULL; + if (s->buff) bdestroy (s->buff); + s->buff = NULL; + parm = s->parm; + s->parm = NULL; + s->isEOF = 1; + bstr__free (s); + return parm; +} + +/* int bsreadlna (bstring r, struct bStream * s, char terminator) + * + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and return it into the parameter r. This + * function may read additional characters from the core stream that are not + * returned, but will be retained for subsequent read operations. + */ +int bsreadlna (bstring r, struct bStream * s, char terminator) { +int i, l, ret, rlo; +char * b; +struct tagbstring x; + + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 || + r->slen < 0 || r->mlen < r->slen) return BSTR_ERR; + l = s->buff->slen; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) s->buff->data; + x.data = (unsigned char *) b; + + /* First check if the current buffer holds the terminator */ + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) ; + if (i < l) { + x.slen = i + 1; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); + return BSTR_OK; + } + + rlo = r->slen; + + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; + + /* Perform direct in-place reads into the destination to allow for + the minimum of data-copies */ + for (;;) { + if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) (r->data + r->slen); + l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char) '\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) ; + if (i < l) break; + r->slen += l; + } + + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + bstr__memcpy (s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bsreadlnsa (bstring r, struct bStream * s, bstring term) + * + * Read a bstring terminated by any character in the term string or the end + * of the stream from the bStream (s) and return it into the parameter r. + * This function may read additional characters from the core stream that + * are not returned, but will be retained for subsequent read operations. + */ +int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) { +int i, l, ret, rlo; +unsigned char * b; +struct tagbstring x; +struct charField cf; + + if (s == NULL || s->buff == NULL || r == NULL || term == NULL || + term->data == NULL || r->mlen <= 0 || r->slen < 0 || + r->mlen < r->slen) return BSTR_ERR; + if (term->slen == 1) return bsreadlna (r, s, term->data[0]); + if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR; + + l = s->buff->slen; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (unsigned char *) s->buff->data; + x.data = b; + + /* First check if the current buffer holds the terminator */ + b[l] = term->data[0]; /* Set sentinel */ + for (i=0; !testInCharField (&cf, b[i]); i++) ; + if (i < l) { + x.slen = i + 1; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); + return BSTR_OK; + } + + rlo = r->slen; + + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; + + /* Perform direct in-place reads into the destination to allow for + the minimum of data-copies */ + for (;;) { + if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; + b = (unsigned char *) (r->data + r->slen); + l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char) '\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + + b[l] = term->data[0]; /* Set sentinel */ + for (i=0; !testInCharField (&cf, b[i]); i++) ; + if (i < l) break; + r->slen += l; + } + + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + bstr__memcpy (s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bsreada (bstring r, struct bStream * s, int n) + * + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream. This function may read additional + * characters from the core stream that are not returned, but will be + * retained for subsequent read operations. This function will not read + * additional characters from the core stream beyond virtual stream pointer. + */ +int bsreada (bstring r, struct bStream * s, int n) { +int l, ret, orslen; +char * b; +struct tagbstring x; + + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 + || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR; + + n += r->slen; + if (n <= 0) return BSTR_ERR; + + l = s->buff->slen; + + orslen = r->slen; + + if (0 == l) { + if (s->isEOF) return BSTR_ERR; + if (r->mlen > n) { + l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm); + if (0 >= l || l > n - r->slen) { + s->isEOF = 1; + return BSTR_ERR; + } + r->slen += l; + r->data[r->slen] = (unsigned char) '\0'; + return 0; + } + } + + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) s->buff->data; + x.data = (unsigned char *) b; + + do { + if (l + r->slen >= n) { + x.slen = n - r->slen; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen); + return BSTR_ERR & -(r->slen == orslen); + } + + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) break; + + l = n - r->slen; + if (l > s->maxBuffSz) l = s->maxBuffSz; + + l = (int) s->readFnPtr (b, 1, l, s->parm); + + } while (l > 0); + if (l < 0) l = 0; + if (l == 0) s->isEOF = 1; + s->buff->slen = l; + return BSTR_ERR & -(r->slen == orslen); +} + +/* int bsreadln (bstring r, struct bStream * s, char terminator) + * + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and return it into the parameter r. This + * function may read additional characters from the core stream that are not + * returned, but will be retained for subsequent read operations. + */ +int bsreadln (bstring r, struct bStream * s, char terminator) { + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0) + return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreadlna (r, s, terminator); +} + +/* int bsreadlns (bstring r, struct bStream * s, bstring term) + * + * Read a bstring terminated by any character in the term string or the end + * of the stream from the bStream (s) and return it into the parameter r. + * This function may read additional characters from the core stream that + * are not returned, but will be retained for subsequent read operations. + */ +int bsreadlns (bstring r, struct bStream * s, const_bstring term) { + if (s == NULL || s->buff == NULL || r == NULL || term == NULL + || term->data == NULL || r->mlen <= 0) return BSTR_ERR; + if (term->slen == 1) return bsreadln (r, s, term->data[0]); + if (term->slen < 1) return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreadlnsa (r, s, term); +} + +/* int bsread (bstring r, struct bStream * s, int n) + * + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream. This function may read additional + * characters from the core stream that are not returned, but will be + * retained for subsequent read operations. This function will not read + * additional characters from the core stream beyond virtual stream pointer. + */ +int bsread (bstring r, struct bStream * s, int n) { + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 + || n <= 0) return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreada (r, s, n); +} + +/* int bsunread (struct bStream * s, const_bstring b) + * + * Insert a bstring into the bStream at the current position. These + * characters will be read prior to those that actually come from the core + * stream. + */ +int bsunread (struct bStream * s, const_bstring b) { + if (s == NULL || s->buff == NULL) return BSTR_ERR; + return binsert (s->buff, 0, b, (unsigned char) '?'); +} + +/* int bspeek (bstring r, const struct bStream * s) + * + * Return the currently buffered characters from the bStream that will be + * read prior to reads from the core stream. + */ +int bspeek (bstring r, const struct bStream * s) { + if (s == NULL || s->buff == NULL) return BSTR_ERR; + return bassign (r, s->buff); +} + +/* bstring bjoin (const struct bstrList * bl, const_bstring sep); + * + * Join the entries of a bstrList into one bstring by sequentially + * concatenating them with the sep string in between. If there is an error + * NULL is returned, otherwise a bstring with the correct result is returned. + */ +bstring bjoin (const struct bstrList * bl, const_bstring sep) { +bstring b; +int i, c, v; + + if (bl == NULL || bl->qty < 0) return NULL; + if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL; + + for (i = 0, c = 1; i < bl->qty; i++) { + v = bl->entry[i]->slen; + if (v < 0) return NULL; /* Invalid input */ + c += v; + if (c < 0) return NULL; /* Wrap around ?? */ + } + + if (sep != NULL) c += (bl->qty - 1) * sep->slen; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (NULL == b) return NULL; /* Out of memory */ + b->data = (unsigned char *) bstr__alloc (c); + if (b->data == NULL) { + bstr__free (b); + return NULL; + } + + b->mlen = c; + b->slen = c-1; + + for (i = 0, c = 0; i < bl->qty; i++) { + if (i > 0 && sep != NULL) { + bstr__memcpy (b->data + c, sep->data, sep->slen); + c += sep->slen; + } + v = bl->entry[i]->slen; + bstr__memcpy (b->data + c, bl->entry[i]->data, v); + c += v; + } + b->data[c] = (unsigned char) '\0'; + return b; +} + +#define BSSSC_BUFF_LEN (256) + +/* int bssplitscb (struct bStream * s, const_bstring splitStr, + * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) + * + * Iterate the set of disjoint sequential substrings read from a stream + * divided by any of the characters in splitStr. An empty splitStr causes + * the whole stream to be iterated once. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitscb will continue by starting the next split + * at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + */ +int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { +struct charField chrs; +bstring buff; +int i, p, ret; + + if (cb == NULL || s == NULL || s->readFnPtr == NULL + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; + + if (splitStr->slen == 0) { + while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ; + if ((ret = cb (parm, 0, buff)) > 0) + ret = 0; + } else { + buildCharField (&chrs, splitStr); + ret = p = i = 0; + for (;;) { + if (i >= buff->slen) { + bsreada (buff, s, BSSSC_BUFF_LEN); + if (i >= buff->slen) { + if (0 < (ret = cb (parm, p, buff))) ret = 0; + break; + } + } + if (testInCharField (&chrs, buff->data[i])) { + struct tagbstring t; + unsigned char c; + + blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1)); + if ((ret = bsunread (s, &t)) < 0) break; + buff->slen = i; + c = buff->data[i]; + buff->data[i] = (unsigned char) '\0'; + if ((ret = cb (parm, p, buff)) < 0) break; + buff->data[i] = c; + buff->slen = 0; + p += i + 1; + i = -1; + } + i++; + } + } + + bdestroy (buff); + return ret; +} + +/* int bssplitstrcb (struct bStream * s, const_bstring splitStr, + * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) + * + * Iterate the set of disjoint sequential substrings read from a stream + * divided by the entire substring splitStr. An empty splitStr causes + * each character of the stream to be iterated. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitscb will continue by starting the next split + * at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + */ +int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { +bstring buff; +int i, p, ret; + + if (cb == NULL || s == NULL || s->readFnPtr == NULL + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm); + + if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; + + if (splitStr->slen == 0) { + for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) { + if ((ret = cb (parm, 0, buff)) < 0) { + bdestroy (buff); + return ret; + } + buff->slen = 0; + } + return BSTR_OK; + } else { + ret = p = i = 0; + for (i=p=0;;) { + if ((ret = binstr (buff, 0, splitStr)) >= 0) { + struct tagbstring t; + blk2tbstr (t, buff->data, ret); + i = ret + splitStr->slen; + if ((ret = cb (parm, p, &t)) < 0) break; + p += i; + bdelete (buff, 0, i); + } else { + bsreada (buff, s, BSSSC_BUFF_LEN); + if (bseof (s)) { + if ((ret = cb (parm, p, buff)) > 0) ret = 0; + break; + } + } + } + } + + bdestroy (buff); + return ret; +} + +/* int bstrListCreate (void) + * + * Create a bstrList. + */ +struct bstrList * bstrListCreate (void) { +struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (sl) { + sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring)); + if (!sl->entry) { + bstr__free (sl); + sl = NULL; + } else { + sl->qty = 0; + sl->mlen = 1; + } + } + return sl; +} + +/* int bstrListDestroy (struct bstrList * sl) + * + * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate. + */ +int bstrListDestroy (struct bstrList * sl) { +int i; + if (sl == NULL || sl->qty < 0) return BSTR_ERR; + for (i=0; i < sl->qty; i++) { + if (sl->entry[i]) { + bdestroy (sl->entry[i]); + sl->entry[i] = NULL; + } + } + sl->qty = -1; + sl->mlen = -1; + bstr__free (sl->entry); + sl->entry = NULL; + bstr__free (sl); + return BSTR_OK; +} + +/* int bstrListAlloc (struct bstrList * sl, int msz) + * + * Ensure that there is memory for at least msz number of entries for the + * list. + */ +int bstrListAlloc (struct bstrList * sl, int msz) { +bstring * l; +int smsz; +size_t nsz; + if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; + if (sl->mlen >= msz) return BSTR_OK; + smsz = snapUpSize (msz); + nsz = ((size_t) smsz) * sizeof (bstring); + if (nsz < (size_t) smsz) return BSTR_ERR; + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) { + smsz = msz; + nsz = ((size_t) smsz) * sizeof (bstring); + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) return BSTR_ERR; + } + sl->mlen = smsz; + sl->entry = l; + return BSTR_OK; +} + +/* int bstrListAllocMin (struct bstrList * sl, int msz) + * + * Try to allocate the minimum amount of memory for the list to include at + * least msz entries or sl->qty whichever is greater. + */ +int bstrListAllocMin (struct bstrList * sl, int msz) { +bstring * l; +size_t nsz; + if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; + if (msz < sl->qty) msz = sl->qty; + if (sl->mlen == msz) return BSTR_OK; + nsz = ((size_t) msz) * sizeof (bstring); + if (nsz < (size_t) msz) return BSTR_ERR; + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) return BSTR_ERR; + sl->mlen = msz; + sl->entry = l; + return BSTR_OK; +} + +/* int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by the + * character in splitChar. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitcb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitcb will continue in an undefined manner. + */ +int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen) + return BSTR_ERR; + + p = pos; + do { + for (i=p; i < str->slen; i++) { + if (str->data[i] == splitChar) break; + } + if ((ret = cb (parm, p, i - p)) < 0) return ret; + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +/* int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by any + * of the characters in splitStr. An empty splitStr causes the whole str to + * be iterated once. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitscb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitscb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + */ +int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +struct charField chrs; +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + if (splitStr->slen == 0) { + if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0; + return ret; + } + + if (splitStr->slen == 1) + return bsplitcb (str, splitStr->data[0], pos, cb, parm); + + buildCharField (&chrs, splitStr); + + p = pos; + do { + for (i=p; i < str->slen; i++) { + if (testInCharField (&chrs, str->data[i])) break; + } + if ((ret = cb (parm, p, i - p)) < 0) return ret; + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +/* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by the + * substring splitStr. An empty splitStr causes the whole str to be + * iterated once. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitstrcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitscb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + */ +int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (0 == splitStr->slen) { + for (i=pos; i < str->slen; i++) { + if ((ret = cb (parm, i, 1)) < 0) return ret; + } + return BSTR_OK; + } + + if (splitStr->slen == 1) + return bsplitcb (str, splitStr->data[0], pos, cb, parm); + + for (i=p=pos; i <= str->slen - splitStr->slen; i++) { + if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) { + if ((ret = cb (parm, p, i - p)) < 0) return ret; + i += splitStr->slen; + p = i; + } + } + if ((ret = cb (parm, p, str->slen - p)) < 0) return ret; + return BSTR_OK; +} + +struct genBstrList { + bstring b; + struct bstrList * bl; +}; + +static int bscb (void * parm, int ofs, int len) { +struct genBstrList * g = (struct genBstrList *) parm; + if (g->bl->qty >= g->bl->mlen) { + int mlen = g->bl->mlen * 2; + bstring * tbl; + + while (g->bl->qty >= mlen) { + if (mlen < g->bl->mlen) return BSTR_ERR; + mlen += mlen; + } + + tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen); + if (tbl == NULL) return BSTR_ERR; + + g->bl->entry = tbl; + g->bl->mlen = mlen; + } + + g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len); + g->bl->qty++; + return BSTR_OK; +} + +/* struct bstrList * bsplit (const_bstring str, unsigned char splitChar) + * + * Create an array of sequential substrings from str divided by the character + * splitChar. + */ +struct bstrList * bsplit (const_bstring str, unsigned char splitChar) { +struct genBstrList g; + + if (str == NULL || str->data == NULL || str->slen < 0) return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + + g.b = (bstring) str; + g.bl->qty = 0; + if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +/* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) + * + * Create an array of sequential substrings from str divided by the entire + * substring splitStr. + */ +struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) { +struct genBstrList g; + + if (str == NULL || str->data == NULL || str->slen < 0) return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + + g.b = (bstring) str; + g.bl->qty = 0; + if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +/* struct bstrList * bsplits (const_bstring str, bstring splitStr) + * + * Create an array of sequential substrings from str divided by any of the + * characters in splitStr. An empty splitStr causes a single entry bstrList + * containing a copy of str to be returned. + */ +struct bstrList * bsplits (const_bstring str, const_bstring splitStr) { +struct genBstrList g; + + if ( str == NULL || str->slen < 0 || str->data == NULL || + splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL) + return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + g.b = (bstring) str; + g.bl->qty = 0; + + if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +#if defined (__TURBOC__) && !defined (__BORLANDC__) +# ifndef BSTRLIB_NOVSNP +# define BSTRLIB_NOVSNP +# endif +#endif + +/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */ +#if defined(__WATCOMC__) || defined(_MSC_VER) +#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);} +#else +#ifdef BSTRLIB_NOVSNP +/* This is just a hack. If you are using a system without a vsnprintf, it is + not recommended that bformat be used at all. */ +#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;} +#define START_VSNBUFF (256) +#else + +#ifdef __GNUC__ +/* Something is making gcc complain about this prototype not being here, so + I've just gone ahead and put it in. */ +extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg); +#endif + +#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);} +#endif +#endif + +#if !defined (BSTRLIB_NOVSNP) + +#ifndef START_VSNBUFF +#define START_VSNBUFF (16) +#endif + +/* On IRIX vsnprintf returns n-1 when the operation would overflow the target + buffer, WATCOM and MSVC both return -1, while C99 requires that the + returned value be exactly what the length would be if the buffer would be + large enough. This leads to the idea that if the return value is larger + than n, then changing n to the return value will reduce the number of + iterations required. */ + +/* int bformata (bstring b, const char * fmt, ...) + * + * After the first parameter, it takes the same parameters as printf (), but + * rather than outputting results to stdio, it appends the results to + * a bstring which contains what would have been output. Note that if there + * is an early generation of a '\0' character, the bstring will be truncated + * to this end point. + */ +int bformata (bstring b, const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 + || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return BSTR_ERR; + } + } + + r = bconcat (b, buff); + bdestroy (buff); + return r; +} + +/* int bassignformat (bstring b, const char * fmt, ...) + * + * After the first parameter, it takes the same parameters as printf (), but + * rather than outputting results to stdio, it outputs the results to + * the bstring parameter b. Note that if there is an early generation of a + * '\0' character, the bstring will be truncated to this end point. + */ +int bassignformat (bstring b, const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 + || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return BSTR_ERR; + } + } + + r = bassign (b, buff); + bdestroy (buff); + return r; +} + +/* bstring bformat (const char * fmt, ...) + * + * Takes the same parameters as printf (), but rather than outputting results + * to stdio, it forms a bstring which contains what would have been output. + * Note that if there is an early generation of a '\0' character, the + * bstring will be truncated to this end point. + */ +bstring bformat (const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (fmt == NULL) return NULL; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return NULL; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return NULL; + } + } + + return buff; +} + +/* int bvcformata (bstring b, int count, const char * fmt, va_list arglist) + * + * The bvcformata function formats data under control of the format control + * string fmt and attempts to append the result to b. The fmt parameter is + * the same as that of the printf function. The variable argument list is + * replaced with arglist, which has been initialized by the va_start macro. + * The size of the output is upper bounded by count. If the required output + * exceeds count, the string b is not augmented with any contents and a value + * below BSTR_ERR is returned. If a value below -count is returned then it + * is recommended that the negative of this value be used as an update to the + * count in a subsequent pass. On other errors, such as running out of + * memory, parameter errors or numeric wrap around BSTR_ERR is returned. + * BSTR_OK is returned when the output is successfully generated and + * appended to b. + * + * Note: There is no sanity checking of arglist, and this function is + * destructive of the contents of b from the b->slen point onward. If there + * is an early generation of a '\0' character, the bstring will be truncated + * to this end point. + */ +int bvcformata (bstring b, int count, const char * fmt, va_list arg) { +int n, r, l; + + if (b == NULL || fmt == NULL || count <= 0 || b->data == NULL + || b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + if (count > (n = b->slen + count) + 2) return BSTR_ERR; + if (BSTR_OK != balloc (b, n + 2)) return BSTR_ERR; + + exvsnprintf (r, (char *) b->data + b->slen, count + 2, fmt, arg); + + /* Did the operation complete successfully within bounds? */ + + if (n >= (l = b->slen + (int) (strlen) ((const char *) b->data + b->slen))) { + b->slen = l; + return BSTR_OK; + } + + /* Abort, since the buffer was not large enough. The return value + tries to help set what the retry length should be. */ + + b->data[b->slen] = '\0'; + if (r > count+1) l = r; else { + l = count+count; + if (count > l) l = INT_MAX; + } + n = -l; + if (n > BSTR_ERR-1) n = BSTR_ERR-1; + return n; +} + +#endif diff --git a/libatalk/cnid/Makefile.am b/libatalk/cnid/Makefile.am new file mode 100644 index 0000000..5c9dd52 --- /dev/null +++ b/libatalk/cnid/Makefile.am @@ -0,0 +1,29 @@ +# Makefile.am for libatalk/cnid/ + +SUBDIRS = last cdb dbd tdb + +noinst_LTLIBRARIES = libcnid.la +LIBCNID_DEPS = dbd/libcnid_dbd.la + +if USE_CDB_BACKEND +LIBCNID_DEPS += cdb/libcnid_cdb.la +endif + +if USE_LAST_BACKEND +LIBCNID_DEPS += last/libcnid_last.la +endif + +if USE_TDB_BACKEND +LIBCNID_DEPS += tdb/libcnid_tdb.la +endif + +if USE_MYSQL_BACKEND +SUBDIRS += mysql +LIBCNID_DEPS += @MYSQL_LIBS@ mysql/libcnid_mysql.la +endif + +libcnid_la_SOURCES = cnid.c cnid_init.c +libcnid_la_LIBADD = $(LIBCNID_DEPS) + +EXTRA_DIST = README + diff --git a/libatalk/cnid/Makefile.in b/libatalk/cnid/Makefile.in new file mode 100644 index 0000000..bcb6af9 --- /dev/null +++ b/libatalk/cnid/Makefile.in @@ -0,0 +1,802 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/cnid/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@USE_CDB_BACKEND_TRUE@am__append_1 = cdb/libcnid_cdb.la +@USE_LAST_BACKEND_TRUE@am__append_2 = last/libcnid_last.la +@USE_TDB_BACKEND_TRUE@am__append_3 = tdb/libcnid_tdb.la +@USE_MYSQL_BACKEND_TRUE@am__append_4 = mysql +@USE_MYSQL_BACKEND_TRUE@am__append_5 = @MYSQL_LIBS@ mysql/libcnid_mysql.la +subdir = libatalk/cnid +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +@USE_MYSQL_BACKEND_TRUE@am__DEPENDENCIES_1 = mysql/libcnid_mysql.la +am__DEPENDENCIES_2 = dbd/libcnid_dbd.la $(am__append_1) \ + $(am__append_2) $(am__append_3) $(am__DEPENDENCIES_1) +libcnid_la_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_libcnid_la_OBJECTS = cnid.lo cnid_init.lo +libcnid_la_OBJECTS = $(am_libcnid_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcnid_la_SOURCES) +DIST_SOURCES = $(libcnid_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = last cdb dbd tdb mysql +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = last cdb dbd tdb $(am__append_4) +noinst_LTLIBRARIES = libcnid.la +LIBCNID_DEPS = dbd/libcnid_dbd.la $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_5) +libcnid_la_SOURCES = cnid.c cnid_init.c +libcnid_la_LIBADD = $(LIBCNID_DEPS) +EXTRA_DIST = README +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/cnid/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/cnid/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcnid.la: $(libcnid_la_OBJECTS) $(libcnid_la_DEPENDENCIES) $(EXTRA_libcnid_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libcnid_la_OBJECTS) $(libcnid_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cnid.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cnid_init.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist cscopelist-recursive ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am + + +# 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/libatalk/cnid/README b/libatalk/cnid/README new file mode 100644 index 0000000..b78f9af --- /dev/null +++ b/libatalk/cnid/README @@ -0,0 +1,50 @@ + + CNID back-end refactoring + +This patch allows to compile all DID schemes into +afpd binary and then select desired schemes at runtime, +per volume. + + +Changes: + +Libatalk/cnid directory as been restructured. Now it contains +subdirectories representing particular back-end types and a +simple cnid-object factory (cnid.c and cnid_init.c). + +All CNID functions have been grouped into a structure which +contains function pointers and some data. Main afpd code uses +them in a object manner rather than structural: it calls cnid +functions through fields of cnid_db structure. + +Actually there are standard backends: transactional db3, cdb, +last and mtab (I'm not sure how to call mtab - it does some magic +with dev/inode numbers, but mtab has been removed some time ago). + +Changes in ./configure options: + +Options --with-did=xxx, --with-cdb have been removed. + +Instead, there are following options: +--with-cnid-cdb-backend - compile DB3 Concurrent Datastore backend +--with-cnid-db3-backend - compile DB3 transactional backend +--with-cnid-last-backend - compile LAST backend +--with-cnid-mtab-backend - compile MTAB backend +--with-cnid-default-backend={cdb|db3|last|mtab} + +Some of the backend names should be (propably) changed (mtab? db3?). + +AppleVolumes.default file has a new option: -cnidscheme:{db3|cdb|last|mtab} + +Again, sorry for this weird naming. I didn't care about it while coding, +some cleanups have to be done later. + +Was tested mainly against test-suite and against MacOS 9 client. + +Things to do: +- some really reliable kind of backend should be developed +- file-name mangling should be runtime option +- naming- and code cleanups are still needed +- optional dynamic CNID backend loading - lower priority, static linking +option has still to be available + diff --git a/libatalk/cnid/cdb/Makefile.am b/libatalk/cnid/cdb/Makefile.am new file mode 100644 index 0000000..cd3ca24 --- /dev/null +++ b/libatalk/cnid/cdb/Makefile.am @@ -0,0 +1,21 @@ +# Makefile.am for libatalk/cnid/ + +libcnid_cdb_la_SOURCES = cnid_cdb_add.c \ + cnid_cdb_close.c \ + cnid_cdb_delete.c \ + cnid_cdb_get.c \ + cnid_cdb_lookup.c \ + cnid_cdb_open.c \ + cnid_cdb_resolve.c \ + cnid_cdb_update.c \ + cnid_cdb_rebuild_add.c \ + cnid_cdb.h +libcnid_cdb_la_CFLAGS = @BDB_CFLAGS@ +libcnid_cdb_la_LIBADD = @BDB_LIBS@ @PTHREAD_LIBS@ + +if USE_CDB_BACKEND +noinst_LTLIBRARIES = libcnid_cdb.la +endif + +noinst_HEADERS = cnid_cdb_meta.h cnid_cdb_private.h +EXTRA_DIST = README cnid_cdb_meta.c cnid_cdb_nextid.c diff --git a/libatalk/cnid/cdb/Makefile.in b/libatalk/cnid/cdb/Makefile.in new file mode 100644 index 0000000..d4d17f7 --- /dev/null +++ b/libatalk/cnid/cdb/Makefile.in @@ -0,0 +1,761 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/cnid/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/cnid/cdb +DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcnid_cdb_la_DEPENDENCIES = +am_libcnid_cdb_la_OBJECTS = libcnid_cdb_la-cnid_cdb_add.lo \ + libcnid_cdb_la-cnid_cdb_close.lo \ + libcnid_cdb_la-cnid_cdb_delete.lo \ + libcnid_cdb_la-cnid_cdb_get.lo \ + libcnid_cdb_la-cnid_cdb_lookup.lo \ + libcnid_cdb_la-cnid_cdb_open.lo \ + libcnid_cdb_la-cnid_cdb_resolve.lo \ + libcnid_cdb_la-cnid_cdb_update.lo \ + libcnid_cdb_la-cnid_cdb_rebuild_add.lo +libcnid_cdb_la_OBJECTS = $(am_libcnid_cdb_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libcnid_cdb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libcnid_cdb_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +@USE_CDB_BACKEND_TRUE@am_libcnid_cdb_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcnid_cdb_la_SOURCES) +DIST_SOURCES = $(libcnid_cdb_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +libcnid_cdb_la_SOURCES = cnid_cdb_add.c \ + cnid_cdb_close.c \ + cnid_cdb_delete.c \ + cnid_cdb_get.c \ + cnid_cdb_lookup.c \ + cnid_cdb_open.c \ + cnid_cdb_resolve.c \ + cnid_cdb_update.c \ + cnid_cdb_rebuild_add.c \ + cnid_cdb.h + +libcnid_cdb_la_CFLAGS = @BDB_CFLAGS@ +libcnid_cdb_la_LIBADD = @BDB_LIBS@ @PTHREAD_LIBS@ +@USE_CDB_BACKEND_TRUE@noinst_LTLIBRARIES = libcnid_cdb.la +noinst_HEADERS = cnid_cdb_meta.h cnid_cdb_private.h +EXTRA_DIST = README cnid_cdb_meta.c cnid_cdb_nextid.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/cnid/cdb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/cnid/cdb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcnid_cdb.la: $(libcnid_cdb_la_OBJECTS) $(libcnid_cdb_la_DEPENDENCIES) $(EXTRA_libcnid_cdb_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcnid_cdb_la_LINK) $(am_libcnid_cdb_la_rpath) $(libcnid_cdb_la_OBJECTS) $(libcnid_cdb_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_add.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_close.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_delete.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_get.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_lookup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_open.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_rebuild_add.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_resolve.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_cdb_la-cnid_cdb_update.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libcnid_cdb_la-cnid_cdb_add.lo: cnid_cdb_add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_add.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_add.Tpo -c -o libcnid_cdb_la-cnid_cdb_add.lo `test -f 'cnid_cdb_add.c' || echo '$(srcdir)/'`cnid_cdb_add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_add.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_add.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_add.c' object='libcnid_cdb_la-cnid_cdb_add.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_add.lo `test -f 'cnid_cdb_add.c' || echo '$(srcdir)/'`cnid_cdb_add.c + +libcnid_cdb_la-cnid_cdb_close.lo: cnid_cdb_close.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_close.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_close.Tpo -c -o libcnid_cdb_la-cnid_cdb_close.lo `test -f 'cnid_cdb_close.c' || echo '$(srcdir)/'`cnid_cdb_close.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_close.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_close.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_close.c' object='libcnid_cdb_la-cnid_cdb_close.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_close.lo `test -f 'cnid_cdb_close.c' || echo '$(srcdir)/'`cnid_cdb_close.c + +libcnid_cdb_la-cnid_cdb_delete.lo: cnid_cdb_delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_delete.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_delete.Tpo -c -o libcnid_cdb_la-cnid_cdb_delete.lo `test -f 'cnid_cdb_delete.c' || echo '$(srcdir)/'`cnid_cdb_delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_delete.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_delete.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_delete.c' object='libcnid_cdb_la-cnid_cdb_delete.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_delete.lo `test -f 'cnid_cdb_delete.c' || echo '$(srcdir)/'`cnid_cdb_delete.c + +libcnid_cdb_la-cnid_cdb_get.lo: cnid_cdb_get.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_get.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_get.Tpo -c -o libcnid_cdb_la-cnid_cdb_get.lo `test -f 'cnid_cdb_get.c' || echo '$(srcdir)/'`cnid_cdb_get.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_get.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_get.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_get.c' object='libcnid_cdb_la-cnid_cdb_get.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_get.lo `test -f 'cnid_cdb_get.c' || echo '$(srcdir)/'`cnid_cdb_get.c + +libcnid_cdb_la-cnid_cdb_lookup.lo: cnid_cdb_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_lookup.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_lookup.Tpo -c -o libcnid_cdb_la-cnid_cdb_lookup.lo `test -f 'cnid_cdb_lookup.c' || echo '$(srcdir)/'`cnid_cdb_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_lookup.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_lookup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_lookup.c' object='libcnid_cdb_la-cnid_cdb_lookup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_lookup.lo `test -f 'cnid_cdb_lookup.c' || echo '$(srcdir)/'`cnid_cdb_lookup.c + +libcnid_cdb_la-cnid_cdb_open.lo: cnid_cdb_open.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_open.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_open.Tpo -c -o libcnid_cdb_la-cnid_cdb_open.lo `test -f 'cnid_cdb_open.c' || echo '$(srcdir)/'`cnid_cdb_open.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_open.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_open.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_open.c' object='libcnid_cdb_la-cnid_cdb_open.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_open.lo `test -f 'cnid_cdb_open.c' || echo '$(srcdir)/'`cnid_cdb_open.c + +libcnid_cdb_la-cnid_cdb_resolve.lo: cnid_cdb_resolve.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_resolve.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_resolve.Tpo -c -o libcnid_cdb_la-cnid_cdb_resolve.lo `test -f 'cnid_cdb_resolve.c' || echo '$(srcdir)/'`cnid_cdb_resolve.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_resolve.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_resolve.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_resolve.c' object='libcnid_cdb_la-cnid_cdb_resolve.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_resolve.lo `test -f 'cnid_cdb_resolve.c' || echo '$(srcdir)/'`cnid_cdb_resolve.c + +libcnid_cdb_la-cnid_cdb_update.lo: cnid_cdb_update.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_update.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_update.Tpo -c -o libcnid_cdb_la-cnid_cdb_update.lo `test -f 'cnid_cdb_update.c' || echo '$(srcdir)/'`cnid_cdb_update.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_update.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_update.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_update.c' object='libcnid_cdb_la-cnid_cdb_update.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_update.lo `test -f 'cnid_cdb_update.c' || echo '$(srcdir)/'`cnid_cdb_update.c + +libcnid_cdb_la-cnid_cdb_rebuild_add.lo: cnid_cdb_rebuild_add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -MT libcnid_cdb_la-cnid_cdb_rebuild_add.lo -MD -MP -MF $(DEPDIR)/libcnid_cdb_la-cnid_cdb_rebuild_add.Tpo -c -o libcnid_cdb_la-cnid_cdb_rebuild_add.lo `test -f 'cnid_cdb_rebuild_add.c' || echo '$(srcdir)/'`cnid_cdb_rebuild_add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_cdb_la-cnid_cdb_rebuild_add.Tpo $(DEPDIR)/libcnid_cdb_la-cnid_cdb_rebuild_add.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_cdb_rebuild_add.c' object='libcnid_cdb_la-cnid_cdb_rebuild_add.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_cdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_cdb_la-cnid_cdb_rebuild_add.lo `test -f 'cnid_cdb_rebuild_add.c' || echo '$(srcdir)/'`cnid_cdb_rebuild_add.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/cnid/cdb/README b/libatalk/cnid/cdb/README new file mode 100644 index 0000000..b39889b --- /dev/null +++ b/libatalk/cnid/cdb/README @@ -0,0 +1,35 @@ +the catalog database keeps track of three mappings: + CNID -> dev/ino and did/name + dev/ino -> CNID + did/name -> CNID + +dev/ino is used to keep track of magically moved files. did/name is +for quick lookups of CNIDs. + +NOTE: the database will append a nul byte to the end of name. in +addition, name should be given as it appears on disk. this allows the +creation of cnid updating/cleaning programs that don't have to deal +with knowing what the particular codepage is. + +here's the ritual: + 1) open a volume. call cnid_open. + 2) every time you need a CNID, call cnid_add(). it will + automatically look for an existing cnid and add a new one + if one isn't already there. you can pass a hint if you + want. the only use this has right now is to enable + consistency between AFP and HFS. in the future, it would + allow people to write conversion utilities that + pre-instantiate a database without needing to re-assign + CNIDs. + 3) if you want to just look for a CNID without automatically + adding one in, you have two choices: + a) cnid_resolve takes a CNID, returns name, and + over-writes the CNID given with the parent DID. this + is good for FPResolveID. + b) cnid_lookup returns a CNID corresponding to the + dev/ino,did/name keys. it will auto-update the catalog + database if there's a discrepancy. + NOTE: cnid_add calls this before adding a new CNID. + 4) when you delete a file or directory, you need to call + cnid_delete with the CNID for that file/directory. + 5) call cnid_close when closing the volume. diff --git a/libatalk/cnid/cdb/cnid_cdb.h b/libatalk/cnid/cdb/cnid_cdb.h new file mode 100644 index 0000000..d6b1727 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb.h @@ -0,0 +1,51 @@ +/* + * interface for database access to cnids. i do it this way to abstract + * things a bit in case we want to change the underlying implementation. + */ + +#ifndef _ATALK_CNID_CDB__H +#define _ATALK_CNID_CDB__H 1 + +#include +#include +#include + +#include + +/* cnid_open.c */ +extern struct _cnid_module cnid_cdb_module; +extern struct _cnid_db *cnid_cdb_open (struct cnid_open_args *args); + +/* cnid_close.c */ +extern void cnid_cdb_close (struct _cnid_db *); + +/* cnid_add.c */ +extern cnid_t cnid_cdb_add (struct _cnid_db *, const struct stat *, cnid_t, + const char *, size_t, cnid_t); +extern int cnid_cdb_getstamp (struct _cnid_db *, void *, const size_t ); + +/* cnid_get.c */ +extern cnid_t cnid_cdb_get (struct _cnid_db *, cnid_t, const char *, size_t); +extern char *cnid_cdb_resolve (struct _cnid_db *, cnid_t *, void *, size_t ); +extern cnid_t cnid_cdb_lookup (struct _cnid_db *, const struct stat *, cnid_t, + const char *, size_t); + +/* cnid_update.c */ +extern int cnid_cdb_update (struct _cnid_db *, cnid_t, const struct stat *, + cnid_t, const char *, size_t); + +/* cnid_delete.c */ +extern int cnid_cdb_delete (struct _cnid_db *, const cnid_t); + +/* cnid_nextid.c */ +extern cnid_t cnid_cdb_nextid (struct _cnid_db *); + +extern int cnid_cdb_lock (void *); +extern int cnid_cdb_unlock (void *); + +extern cnid_t cnid_cdb_rebuild_add (struct _cnid_db *, const struct stat *, + cnid_t, const char *, size_t, cnid_t); + + +#endif /* include/atalk/cnid_cdb.h */ + diff --git a/libatalk/cnid/cdb/cnid_cdb_add.c b/libatalk/cnid/cdb/cnid_cdb_add.c new file mode 100644 index 0000000..18f42c3 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_add.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + * cnid_add (db, dev, ino, did, name, hint): + * add a name to the CNID database. we use both dev/ino and did/name + * to keep track of things. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include +#include "cnid_cdb_private.h" + +extern int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, + cnid_t did, const char *name, size_t len); + +#define tid NULL + +static void make_devino_data(unsigned char *buf, dev_t dev, ino_t ino) +{ + buf[CNID_DEV_LEN - 1] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 2] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 3] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 4] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 5] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 6] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 7] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 8] = dev; + + buf[CNID_DEV_LEN + CNID_INO_LEN - 1] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 2] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 3] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 4] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 5] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 6] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 7] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 8] = ino; +} + +unsigned char *make_cnid_data(u_int32_t flags, const struct stat *st, const cnid_t did, + const char *name, const size_t len) +{ + static unsigned char start[CNID_HEADER_LEN + MAXPATHLEN + 1]; + unsigned char *buf = start +CNID_LEN; + u_int32_t i; + + if (len > MAXPATHLEN) + return NULL; + + make_devino_data(buf, !(flags & CNID_FLAG_NODEV)?st->st_dev:0, st->st_ino); + buf += CNID_DEVINO_LEN; + + i = S_ISDIR(st->st_mode)?1:0; + i = htonl(i); + memcpy(buf, &i, sizeof(i)); + buf += sizeof(i); + + /* did is already in network byte order */ + memcpy(buf, &did, sizeof(did)); + buf += sizeof(did); + + memcpy(buf, name, len); + *(buf + len) = '\0'; + + return start; +} + +/* --------------- */ +static int db_stamp(void *buffer, size_t size) +{ +time_t t; + memset(buffer, 0, size); + /* return the current time. */ + if (size < sizeof(time_t)) + return -1; + t = time(NULL); + memcpy(buffer,&t, sizeof(time_t)); + return 0; + +} + + +/* ----------------------------- */ +static cnid_t get_cnid(CNID_private *db) +{ + DBT rootinfo_key, rootinfo_data; + DBC *cursor; + int rc; + int flag, setstamp=0; + cnid_t hint,id; + char buf[ROOTINFO_DATALEN]; + char stamp[CNID_DEV_LEN]; + + if ((rc = db->db_cnid->cursor(db->db_cnid, NULL, &cursor, DB_WRITECURSOR) ) != 0) { + LOG(log_error, logtype_default, "get_cnid: Unable to get a cursor: %s", db_strerror(rc)); + return CNID_INVALID; + } + + memset(&rootinfo_key, 0, sizeof(rootinfo_key)); + memset(&rootinfo_data, 0, sizeof(rootinfo_data)); + rootinfo_key.data = ROOTINFO_KEY; + rootinfo_key.size = ROOTINFO_KEYLEN; + + switch (rc = cursor->c_get(cursor, &rootinfo_key, &rootinfo_data, DB_SET)) { + case 0: + memcpy(&hint, (char *)rootinfo_data.data +CNID_TYPE_OFS, sizeof(hint)); + id = ntohl(hint); + /* If we've hit the max CNID allowed, we return a fatal error. CNID + * needs to be recycled before proceding. */ + if (++id == CNID_INVALID) { + LOG(log_error, logtype_default, "cnid_add: FATAL: CNID database has reached its limit."); + errno = CNID_ERR_MAX; + goto cleanup; + } + hint = htonl(id); + flag = DB_CURRENT; + break; + case DB_NOTFOUND: + hint = htonl(CNID_START); + flag = DB_KEYFIRST; + setstamp = 1; + break; + default: + LOG(log_error, logtype_default, "cnid_add: Unable to lookup rootinfo: %s", db_strerror(rc)); + errno = CNID_ERR_DB; + goto cleanup; + } + + memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN); + rootinfo_data.data = buf; + rootinfo_data.size = ROOTINFO_DATALEN; + memcpy((char *)rootinfo_data.data +CNID_TYPE_OFS, &hint, sizeof(hint)); + if (setstamp) { + if (db_stamp(stamp, CNID_DEV_LEN) < 0) { + goto cleanup; + } + memcpy((char *)rootinfo_data.data +CNID_DEV_OFS, stamp, sizeof(stamp)); + } + + + switch (rc = cursor->c_put(cursor, &rootinfo_key, &rootinfo_data, flag)) { + case 0: + break; + default: + LOG(log_error, logtype_default, "cnid_add: Unable to update rootinfo: %s", db_strerror(rc)); + errno = CNID_ERR_DB; + goto cleanup; + } + if ((rc = cursor->c_close(cursor)) != 0) { + LOG(log_error, logtype_default, "get_cnid: Unable to close cursor: %s", db_strerror(rc)); + errno = CNID_ERR_DB; + return CNID_INVALID; + } + return hint; +cleanup: + if ((rc = cursor->c_close(cursor)) != 0) { + LOG(log_error, logtype_default, "get_cnid: Unable to close cursor: %s", db_strerror(rc)); + return CNID_INVALID; + } + return CNID_INVALID; +} + +/* ------------------------ */ +cnid_t cnid_cdb_add(struct _cnid_db *cdb, const struct stat *st, + cnid_t did, const char *name, size_t len, cnid_t hint) +{ + CNID_private *db; + DBT key, data; + cnid_t id; + int rc; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + /* Do a lookup. */ + id = cnid_cdb_lookup(cdb, st, did, name, len); + /* ... Return id if it is valid, or if Rootinfo is read-only. */ + if (id || (db->flags & CNIDFLAG_DB_RO)) { +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id)); +#endif + return id; + } + + /* Initialize our DBT data structures. */ + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + if ((data.data = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { + LOG(log_error, logtype_default, "cnid_add: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + data.size = CNID_HEADER_LEN + len + 1; + + if ((hint = get_cnid(db)) == 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + memcpy(data.data, &hint, sizeof(hint)); + + key.data = &hint; + key.size = sizeof(hint); + + /* Now we need to add the CNID data to the databases. */ + if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, DB_NOOVERWRITE))) { + if (rc == EINVAL) { + /* if we have a duplicate + * on cnid it's a fatal error. + * on dev:inode + * - leftover should have been delete before. + * - a second process already updated the db + * - it's a new file eg our file is already deleted and replaced + * on did:name leftover + */ + if (cnid_cdb_update(cdb, hint, st, did, name, len)) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + } + else { + LOG(log_error, logtype_default + , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", + name, ntohl(hint), db_strerror(rc)); + errno = CNID_ERR_DB; + return CNID_INVALID; + } + } + +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint)); +#endif + + return hint; +} + +/* cnid_cbd_getstamp */ +/*-----------------------*/ +int cnid_cdb_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) +{ + DBT key, data; + int rc; + CNID_private *db; + + if (!cdb || !(db = cdb->cnid_db_private) || !buffer || !len) { + errno = CNID_ERR_PARAM; + return -1; + } + + memset(buffer, 0, len); + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if (0 != (rc = db->db_cnid->get(db->db_cnid, NULL, &key, &data, 0 )) ) { + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_default, "cnid_lookup: Unable to get database stamp: %s", + db_strerror(rc)); + errno = CNID_ERR_DB; + return -1; + } + /* we waste a single ID here... */ + get_cnid(db); + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + if (0 != (rc = db->db_cnid->get(db->db_cnid, NULL, &key, &data, 0 )) ) { + LOG(log_error, logtype_default, "cnid_getstamp: failed to get rootinfo: %s", + db_strerror(rc)); + errno = CNID_ERR_DB; + return -1; + } + } + + memcpy(buffer, (char*)data.data + CNID_DEV_OFS, len); +#ifdef DEBUG + LOG(log_debug9, logtype_cnid, "cnid_getstamp: Returning stamp"); +#endif + return 0; +} + + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_close.c b/libatalk/cnid/cdb/cnid_cdb_close.c new file mode 100644 index 0000000..c5aecee --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_close.c @@ -0,0 +1,36 @@ +/* + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include "cnid_cdb_private.h" + +void cnid_cdb_close(struct _cnid_db *cdb) { + CNID_private *db; + + if (!cdb) { + LOG(log_error, logtype_afpd, "cnid_close called with NULL argument !"); + return; + } + + if (!(db = cdb->cnid_db_private)) { + return; + } + db->db_didname->sync(db->db_didname, 0); + db->db_devino->sync(db->db_devino, 0); + db->db_cnid->sync(db->db_cnid, 0); + + db->db_didname->close(db->db_didname, 0); + db->db_devino->close(db->db_devino, 0); + db->db_cnid->close(db->db_cnid, 0); + + db->dbenv->close(db->dbenv, 0); + + free(db); + free(cdb); +} + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_delete.c b/libatalk/cnid/cdb/cnid_cdb_delete.c new file mode 100644 index 0000000..deaeca4 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_delete.c @@ -0,0 +1,46 @@ +/* + * + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + * cnid_delete: delete a CNID from the database + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include +#include "cnid_cdb_private.h" + +#define tid NULL + +int cnid_cdb_delete(struct _cnid_db *cdb, const cnid_t id) { + CNID_private *db; + DBT key; + int rc; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || (db->flags & CNIDFLAG_DB_RO)) { + return -1; + } + + memset(&key, 0, sizeof(key)); + + /* Get from ain CNID database. */ + key.data = (cnid_t *)&id; + key.size = sizeof(id); + + if ((rc = db->db_cnid->del(db->db_cnid, tid, &key, 0))) { + LOG(log_error, logtype_default, "cnid_delete: Unable to delete CNID %u: %s", + ntohl(id), db_strerror(rc)); + } + else { +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_delete: Deleting CNID %u", ntohl(id)); +#endif + } + return rc; +} + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_get.c b/libatalk/cnid/cdb/cnid_cdb_get.c new file mode 100644 index 0000000..9c682a8 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_get.c @@ -0,0 +1,50 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include "cnid_cdb_private.h" + +/* Return CNID for a given did/name. */ +cnid_t cnid_cdb_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len) +{ + char start[CNID_DID_LEN + MAXPATHLEN + 1], *buf; + CNID_private *db; + DBT key, data; + cnid_t id; + int rc; + + if (!cdb || !(db = cdb->cnid_db_private) || (len > MAXPATHLEN)) { + return 0; + } + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + buf = start; + memcpy(buf, &did, sizeof(did)); + buf += sizeof(did); + memcpy(buf, name, len); + *(buf + len) = '\0'; /* Make it a C-string. */ + key.data = start; + key.size = CNID_DID_LEN + len + 1; + + while ((rc = db->db_didname->get(db->db_didname, NULL, &key, &data, 0))) { + + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_default, "cnid_get: Unable to get CNID %u, name %s: %s", + ntohl(did), name, db_strerror(rc)); + } + + return 0; + } + + memcpy(&id, data.data, sizeof(id)); +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_get: Returning CNID for %u, name %s as %u", + ntohl(did), name, ntohl(id)); +#endif + return id; +} + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_lookup.c b/libatalk/cnid/cdb/cnid_cdb_lookup.c new file mode 100644 index 0000000..950709d --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_lookup.c @@ -0,0 +1,136 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include "cnid_cdb_private.h" + +#define LOGFILEMAX 100 /* kbytes */ +#define CHECKTIMEMAX 30 /* minutes */ + +/* This returns the CNID corresponding to a particular file. It will + * also fix up the various databases if there's a problem. */ +cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, + const char *name, size_t len) +{ + unsigned char *buf; + CNID_private *db; + DBT key, devdata, diddata; + char dev[CNID_DEV_LEN]; + char ino[CNID_INO_LEN]; + int devino = 1, didname = 1; + u_int32_t type_devino = (unsigned)-1; + u_int32_t type_didname = (unsigned)-1; + u_int32_t type; + int update = 0; + cnid_t id_devino, id_didname,id = 0; + int rc; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { + return 0; + } + + if ((buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { + LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long"); + return 0; + } + + memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type)); + type = ntohl(type); + + memset(&key, 0, sizeof(key)); + memset(&diddata, 0, sizeof(diddata)); + memset(&devdata, 0, sizeof(devdata)); + + /* Look for a CNID for our did/name */ + key.data = buf +CNID_DEVINO_OFS; + key.size = CNID_DEVINO_LEN; + + memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN); + memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN); + + if (0 != (rc = db->db_didname->get(db->db_devino, NULL, &key, &devdata, 0 )) ) { + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s", + did, name, db_strerror(rc)); + return 0; + } + devino = 0; + } + else { + memcpy(&id_devino, devdata.data, sizeof(cnid_t)); + memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino)); + type_devino = ntohl(type_devino); + } + + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); + key.data = buf +CNID_DID_OFS; + key.size = CNID_DID_LEN + len + 1; + + if (0 != (rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0 ) ) ) { + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s", + did, name, db_strerror(rc)); + return 0; + } + didname = 0; + } + else { + memcpy(&id_didname, diddata.data, sizeof(cnid_t)); + memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname)); + type_didname = ntohl(type_didname); + } + + if (!devino && !didname) { + return 0; + } + + if (devino && didname && id_devino == id_didname && type_devino == type) { + /* the same */ + return id_didname; + } + + if (didname) { + id = id_didname; + /* we have a did:name + * if it's the same dev or not the same type + * just delete it + */ + if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) || + type_didname != type) { + if (cnid_cdb_delete(cdb, id) < 0) { + return 0; + } + } + else { + update = 1; + } + } + + if (devino) { + id = id_devino; + if (type_devino != type) { + /* same dev:inode but not same type one is a folder the other + * is a file,it's an inode reused, delete the record + */ + if (cnid_cdb_delete(cdb, id) < 0) { + return 0; + } + } + else { + update = 1; + } + } + if (!update) { + return 0; + } + /* Fix up the database. assume it was a file move and rename */ + cnid_cdb_update(cdb, id, st, did, name, len); + +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id)); +#endif + return id; +} + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_meta.c b/libatalk/cnid/cdb/cnid_cdb_meta.c new file mode 100644 index 0000000..f88a9e2 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_meta.c @@ -0,0 +1,8 @@ +/* + * + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + * deal with metadata + * + */ diff --git a/libatalk/cnid/cdb/cnid_cdb_meta.h b/libatalk/cnid/cdb/cnid_cdb_meta.h new file mode 100644 index 0000000..e8a4bdd --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_meta.h @@ -0,0 +1,50 @@ +/* + */ + +#define CNID_META_CNID_LEN 4 +#define CNID_META_MDATE_LEN 4 /* space for 8 */ +#define CNID_META_CDATE_LEN 4 /* space for 8 */ +#define CNID_META_BDATE_LEN 4 /* ditto */ +#define CNID_META_ADATE_LEN 4 /* ditto */ +#define CNID_META_AFPI_LEN 4 /* plus permission bits */ +#define CNID_META_FINDERI_LEN 32 +#define CNID_META_PRODOSI_LEN 8 +#define CNID_META_RFORKLEN_LEN 4 /* space for 8 */ +#define CNID_META_MACNAME_LEN 32 /* maximum size */ +#define CNID_META_SHORTNAME_LEN 12 /* max size (8.3) */ +#define CNID_META_FILLER_LEN 4 + +#define CNID_META_CNID_OFF 0 +#define CNID_META_MDATE_OFF (CNID_META_CNID_OFF + CNID_META_CNID_LEN + \ + CNID_META_FILLER_LEN) +#define CNID_META_CDATE_OFF (CNID_META_MDATE_OFF + CNID_META_MDATE_LEN + \ + CNID_META_FILLER_LEN) +#define CNID_META_BDATE_OFF (CNID_META_CDATE_OFF + CNID_META_CDATE_LEN + \ + CNID_META_FILLER_LEN) +#define CNID_META_ADATE_OFF (CNID_META_BDATE_OFF + CNID_META_BDATE_LEN + \ + CNID_META_FILLER_LEN) +#define CNID_META_AFPI_OFF (CNID_META_ADATE_OFF + CNID_META_ADATE_LEN) +#define CNID_META_FINDERI_OFF (CNID_META_AFPI_OFF + CNID_META_AFPI_LEN) +#define CNID_META_PRODOSI_OFF (CNID_META_FINDERI_OFF + CNID_META_FINDERI_LEN) +#define CNID_META_RFORKLEN_OFF (CNID_META_PRODOSI_OFF + CNID_META_PRODOSI_LEN) +#define CNID_META_MACNAME_OFF (CNID_META_RFORKLEN_OFF + \ + CNID_META_RFORKLEN_LEN) +#define CNID_META_SHORTNAME_OFF (CNID_META_MACNAME_OFF + + + +#define cnid_meta_clear(a) +#define cnid_meta_get(id) + +#define cnid_meta_cnid(a) +#define cnid_meta_modifydate(a) +#define cnid_meta_createdate(a) +#define cnid_meta_backupdate(a) +#define cnid_meta_accessdate(a) +#define cnid_meta_afpi(a) +#define cnid_meta_finderi(a) +#define cnid_meta_prodosi(a) +#define cnid_meta_rforklen(a) +#define cnid_meta_macname(a) +#define cnid_meta_shortname(a) +#define cnid_meta_longname(a) + diff --git a/libatalk/cnid/cdb/cnid_cdb_nextid.c b/libatalk/cnid/cdb/cnid_cdb_nextid.c new file mode 100644 index 0000000..ba14bd8 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_nextid.c @@ -0,0 +1,28 @@ +/* + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB + +#ifdef unused +#include "cnid_cdb_private.h" + +/* return the next id. we use the fact that ad files are memory + * mapped. */ +cnid_t cnid_cdb_nextid(struct _cnid_db *cdb) +{ + CNID_private *db; + cnid_t id; + + if (!cdb || !(db = cdb->_private)) + return 0; + + memcpy(&id, ad_entry(&db->rootinfo, ADEID_DID), sizeof(id)); + return id; +} +#endif + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_open.c b/libatalk/cnid/cdb/cnid_cdb_open.c new file mode 100644 index 0000000..0a8cfa3 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_open.c @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + * CNID database support. + * + * here's the deal: + * 1) afpd already caches did's. + * 2) the database stores cnid's as both did/name and dev/ino pairs. + * 3) RootInfo holds the value of the NextID. + * 4) the cnid database gets called in the following manner -- + * start a database: + * cnid = cnid_open(root_dir); + * + * allocate a new id: + * newid = cnid_add(cnid, dev, ino, parent did, + * name, id); id is a hint for a specific id. pass 0 if you don't + * care. if the id is already assigned, you won't get what you + * requested. + * + * given an id, get a did/name and dev/ino pair. + * name = cnid_get(cnid, &id); given an id, return the corresponding + * info. + * return code = cnid_delete(cnid, id); delete an entry. + * + * with AFP, CNIDs 0-2 have special meanings. here they are: + * 0 -- invalid cnid + * 1 -- parent of root directory (handled by afpd) + * 2 -- root directory (handled by afpd) + * + * CNIDs 4-16 are reserved according to page 31 of the AFP 3.0 spec so, + * CNID_START begins at 17. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB + +#include +#include +#include "cnid_cdb_private.h" + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif /* ! MIN */ + +#define DBHOME ".AppleDB" +#define DBCNID "cnid2.db" +#define DBDEVINO "devino.db" +#define DBDIDNAME "didname.db" /* did/full name mapping */ +#define DBLOCKFILE "cnid.lock" + +#define DBHOMELEN 8 +#define DBLEN 10 + +#define DBOPTIONS (DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL) + +#define MAXITER 0xFFFF /* maximum number of simultaneously open CNID + * databases. */ + +static char *old_dbfiles[] = {"cnid.db", NULL}; + +/* --------------- */ +static int didname(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) +{ +int len; + + memset(skey, 0, sizeof(DBT)); + skey->data = (char *)pdata->data + CNID_DID_OFS; + len = strlen((char *)skey->data + CNID_DID_LEN); + skey->size = CNID_DID_LEN + len + 1; + return (0); +} + +/* --------------- */ +static int devino(DB *dbp _U_, const DBT *pkey _U_, const DBT *pdata, DBT *skey) +{ + memset(skey, 0, sizeof(DBT)); + skey->data = (char *)pdata->data + CNID_DEVINO_OFS; + skey->size = CNID_DEVINO_LEN; + return (0); +} + +/* --------------- */ +static int my_associate (DB *p, DB *s, + int (*callback)(DB *, const DBT *,const DBT *, DBT *), + u_int32_t flags) +{ +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) + return p->associate(p, NULL, s, callback, flags); +#else +#if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0) + return p->associate(p, s, callback, flags); +#else + return 0; /* FIXME */ +#endif +#endif +} + +/* --------------- */ +static int my_open(DB * p, const char *f, const char *d, DBTYPE t, u_int32_t flags, int mode) +{ +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) + return p->open(p, NULL, f, d, t, flags, mode); +#else + return p->open(p, f, d, t, flags, mode); +#endif +} + +/* --------------- */ +static struct _cnid_db *cnid_cdb_new(struct vol *vol) +{ + struct _cnid_db *cdb; + int major, minor, patch; + char *version_str; + + version_str = db_version(&major, &minor, &patch); + + /* check library match, ignore if only patch level changed */ + if ( major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR) + { + LOG(log_error, logtype_cnid, "cnid_cdb_new: the Berkeley DB library version used does not match the version compiled with: (%u.%u)/(%u.%u)", DB_VERSION_MAJOR, DB_VERSION_MINOR, major, minor); + return NULL; + } + + if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL) + return NULL; + + cdb->cnid_db_vol = vol; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT; + cdb->cnid_add = cnid_cdb_add; + cdb->cnid_delete = cnid_cdb_delete; + cdb->cnid_get = cnid_cdb_get; + cdb->cnid_lookup = cnid_cdb_lookup; + cdb->cnid_nextid = NULL; /*cnid_cdb_nextid;*/ + cdb->cnid_resolve = cnid_cdb_resolve; + cdb->cnid_update = cnid_cdb_update; + cdb->cnid_close = cnid_cdb_close; + cdb->cnid_getstamp = cnid_cdb_getstamp; + cdb->cnid_rebuild_add = cnid_cdb_rebuild_add; + cdb->cnid_wipe = NULL; + return cdb; +} + +/* --------------- */ +static int upgrade_required(char *dbdir) +{ + char path[MAXPATHLEN + 1]; + int len, i; + int found = 0; + struct stat st; + + strcpy(path, dbdir); + + len = strlen(path); + if (path[len - 1] != '/') { + strcat(path, "/"); + len++; + } + + for (i = 0; old_dbfiles[i] != NULL; i++) { + strcpy(path + len, old_dbfiles[i]); + if ( !(stat(path, &st) < 0) ) { + found++; + continue; + } + if (errno != ENOENT) { + LOG(log_error, logtype_default, "cnid_open: Checking %s gave %s", path, strerror(errno)); + found++; + } + } + return found; +} + +/* --------------- */ +struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args) +{ + struct stat st; + char path[MAXPATHLEN + 1]; + CNID_private *db; + struct _cnid_db *cdb; + int open_flag, len; + static int first = 0; + int rc; + struct vol *vol = args->cnid_args_vol; + + /* this checks .AppleDB. + We need space for dir + '/' + DBHOMELEN + '/' + DBLEN */ + if ((len = strlen(vol->v_path)) > (MAXPATHLEN - DBHOMELEN - DBLEN - 2)) { + LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", vol->v_path); + return NULL; + } + + if ((cdb = cnid_cdb_new(vol)) == NULL) { + LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database"); + return NULL; + } + + if ((db = (CNID_private *) calloc(1, sizeof(CNID_private))) == NULL) { + LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database"); + goto fail_cdb; + } + + cdb->cnid_db_private = (void *) db; + + strcpy(path, vol->v_path); + if (path[len - 1] != '/') { + strcat(path, "/"); + len++; + } + + strcpy(path + len, DBHOME); + if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~vol->v_umask) < 0)) { + LOG(log_error, logtype_default, "cnid_open: DBHOME mkdir failed for %s", path); + goto fail_adouble; + } + + if (upgrade_required(path)) { + LOG(log_error, logtype_default, "cnid_open: Found version 1 of the CNID database. Please upgrade to version 2"); + goto fail_adouble; + } + + /* Print out the version of BDB we're linked against. */ + if (!first) { + first = 1; + LOG(log_info, logtype_default, "CNID DB initialized using %s", db_version(NULL, NULL, NULL)); + } + + open_flag = DB_CREATE; + + /* We need to be able to open the database environment with full + * transaction, logging, and locking support if we ever hope to + * be a true multi-acess file server. */ + if ((rc = db_env_create(&db->dbenv, 0)) != 0) { + LOG(log_error, logtype_default, "cnid_open: db_env_create: %s", db_strerror(rc)); + goto fail_lock; + } + + /* Open the database environment. */ + if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~vol->v_umask)) != 0) { + LOG(log_error, logtype_default, "cnid_open: dbenv->open (rw) of %s failed: %s", path, db_strerror(rc)); + /* FIXME: This should probably go. Even if it worked, any use for a read-only DB? Didier? */ + if (rc == DB_RUNRECOVERY) { + /* This is the mother of all errors. We _must_ fail here. */ + LOG(log_error, logtype_default, + "cnid_open: CATASTROPHIC ERROR opening database environment %s. Run db_recovery -c immediately", path); + goto fail_lock; + } + + /* We can't get a full transactional environment, so multi-access + * is out of the question. Let's assume a read-only environment, + * and try to at least get a shared memory pool. */ + if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~vol->v_umask)) != 0) { + /* Nope, not a MPOOL, either. Last-ditch effort: we'll try to + * open the environment with no flags. */ + if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~vol->v_umask)) != 0) { + LOG(log_error, logtype_default, "cnid_open: dbenv->open of %s failed: %s", path, db_strerror(rc)); + goto fail_lock; + } + } + db->flags |= CNIDFLAG_DB_RO; + open_flag = DB_RDONLY; + LOG(log_info, logtype_default, "cnid_open: Obtained read-only database environment %s", path); + } + + /* ---------------------- */ + /* Main CNID database. Use a hash for this one. */ + + if ((rc = db_create(&db->db_cnid, db->dbenv, 0)) != 0) { + LOG(log_error, logtype_default, "cnid_open: Failed to create cnid database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + if ((rc = my_open(db->db_cnid, DBCNID, DBCNID, DB_BTREE, open_flag, 0666 & ~vol->v_umask)) != 0) { + LOG(log_error, logtype_default, "cnid_open: Failed to open dev/ino database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + /* ---------------------- */ + /* did/name reverse mapping. We use a BTree for this one. */ + + if ((rc = db_create(&db->db_didname, db->dbenv, 0)) != 0) { + LOG(log_error, logtype_default, "cnid_open: Failed to create did/name database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + if ((rc = my_open(db->db_didname, DBCNID, DBDIDNAME, DB_BTREE, open_flag, 0666 & ~vol->v_umask))) { + LOG(log_error, logtype_default, "cnid_open: Failed to open did/name database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + /* ---------------------- */ + /* dev/ino reverse mapping. Use a hash for this one. */ + + if ((rc = db_create(&db->db_devino, db->dbenv, 0)) != 0) { + LOG(log_error, logtype_default, "cnid_open: Failed to create dev/ino database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + if ((rc = my_open(db->db_devino, DBCNID, DBDEVINO, DB_BTREE, open_flag, 0666 & ~vol->v_umask)) != 0) { + LOG(log_error, logtype_default, "cnid_open: Failed to open devino database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + /* ---------------------- */ + /* Associate the secondary with the primary. */ + if ((rc = my_associate(db->db_cnid, db->db_didname, didname, 0)) != 0) { + LOG(log_error, logtype_default, "cnid_open: Failed to associate didname database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + if ((rc = my_associate(db->db_cnid, db->db_devino, devino, 0)) != 0) { + LOG(log_error, logtype_default, "cnid_open: Failed to associate devino database: %s", + db_strerror(rc)); + goto fail_appinit; + } + + /* ---------------------- */ + /* Check for version. "cdb" only supports CNID_VERSION_0, cf cnid_private.h */ + + DBT key, data; + uint32_t version; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.data = ROOTINFO_KEY; + key.size = ROOTINFO_KEYLEN; + + if ((rc = db->db_cnid->get(db->db_cnid, NULL, &key, &data, 0)) == 0) { + /* If not found, ignore it */ + memcpy(&version, data.data + CNID_DID_OFS, sizeof(version)); + version = ntohl(version); + LOG(log_debug, logtype_default, "CNID db version %u", version); + if (version != CNID_VERSION_0) { + LOG(log_error, logtype_default, "Unsupported CNID db version %u, use CNID backend \"dbd\"", version); + goto fail_appinit; + } + } + + return cdb; + + fail_appinit: + if (db->db_didname) + db->db_didname->close(db->db_didname, 0); + if (db->db_devino) + db->db_devino->close(db->db_devino, 0); + if (db->db_cnid) + db->db_cnid->close(db->db_cnid, 0); + LOG(log_error, logtype_default, "cnid_open: Failed to setup CNID DB environment"); + db->dbenv->close(db->dbenv, 0); + + fail_lock: + + fail_adouble: + + free(db); + + fail_cdb: + free(cdb); + + return NULL; +} + +struct _cnid_module cnid_cdb_module = { + "cdb", + {NULL, NULL}, + cnid_cdb_open, + CNID_FLAG_SETUID | CNID_FLAG_BLOCK +}; + + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_private.h b/libatalk/cnid/cdb/cnid_cdb_private.h new file mode 100644 index 0000000..ff28be8 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_private.h @@ -0,0 +1,125 @@ +#ifndef LIBATALK_CDB_PRIVATE_H +#define LIBATALK_CDB_PRIVATE_H 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include "cnid_cdb.h" + +/* record structure + cnid 4 + dev 8 + inode 8 + type/last cnid 4 Not used + did 4 + name strlen(name) +1 + +primary key +cnid +secondary keys +dev/inode +did/name + +*/ + +typedef struct cnid_record { /* helper for debug don't use */ + unsigned int cnid; + dev_t dev; + ino_t inode; + unsigned int type; + unsigned int did; + char name[50]; +} cnid_record; + +typedef struct CNID_private { + u_int32_t magic; + DB *db_cnid; + DB *db_didname; + DB *db_devino; + DB_ENV *dbenv; + int lockfd, flags; + char lock_file[MAXPATHLEN + 1]; +} CNID_private; + +/* XXX stuff below is outdate */ +/* on-disk data format (in network byte order where appropriate) -- + * db_cnid: (key: cnid) + * name size (in bytes) + * dev 4 + * ino 4 + * did 4 + * unix name strlen(name) + 1 + * + * db_didname: (key: did/unix name) + * -- this also caches the bits of .AppleDouble used by FPGetFilDirParam + * so that we don't have to open the header file. + * NOTE: FPCatSearch has to search through all of the directories as + * this stuff doesn't get entered until needed. + * if the entire volume is in the database, though, we can use + * cursor operations to make this faster. + * + * version number is stored with did/name key of 0/0 + * + * cnid 4 + * modfiller 4 (dates only use 4 bytes right now, but we leave space + * moddate 4 for 8. moddate is also used to keep this info + * createfiller 4 up-to-date.) + * createdate 4 + * backfiller 4 + * backupdate 4 + * accfiller 4 (unused) + * accdate 4 (unused) + * AFP info 4 (stores a couple permission bits as well) + * finder info 32 + * prodos info 8 + * rforkfiller 4 + * rforklen 4 + * macname 32 (nul-terminated) + * shortname 12 (nul-terminated) + * longname longnamelen (nul-terminated) + * --------------- + * 132 bytes + longnamelen + * + * db_devino: (key: dev/ino) + * -- this is only used for consistency checks and isn't 1-1 + * cnid 4 + * + * these correspond to the different path types. longname is for the + * 255 unicode character names (path type == ?), macname is for the + * 32-character names (path type == 2), and shortname is for the + * 8+3-character names (path type == 1). + * + * db_longname: (key: did/longname) + * name namelen = strlen(name) + 1 + * + * db_macname: (key: did/macname) + * name namelen = strlen(name) + 1 + * + * db_shortname: (key: did/shortname) + * name namelen = strlen(name) + 1 + */ + +/* construct db_cnid data. NOTE: this is not re-entrant. */ +extern unsigned char *make_cnid_data (u_int32_t flags, const struct stat *,const cnid_t , + const char *, const size_t ); + +#endif /* atalk/cnid/cnid_private.h */ diff --git a/libatalk/cnid/cdb/cnid_cdb_rebuild_add.c b/libatalk/cnid/cdb/cnid_cdb_rebuild_add.c new file mode 100644 index 0000000..9516746 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_rebuild_add.c @@ -0,0 +1,140 @@ +/* + * + * All Rights Reserved. See COPYRIGHT. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include "cnid_cdb_private.h" + +#define tid NULL +#define DEBUG 1 + +#include "cnid_cdb.h" + +/* ----------------------------- */ +static cnid_t set_max_cnid(CNID_private *db, cnid_t hint) +{ + DBT rootinfo_key, rootinfo_data; + int rc; + char buf[ROOTINFO_DATALEN]; + cnid_t id, id1; + time_t t; + + memset(&rootinfo_key, 0, sizeof(rootinfo_key)); + memset(&rootinfo_data, 0, sizeof(rootinfo_data)); + + rootinfo_key.data = ROOTINFO_KEY; + rootinfo_key.size = ROOTINFO_KEYLEN; + + switch ((rc = db->db_cnid->get(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) { + case 0: + memcpy(buf, (char *)rootinfo_data.data, ROOTINFO_DATALEN); + break; + case DB_NOTFOUND: + /* FIXME: This duplicates stuff from cnid_cdb_add.c. + We also implicitely assume that sizeof(time_t) <= CNID_DEV_LEN */ + memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN); + t = time(NULL); + memset(buf + CNID_DEV_OFS, 0, CNID_DEV_LEN); + memcpy(buf + CNID_DEV_OFS, &t, sizeof(time_t)); + id = htonl(CNID_START); + memcpy(buf + CNID_TYPE_OFS, &id, sizeof(id)); + break; + default: + LOG(log_error, logtype_default, "set_max_cnid: Unable to read rootinfo: %s", db_strerror(rc)); + errno = CNID_ERR_DB; + goto cleanup; + } + + memcpy(&id, buf + CNID_TYPE_OFS, sizeof(id)); + id = ntohl(id); + id1 = ntohl(hint); + + if (id1 > id) { + memcpy(buf + CNID_TYPE_OFS, &hint, sizeof(hint)); + rootinfo_data.data = buf; + rootinfo_data.size = ROOTINFO_DATALEN; + if ((rc = db->db_cnid->put(db->db_cnid, tid, &rootinfo_key, &rootinfo_data, 0))) { + LOG(log_error, logtype_default, "set_max_cnid: Unable to write rootinfo: %s", db_strerror(rc)); + errno = CNID_ERR_DB; + goto cleanup; + } + } + + return hint; + +cleanup: + return CNID_INVALID; +} + +cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st, + cnid_t did, const char *name, size_t len, cnid_t hint) +{ + CNID_private *db; + DBT key, data; + int rc; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) { + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + +#if 0 + /* FIXME: Bjoern does a lookup. Should we not overwrite unconditionally? */ + /* Do a lookup. */ + id = cnid_cdb_lookup(cdb, st, did, name, len); + /* ... Return id if it is valid, or if Rootinfo is read-only. */ + if (id || (db->flags & CNIDFLAG_DB_RO)) { +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id)); +#endif + return id; + } +#endif + + /* Initialize our DBT data structures. */ + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + if ((data.data = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { + LOG(log_error, logtype_default, "cnid_add: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + data.size = CNID_HEADER_LEN + len + 1; + + memcpy(data.data, &hint, sizeof(hint)); + + key.data = &hint; + key.size = sizeof(hint); + + /* Now we need to add the CNID data to the databases. */ + if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) { + LOG(log_error, logtype_default + , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", + name, ntohl(hint), db_strerror(rc)); + errno = CNID_ERR_DB; + goto cleanup; + } + + if (set_max_cnid(db, hint) == CNID_INVALID) { + errno = CNID_ERR_DB; + goto cleanup; + } + +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint)); +#endif + + return hint; + +cleanup: + return CNID_INVALID; +} + +#endif /* CNID_BACKEND_CDB */ diff --git a/libatalk/cnid/cdb/cnid_cdb_resolve.c b/libatalk/cnid/cdb/cnid_cdb_resolve.c new file mode 100644 index 0000000..d3f6dab --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_resolve.c @@ -0,0 +1,49 @@ +/* + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include "cnid_cdb_private.h" + +/* Return the did/name pair corresponding to a CNID. */ +char *cnid_cdb_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len) { + CNID_private *db; + DBT key, data; + int rc; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) { + return NULL; + } + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + data.data = buffer; + data.ulen = len; + data.flags = DB_DBT_USERMEM; + + key.data = id; + key.size = sizeof(cnid_t); + while ((rc = db->db_cnid->get(db->db_cnid, NULL, &key, &data, 0))) { + + if (rc != DB_NOTFOUND) { + LOG(log_error, logtype_default, "cnid_resolve: Unable to get did/name: %s", + db_strerror(rc)); + } + + *id = 0; + return NULL; + } + + memcpy(id, (char *)data.data +CNID_DID_OFS, sizeof(cnid_t)); +#ifdef DEBUG + LOG(log_debug9, logtype_default, "cnid_resolve: Returning id = %u, did/name = %s", + ntohl(*id), (char *)data.data + CNID_NAME_OFS); +#endif + return (char *)data.data + CNID_NAME_OFS; +} + +#endif diff --git a/libatalk/cnid/cdb/cnid_cdb_update.c b/libatalk/cnid/cdb/cnid_cdb_update.c new file mode 100644 index 0000000..90c7d93 --- /dev/null +++ b/libatalk/cnid/cdb/cnid_cdb_update.c @@ -0,0 +1,104 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_CDB +#include "cnid_cdb_private.h" + +#define tid NULL + +/* cnid_update: takes the given cnid and updates the metadata. To + * handle the did/name data, there are a bunch of functions to get + * and set the various fields. */ +int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, + cnid_t did, const char *name, size_t len) +{ + unsigned char *buf; + CNID_private *db; + DBT key, pkey, data; + int rc; + int notfound = 0; + char getbuf[CNID_HEADER_LEN + MAXPATHLEN +1]; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) { + return -1; + } + + memset(&key, 0, sizeof(key)); + memset(&pkey, 0, sizeof(pkey)); + memset(&data, 0, sizeof(data)); + + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); + + key.data = buf +CNID_DEVINO_OFS; + key.size = CNID_DEVINO_LEN; + data.data = getbuf; + data.size = CNID_HEADER_LEN + MAXPATHLEN + 1; + + if (0 != (rc = db->db_devino->pget(db->db_devino, tid, &key, &pkey, &data, 0)) ) { +#if DB_VERSION_MAJOR >= 4 + if (rc != DB_NOTFOUND && rc != DB_SECONDARY_BAD) { +#else + if (rc != DB_NOTFOUND) { +#endif + LOG(log_error, logtype_default, "cnid_update: Unable to get devino CNID %u, name %s: %s", + ntohl(did), name, db_strerror(rc)); + goto fin; + } + notfound = 1; + } else { + if ((rc = db->db_cnid->del(db->db_cnid, tid, &pkey, 0))) { + LOG(log_error, logtype_default, "cnid_update: Unable to delete CNID %u: %s", + ntohl(id), db_strerror(rc)); + } + } + + memset(&pkey, 0, sizeof(pkey)); + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); + key.data = buf + CNID_DID_OFS; + key.size = CNID_DID_LEN + len + 1; + + if (0 != (rc = db->db_didname->pget(db->db_didname, tid, &key, &pkey, &data, 0)) ) { +#if DB_VERSION_MAJOR >= 4 + if (rc != DB_NOTFOUND && rc != DB_SECONDARY_BAD) { +#else + if (rc != DB_NOTFOUND) { +#endif + LOG(log_error, logtype_default, "cnid_update: Unable to get didname CNID %u, name %s: %s", + ntohl(did), name, db_strerror(rc)); + goto fin; + } + notfound |= 2; + } else { + if ((rc = db->db_cnid->del(db->db_cnid, tid, &pkey, 0))) { + LOG(log_error, logtype_default, "cnid_update: Unable to delete CNID %u: %s", + ntohl(id), db_strerror(rc)); + } + } + + + memset(&key, 0, sizeof(key)); + key.data = (cnid_t *)&id; + key.size = sizeof(id); + + memset(&data, 0, sizeof(data)); + /* Make a new entry. */ + buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len); + data.data = buf; + memcpy(data.data, &id, sizeof(id)); + data.size = CNID_HEADER_LEN + len + 1; + + /* Update the old CNID with the new info. */ + if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) { + LOG(log_error, logtype_default, "cnid_update: (%d) Unable to update CNID %u:%s: %s", + notfound, ntohl(id), name, db_strerror(rc)); + goto fin; + } + + return 0; +fin: + return -1; + +} + +#endif diff --git a/libatalk/cnid/cnid.c b/libatalk/cnid/cnid.c new file mode 100644 index 0000000..fde4d70 --- /dev/null +++ b/libatalk/cnid/cnid.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2003 the Netatalk Team + * Copyright (c) 2003 Rafal Lewczuk + * + * This program is free software; you can redistribute 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 or later + * version if explicitly stated by any of above copyright holders. + * + */ +#define USE_LIST + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* List of all registered modules. */ +static struct list_head modules = ATALK_LIST_HEAD_INIT(modules); + +static sigset_t sigblockset; +static const struct itimerval none = {{0, 0}, {0, 0}}; + +/* Registers new CNID backend module. */ + +/* Once module has been registered, it cannot be unregistered. */ +void cnid_register(struct _cnid_module *module) +{ + struct list_head *ptr; + + /* Check if our module is already registered. */ + list_for_each(ptr, &modules) + if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, module->name)) { + LOG(log_error, logtype_afpd, "Module with name [%s] is already registered !", module->name); + return; + } + + LOG(log_info, logtype_afpd, "Registering CNID module [%s]", module->name); + ptr = &(module->db_list); + list_add_tail(ptr, &modules); +} + +/* --------------- */ +static int cnid_dir(const char *dir, mode_t mask) +{ + struct stat st, st1; + char tmp[MAXPATHLEN]; + + if (stat(dir, &st) < 0) { + if (errno != ENOENT) + return -1; + if (ad_stat( dir, &st) < 0) + return -1; + + LOG(log_info, logtype_cnid, "Setting uid/gid to %d/%d", st.st_uid, st.st_gid); + if (setegid(st.st_gid) < 0 || seteuid(st.st_uid) < 0) { + LOG(log_error, logtype_cnid, "uid/gid: %s", strerror(errno)); + return -1; + } + + if (mkdir(dir, 0777 & ~mask) < 0) + return -1; + } else { + strlcpy(tmp, dir, sizeof(tmp)); + strlcat(tmp, "/.AppleDB", sizeof(tmp)); + if (stat(tmp, &st1) < 0) /* use .AppleDB owner, if folder already exists */ + st1 = st; + LOG(log_info, logtype_cnid, "Setting uid/gid to %d/%d", st1.st_uid, st1.st_gid); + if (setegid(st1.st_gid) < 0 || seteuid(st1.st_uid) < 0) { + LOG(log_error, logtype_cnid, "uid/gid: %s", strerror(errno)); + return -1; + } + } + return 0; +} + +/* Opens CNID database using particular back-end */ +struct _cnid_db *cnid_open(struct vol *vol, char *type, int flags) +{ + struct _cnid_db *db; + cnid_module *mod = NULL; + struct list_head *ptr; + uid_t uid = -1; + gid_t gid = -1; + + list_for_each(ptr, &modules) { + if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, type)) { + mod = list_entry(ptr, cnid_module, db_list); + break; + } + } + + if (NULL == mod) { + LOG(log_error, logtype_afpd, "Cannot find module named [%s] in registered module list!", type); + return NULL; + } + + if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) { + uid = geteuid(); + gid = getegid(); + if (seteuid(0)) { + LOG(log_error, logtype_afpd, "seteuid failed %s", strerror(errno)); + return NULL; + } + if (cnid_dir(vol->v_path, vol->v_umask) < 0) { + if ( setegid(gid) < 0 || seteuid(uid) < 0) { + LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno)); + exit(EXITERR_SYS); + } + return NULL; + } + } + + struct cnid_open_args args = { + .cnid_args_flags = flags, + .cnid_args_vol = vol + }; + + db = mod->cnid_open(&args); + + if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) { + seteuid(0); + if ( setegid(gid) < 0 || seteuid(uid) < 0) { + LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno)); + exit(EXITERR_SYS); + } + } + + if (NULL == db) { + LOG(log_error, logtype_afpd, "Cannot open CNID db at [%s].", vol->v_path); + return NULL; + } + + db->cnid_db_flags |= mod->flags; + if (flags & CNID_FLAG_NODEV) + db->cnid_db_flags |= CNID_FLAG_NODEV; + + if (db->cnid_db_flags & CNID_FLAG_BLOCK) { + sigemptyset(&sigblockset); + sigaddset(&sigblockset, SIGTERM); + sigaddset(&sigblockset, SIGHUP); + sigaddset(&sigblockset, SIGUSR1); + sigaddset(&sigblockset, SIGUSR2); + sigaddset(&sigblockset, SIGALRM); + } + + return db; +} + +/* ------------------- */ +static void block_signal(uint32_t flags) +{ + if ((flags & CNID_FLAG_BLOCK)) { + pthread_sigmask(SIG_BLOCK, &sigblockset, NULL); + } +} + +/* ------------------- */ +static void unblock_signal(uint32_t flags) +{ + if ((flags & CNID_FLAG_BLOCK)) { + pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL); + } +} + +/* ------------------- + protect against bogus value from the DB. + adddir really doesn't like 2 +*/ +static cnid_t valide(cnid_t id) +{ + if (id == CNID_INVALID) + return id; + + if (id < CNID_START) { + static int err = 0; + if (!err) { + err = 1; + LOG(log_error, logtype_afpd, "Error: Invalid cnid, corrupted DB?"); + } + return CNID_INVALID; + } + return id; +} + +/* Closes CNID database. Currently it's just a wrapper around db->cnid_close(). */ +void cnid_close(struct _cnid_db *db) +{ + uint32_t flags; + + if (NULL == db) { + LOG(log_error, logtype_afpd, "Error: cnid_close called with NULL argument !"); + return; + } + /* cnid_close free db */ + flags = db->cnid_db_flags; + block_signal(flags); + db->cnid_close(db); + unblock_signal(flags); +} + +/* --------------- */ +cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + const char *name, const size_t len, cnid_t hint) +{ + cnid_t ret; + + if (len == 0) + return CNID_INVALID; + + block_signal(cdb->cnid_db_flags); + ret = valide(cdb->cnid_add(cdb, st, did, name, len, hint)); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + +/* --------------- */ +int cnid_delete(struct _cnid_db *cdb, cnid_t id) +{ +int ret; + + block_signal(cdb->cnid_db_flags); + ret = cdb->cnid_delete(cdb, id); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + + +/* --------------- */ +cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, char *name,const size_t len) +{ +cnid_t ret; + + block_signal(cdb->cnid_db_flags); + ret = valide(cdb->cnid_get(cdb, did, name, len)); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + +/* --------------- */ +int cnid_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) +{ +cnid_t ret; +time_t t; + + if (!cdb->cnid_getstamp) { + memset(buffer, 0, len); + /* return the current time. it will invalide cache */ + if (len < sizeof(time_t)) + return -1; + t = time(NULL); + memcpy(buffer, &t, sizeof(time_t)); + return 0; + } + block_signal(cdb->cnid_db_flags); + ret = cdb->cnid_getstamp(cdb, buffer, len); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + +/* --------------- */ +cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + char *name, const size_t len) +{ + cnid_t ret; + + block_signal(cdb->cnid_db_flags); + ret = valide(cdb->cnid_lookup(cdb, st, did, name, len)); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + +/* --------------- */ +int cnid_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen) +{ + int ret; + + if (cdb->cnid_find == NULL) { + LOG(log_error, logtype_cnid, "cnid_find not supported by CNID backend"); + return -1; + } + + block_signal(cdb->cnid_db_flags); + ret = cdb->cnid_find(cdb, name, namelen, buffer, buflen); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + +/* --------------- */ +char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len) +{ +char *ret; + + block_signal(cdb->cnid_db_flags); + ret = cdb->cnid_resolve(cdb, id, buffer, len); + unblock_signal(cdb->cnid_db_flags); + if (ret && !strcmp(ret, "..")) { + LOG(log_error, logtype_afpd, "cnid_resolve: name is '..', corrupted db? "); + ret = NULL; + } + return ret; +} + +/* --------------- */ +int cnid_update (struct _cnid_db *cdb, const cnid_t id, const struct stat *st, + const cnid_t did, char *name, const size_t len) +{ +int ret; + + block_signal(cdb->cnid_db_flags); + ret = cdb->cnid_update(cdb, id, st, did, name, len); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + +/* --------------- */ +cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + char *name, const size_t len, cnid_t hint) +{ +cnid_t ret; + + block_signal(cdb->cnid_db_flags); + ret = cdb->cnid_rebuild_add(cdb, st, did, name, len, hint); + unblock_signal(cdb->cnid_db_flags); + return ret; +} + +/* --------------- */ +int cnid_wipe(struct _cnid_db *cdb) +{ + int ret = 0; + + block_signal(cdb->cnid_db_flags); + if (cdb->cnid_wipe) + ret = cdb->cnid_wipe(cdb); + unblock_signal(cdb->cnid_db_flags); + return ret; +} diff --git a/libatalk/cnid/cnid_init.c b/libatalk/cnid/cnid_init.c new file mode 100644 index 0000000..03cad38 --- /dev/null +++ b/libatalk/cnid/cnid_init.c @@ -0,0 +1,96 @@ + +/* + * + * Copyright (c) 2003 the Netatalk Team + * Copyright (c) 2003 Rafal Lewczuk + * + * This program is free software; you can redistribute 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 or later + * version if explicitly stated by any of above copyright holders. + * + */ + +/* + * This file contains initialization stuff for CNID backends. + * Currently it only employs static bindings. + * No plans for dynamically loaded CNID backends here (temporary). + * Maybe somewhere in the future. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + + +#ifdef CNID_BACKEND_DB3 +extern struct _cnid_module cnid_db3_module; +#endif + +#ifdef CNID_BACKEND_HASH +extern struct _cnid_module cnid_hash_module; +#endif + +#ifdef CNID_BACKEND_LAST +extern struct _cnid_module cnid_last_module; +#endif + +#ifdef CNID_BACKEND_MTAB +extern struct _cnid_module cnid_mtab_module; +#endif + +#ifdef CNID_BACKEND_CDB +extern struct _cnid_module cnid_cdb_module; +#endif + +#ifdef CNID_BACKEND_DBD +extern struct _cnid_module cnid_dbd_module; +#endif + +#ifdef CNID_BACKEND_TDB +extern struct _cnid_module cnid_tdb_module; +#endif + +#ifdef CNID_BACKEND_MYSQL +extern struct _cnid_module cnid_mysql_module; +#endif + +void cnid_init(void) +{ +#ifdef CNID_BACKEND_DB3 + cnid_register(&cnid_db3_module); +#endif + +#ifdef CNID_BACKEND_HASH + cnid_register(&cnid_hash_module); +#endif + +#ifdef CNID_BACKEND_LAST + cnid_register(&cnid_last_module); +#endif + +#ifdef CNID_BACKEND_MTAB + cnid_register(&cnid_mtab_module); +#endif + +#ifdef CNID_BACKEND_CDB + cnid_register(&cnid_cdb_module); +#endif + +#ifdef CNID_BACKEND_DBD + cnid_register(&cnid_dbd_module); +#endif + +#ifdef CNID_BACKEND_TDB + cnid_register(&cnid_tdb_module); +#endif + +#ifdef CNID_BACKEND_MYSQL + cnid_register(&cnid_mysql_module); +#endif +} diff --git a/libatalk/cnid/dbd/Makefile.am b/libatalk/cnid/dbd/Makefile.am new file mode 100644 index 0000000..ecbaa0f --- /dev/null +++ b/libatalk/cnid/dbd/Makefile.am @@ -0,0 +1,6 @@ +# Makefile.am for libatalk/cnid/ + +noinst_LTLIBRARIES = libcnid_dbd.la + +libcnid_dbd_la_SOURCES = cnid_dbd.c cnid_dbd.h + diff --git a/libatalk/cnid/dbd/Makefile.in b/libatalk/cnid/dbd/Makefile.in new file mode 100644 index 0000000..0b8f43f --- /dev/null +++ b/libatalk/cnid/dbd/Makefile.in @@ -0,0 +1,661 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/cnid/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/cnid/dbd +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcnid_dbd_la_LIBADD = +am_libcnid_dbd_la_OBJECTS = cnid_dbd.lo +libcnid_dbd_la_OBJECTS = $(am_libcnid_dbd_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcnid_dbd_la_SOURCES) +DIST_SOURCES = $(libcnid_dbd_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libcnid_dbd.la +libcnid_dbd_la_SOURCES = cnid_dbd.c cnid_dbd.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/cnid/dbd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/cnid/dbd/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcnid_dbd.la: $(libcnid_dbd_la_OBJECTS) $(libcnid_dbd_la_DEPENDENCIES) $(EXTRA_libcnid_dbd_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libcnid_dbd_la_OBJECTS) $(libcnid_dbd_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cnid_dbd.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/cnid/dbd/cnid_dbd.c b/libatalk/cnid/dbd/cnid_dbd.c new file mode 100644 index 0000000..d460640 --- /dev/null +++ b/libatalk/cnid/dbd/cnid_dbd.c @@ -0,0 +1,1043 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_DBD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cnid_dbd.h" + +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif /* ! SOL_TCP */ + +/* Wait MAX_DELAY seconds before a request to the CNID server times out */ +#define MAX_DELAY 20 +#define ONE_DELAY 5 + +static void RQST_RESET(struct cnid_dbd_rqst *r) +{ + memset(r, 0, sizeof(struct cnid_dbd_rqst )); +} + +static void delay(int sec) +{ + struct timeval tv; + + tv.tv_usec = 0; + tv.tv_sec = sec; + select(0, NULL, NULL, NULL, &tv); +} + +static int tsock_getfd(const char *host, const char *port) +{ + int sock = -1; + int attr; + int err; + struct addrinfo hints, *servinfo, *p; + int optval; + socklen_t optlen = sizeof(optval); + + /* Prepare hint for getaddrinfo */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; +#ifdef AI_NUMERICSERV + hints.ai_flags = AI_NUMERICSERV; +#endif + + if ((err = getaddrinfo(host, port, &hints, &servinfo)) != 0) { + LOG(log_error, logtype_default, "tsock_getfd: getaddrinfo: CNID server %s:%s : %s\n", + host, port, gai_strerror(err)); + return -1; + } + + /* loop through all the results and bind to the first we can */ + for (p = servinfo; p != NULL; p = p->ai_next) { + if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + LOG(log_info, logtype_default, "tsock_getfd: socket CNID server %s:: %s", + host, strerror(errno)); + continue; + } + + attr = 1; + if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &attr, sizeof(attr)) == -1) { + LOG(log_error, logtype_cnid, "getfd: set TCP_NODELAY CNID server %s: %s", + host, strerror(errno)); + close(sock); + sock = -1; + return -1; + } + + if (setnonblock(sock, 1) != 0) { + LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(errno)); + close(sock); + sock = -1; + return -1; + } + + if (connect(sock, p->ai_addr, p->ai_addrlen) == -1) { + if (errno == EINPROGRESS) { + struct timeval tv; + tv.tv_usec = 0; + tv.tv_sec = 5; /* give it five seconds ... */ + fd_set wfds; + FD_ZERO(&wfds); + FD_SET(sock, &wfds); + + if ((err = select(sock + 1, NULL, &wfds, NULL, &tv)) == 0) { + /* timeout */ + LOG(log_error, logtype_cnid, "getfd: select timed out for CNID server %s", + host); + close(sock); + sock = -1; + continue; + } + if (err == -1) { + /* select failed */ + LOG(log_error, logtype_cnid, "getfd: select failed for CNID server %s", + host); + close(sock); + sock = -1; + continue; + } + + if ( ! FD_ISSET(sock, &wfds)) { + /* give up */ + LOG(log_error, logtype_cnid, "getfd: socket not ready connecting to %s", + host); + close(sock); + sock = -1; + continue; + } + + if ((err = getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen)) != 0 || optval != 0) { + if (err != 0) { + /* somethings very wrong */ + LOG(log_error, logtype_cnid, "getfd: getsockopt error with CNID server %s: %s", + host, strerror(errno)); + } else { + errno = optval; + LOG(log_error, logtype_cnid, "getfd: getsockopt says: %s", + strerror(errno)); + } + close(sock); + sock = -1; + continue; + } + } else { + LOG(log_error, logtype_cnid, "getfd: connect CNID server %s: %s", + host, strerror(errno)); + close(sock); + sock = -1; + continue; + } + } + + /* We've got a socket */ + break; + } + + freeaddrinfo(servinfo); + + if (p == NULL) { + errno = optval; + LOG(log_error, logtype_cnid, "tsock_getfd: no suitable network config from CNID server (%s:%s): %s", + host, port, strerror(errno)); + return -1; + } + + return(sock); +} + +/*! + * Write "towrite" bytes using writev on non-blocking fd + * + * Every short write is considered an error, transmit can handle that. + * + * @param fd (r) socket fd which must be non-blocking + * @param iov (r) iovec for writev + * @param towrite (r) number of bytes in all iovec elements + * @param vecs (r) number of iovecs in array + * + * @returns "towrite" bytes written or -1 on error + */ +static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs) +{ + ssize_t len; + int slept = 0; + int sleepsecs; + + while (1) { + if (((len = writev(fd, iov, vecs)) == -1 && errno == EINTR)) + continue; + + if ((! slept) && len == -1 && errno == EAGAIN) { + sleepsecs = 2; + while ((sleepsecs = sleep(sleepsecs))); + slept = 1; + continue; + } + + if (len == towrite) /* wrote everything out */ + break; + + if (len == -1) + LOG(log_error, logtype_cnid, "write_vec: %s", strerror(errno)); + else + LOG(log_error, logtype_cnid, "write_vec: short write: %d", len); + return len; + } + + LOG(log_maxdebug, logtype_cnid, "write_vec: wrote %d bytes", len); + + return len; +} + +/* --------------------- */ +static int init_tsock(CNID_bdb_private *db) +{ + int fd; + int len[DBD_NUM_OPEN_ARGS]; + int iovecs; + struct iovec iov[DBD_NUM_OPEN_ARGS + 1] = {{0}}; + struct vol *vol = db->vol; + ssize_t iovlen; + + LOG(log_debug, logtype_cnid, "connecting to CNID server: %s:%s", + vol->v_cnidserver, vol->v_cnidport); + + if ((fd = tsock_getfd(vol->v_cnidserver, vol->v_cnidport)) < 0) + return -1; + + LOG(log_debug, logtype_cnid, "connecting volume '%s', path: %s, user: %s", + vol->v_configname, vol->v_path, vol->v_obj->username[0] ? vol->v_obj->username : "-"); + + iovecs = 1 + DBD_NUM_OPEN_ARGS - 1; + + len[0] = strlen(vol->v_configname) + 1; + len[1] = strlen(vol->v_path) + 1; + len[2] = strlen(vol->v_obj->username); + + iov[0].iov_base = &len[0]; + iov[0].iov_len = DBD_NUM_OPEN_ARGS * sizeof(int); + + iov[1].iov_base = vol->v_configname; + iov[1].iov_len = len[0]; + + iov[2].iov_base = vol->v_path; + iov[2].iov_len = len[1]; + + if (len[2] > 0) { + len[2] += 1; + iovecs++; + iov[3].iov_base = vol->v_obj->username; + iov[3].iov_len = len[2]; + } + + iovlen = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len + iov[3].iov_len; + + if (write_vec(fd, iov, iovlen, iovecs) != iovlen) { + LOG(log_error, logtype_cnid, "init_tsock: Error/short write: %s", strerror(errno)); + close(fd); + return -1; + } + + LOG(log_debug, logtype_cnid, "init_tsock: ok"); + + return fd; +} + +/* --------------------- */ +static int send_packet(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst) +{ + struct iovec iov[2]; + size_t towrite; + int vecs; + + iov[0].iov_base = rqst; + iov[0].iov_len = sizeof(struct cnid_dbd_rqst); + towrite = sizeof(struct cnid_dbd_rqst); + vecs = 1; + + if (rqst->namelen) { + iov[1].iov_base = (char *)rqst->name; + iov[1].iov_len = rqst->namelen; + towrite += rqst->namelen; + vecs++; + } + + if (write_vec(db->fd, iov, towrite, vecs) != towrite) { + LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (volume %s): %s", + db->vol->v_localname, strerror(errno)); + return -1; + } + + LOG(log_maxdebug, logtype_cnid, "send_packet: {done}"); + return 0; +} + +/* ------------------- */ +static void dbd_initstamp(struct cnid_dbd_rqst *rqst) +{ + RQST_RESET(rqst); + rqst->op = CNID_DBD_OP_GETSTAMP; +} + +/* ------------------- */ +static int dbd_reply_stamp(struct cnid_dbd_rply *rply) +{ + switch (rply->result) { + case CNID_DBD_RES_OK: + break; + case CNID_DBD_RES_NOTFOUND: + return -1; + case CNID_DBD_RES_ERR_DB: + default: + errno = CNID_ERR_DB; + return -1; + } + return 0; +} + +/* --------------------- + * send a request and get reply + * assume send is non blocking + * if no answer after sometime (at least MAX_DELAY secondes) return an error + */ +static int dbd_rpc(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + ssize_t ret; + char *nametmp; + size_t len; + + if (send_packet(db, rqst) < 0) { + return -1; + } + len = rply->namelen; + nametmp = rply->name; + + ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY); + + if (ret != sizeof(struct cnid_dbd_rply)) { + LOG(log_debug, logtype_cnid, "dbd_rpc: Error reading header from fd (volume %s): %s", + db->vol->v_localname, ret == -1 ? strerror(errno) : "closed"); + rply->name = nametmp; + return -1; + } + rply->name = nametmp; + if (rply->namelen && rply->namelen > len) { + LOG(log_error, logtype_cnid, + "dbd_rpc: Error reading name (volume %s): %s name too long: %d. only wanted %d, garbage?", + db->vol->v_localname, rply->name, rply->namelen, len); + return -1; + } + if (rply->namelen && (ret = readt(db->fd, rply->name, rply->namelen, 0, ONE_DELAY)) != (ssize_t)rply->namelen) { + LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (volume %s): %s", + db->vol->v_localname, ret == -1?strerror(errno):"closed"); + return -1; + } + + LOG(log_maxdebug, logtype_cnid, "dbd_rpc: {done}"); + + return 0; +} + +/* -------------------- */ +static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + time_t orig, t; + int clean = 1; /* no errors so far - to prevent sleep on first try */ + + while (1) { + if (db->fd == -1) { + LOG(log_maxdebug, logtype_cnid, "transmit: connecting to cnid_dbd ..."); + if ((db->fd = init_tsock(db)) < 0) { + goto transmit_fail; + } + if (db->notfirst) { + LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd"); + } else { /* db->notfirst == 0 */ + db->notfirst = 1; + } + LOG(log_debug, logtype_cnid, "transmit: attached to '%s'", db->vol->v_localname); + } + if (!dbd_rpc(db, rqst, rply)) { + LOG(log_maxdebug, logtype_cnid, "transmit: {done}"); + return 0; + } + transmit_fail: + if (db->fd != -1) { + close(db->fd); + db->fd = -1; /* FD not valid... will need to reconnect */ + } + + if (errno == ECONNREFUSED) { /* errno carefully injected in tsock_getfd */ + /* give up */ + LOG(log_error, logtype_cnid, "transmit: connection refused (volume %s)", db->vol->v_localname); + return -1; + } + + if (!clean) { /* don't sleep if just got disconnected by cnid server */ + time(&t); + if (t - orig > MAX_DELAY) { + LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (volume %s) timed out.", db->vol->v_localname); + return -1; + } + /* sleep a little before retry */ + delay(1); + } else { + clean = 0; /* false... next time sleep */ + time(&orig); + } + } + return -1; +} + +/* ---------------------- */ +static struct _cnid_db *cnid_dbd_new(struct vol *vol) +{ + struct _cnid_db *cdb; + + if ((cdb = (struct _cnid_db *)calloc(1, sizeof(struct _cnid_db))) == NULL) + return NULL; + + cdb->cnid_db_vol = vol; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; + cdb->cnid_add = cnid_dbd_add; + cdb->cnid_delete = cnid_dbd_delete; + cdb->cnid_get = cnid_dbd_get; + cdb->cnid_lookup = cnid_dbd_lookup; + cdb->cnid_find = cnid_dbd_find; + cdb->cnid_nextid = NULL; + cdb->cnid_resolve = cnid_dbd_resolve; + cdb->cnid_getstamp = cnid_dbd_getstamp; + cdb->cnid_update = cnid_dbd_update; + cdb->cnid_rebuild_add = cnid_dbd_rebuild_add; + cdb->cnid_close = cnid_dbd_close; + cdb->cnid_wipe = cnid_dbd_wipe; + return cdb; +} + +/* ---------------------- */ +struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args) +{ + CNID_bdb_private *db = NULL; + struct _cnid_db *cdb = NULL; + + if ((cdb = cnid_dbd_new(args->cnid_args_vol)) == NULL) { + LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database"); + return NULL; + } + + if ((db = (CNID_bdb_private *)calloc(1, sizeof(CNID_bdb_private))) == NULL) { + LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database"); + goto cnid_dbd_open_fail; + } + + cdb->cnid_db_private = db; + + db->fd = -1; + db->vol = args->cnid_args_vol; + + LOG(log_debug, logtype_cnid, "Finished initializing CNID dbd module for volume '%s'", + args->cnid_args_vol->v_localname); + + return cdb; + +cnid_dbd_open_fail: + if (cdb != NULL) + free(cdb); + if (db != NULL) + free(db); + + return NULL; +} + +/* ---------------------- */ +void cnid_dbd_close(struct _cnid_db *cdb) +{ + CNID_bdb_private *db; + + if (!cdb) { + LOG(log_error, logtype_cnid, "cnid_close called with NULL argument !"); + return; + } + + if ((db = cdb->cnid_db_private) != NULL) { + LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->vol->v_localname); + + if (db->fd >= 0) + close(db->fd); + free(db); + } + + free(cdb); + + return; +} + +/** + * Get the db stamp + **/ +static int cnid_dbd_stamp(CNID_bdb_private *db) +{ + struct cnid_dbd_rqst rqst_stamp; + struct cnid_dbd_rply rply_stamp; + char stamp[ADEDLEN_PRIVSYN]; + + dbd_initstamp(&rqst_stamp); + memset(stamp, 0, ADEDLEN_PRIVSYN); + rply_stamp.name = stamp; + rply_stamp.namelen = ADEDLEN_PRIVSYN; + + if (transmit(db, &rqst_stamp, &rply_stamp) < 0) + return -1; + if (dbd_reply_stamp(&rply_stamp ) < 0) + return -1; + + if (db->client_stamp) + memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN); + memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN); + + return 0; +} + +/* ---------------------- */ +cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, + cnid_t did, const char *name, size_t len, cnid_t hint) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + cnid_t id; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { + LOG(log_error, logtype_cnid, "cnid_add: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_add: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_ADD; + + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { + rqst.dev = st->st_dev; + } + + rqst.ino = st->st_ino; + rqst.type = S_ISDIR(st->st_mode)?1:0; + rqst.cnid = hint; + rqst.did = did; + rqst.name = name; + rqst.namelen = len; + + LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', dev: 0x%llx, inode: 0x%llx, type: %s", + ntohl(did), name, (long long)rqst.dev, (long long)st->st_ino, rqst.type ? "dir" : "file"); + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + switch(rply.result) { + case CNID_DBD_RES_OK: + id = rply.cnid; + LOG(log_debug, logtype_cnid, "cnid_dbd_add: got CNID: %u", ntohl(id)); + break; + case CNID_DBD_RES_ERR_MAX: + errno = CNID_ERR_MAX; + id = CNID_INVALID; + break; + case CNID_DBD_RES_ERR_DB: + case CNID_DBD_RES_ERR_DUPLCNID: + errno = CNID_ERR_DB; + id = CNID_INVALID; + break; + default: + abort(); + } + + return id; +} + +/* ---------------------- */ +cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + cnid_t id; + + if (!cdb || !(db = cdb->cnid_db_private) || !name) { + LOG(log_error, logtype_cnid, "cnid_dbd_get: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_dbd_get: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + LOG(log_debug, logtype_cnid, "cnid_dbd_get: DID: %u, name: '%s'", ntohl(did), name); + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_GET; + rqst.did = did; + rqst.name = name; + rqst.namelen = len; + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + switch(rply.result) { + case CNID_DBD_RES_OK: + id = rply.cnid; + LOG(log_debug, logtype_cnid, "cnid_dbd_get: got CNID: %u", ntohl(id)); + break; + case CNID_DBD_RES_NOTFOUND: + id = CNID_INVALID; + break; + case CNID_DBD_RES_ERR_DB: + id = CNID_INVALID; + errno = CNID_ERR_DB; + break; + default: + abort(); + } + + return id; +} + +/* ---------------------- */ +char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + char *name; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) { + LOG(log_error, logtype_cnid, "cnid_resolve: Parameter error"); + errno = CNID_ERR_PARAM; + return NULL; + } + + LOG(log_debug, logtype_cnid, "cnid_dbd_resolve: resolving CNID: %u", ntohl(*id)); + + /* TODO: We should maybe also check len. At the moment we rely on the caller + to provide a buffer that is large enough for MAXPATHLEN plus + CNID_HEADER_LEN plus 1 byte, which is large enough for the maximum that + can come from the database. */ + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_RESOLVE; + rqst.cnid = *id; + + /* Pass buffer to transmit so it can stuff the reply data there */ + rply.name = (char *)buffer; + rply.namelen = len; + + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + *id = CNID_INVALID; + return NULL; + } + + switch (rply.result) { + case CNID_DBD_RES_OK: + *id = rply.did; + name = rply.name + CNID_NAME_OFS; + LOG(log_debug, logtype_cnid, "cnid_dbd_resolve: resolved did: %u, name: '%s'", ntohl(*id), name); + break; + case CNID_DBD_RES_NOTFOUND: + *id = CNID_INVALID; + name = NULL; + break; + case CNID_DBD_RES_ERR_DB: + errno = CNID_ERR_DB; + *id = CNID_INVALID; + name = NULL; + break; + default: + abort(); + } + + return name; +} + +/** + * Caller passes buffer where we will store the db stamp + **/ +int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) +{ + CNID_bdb_private *db; + + if (!cdb || !(db = cdb->cnid_db_private) || len != ADEDLEN_PRIVSYN) { + LOG(log_error, logtype_cnid, "cnid_getstamp: Parameter error"); + errno = CNID_ERR_PARAM; + return -1; + } + db->client_stamp = buffer; + db->stamp_size = len; + + return cnid_dbd_stamp(db); +} + +/* ---------------------- */ +cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, + const char *name, size_t len) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + cnid_t id; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { + LOG(log_error, logtype_cnid, "cnid_lookup: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_lookup: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_LOOKUP; + + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { + rqst.dev = st->st_dev; + } + + rqst.ino = st->st_ino; + rqst.type = S_ISDIR(st->st_mode)?1:0; + rqst.did = did; + rqst.name = name; + rqst.namelen = len; + + LOG(log_debug, logtype_cnid, "cnid_dbd_lookup: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)", + ntohl(did), name, (long long)st->st_ino, rqst.type); + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + switch (rply.result) { + case CNID_DBD_RES_OK: + id = rply.cnid; + LOG(log_debug, logtype_cnid, "cnid_dbd_lookup: got CNID: %u", ntohl(id)); + break; + case CNID_DBD_RES_NOTFOUND: + id = CNID_INVALID; + break; + case CNID_DBD_RES_ERR_DB: + errno = CNID_ERR_DB; + id = CNID_INVALID; + break; + default: + abort(); + } + + return id; +} + +/* ---------------------- */ +int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + int count; + + if (!cdb || !(db = cdb->cnid_db_private) || !name) { + LOG(log_error, logtype_cnid, "cnid_find: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (namelen > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_find: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + LOG(log_debug, logtype_cnid, "cnid_find(\"%s\")", name); + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_SEARCH; + + rqst.name = name; + rqst.namelen = namelen; + + rply.name = buffer; + rply.namelen = buflen; + + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + switch (rply.result) { + case CNID_DBD_RES_OK: + count = rply.namelen / sizeof(cnid_t); + LOG(log_debug, logtype_cnid, "cnid_find: got %d matches", count); + break; + case CNID_DBD_RES_NOTFOUND: + count = 0; + break; + case CNID_DBD_RES_ERR_DB: + errno = CNID_ERR_DB; + count = -1; + break; + default: + abort(); + } + + return count; +} + +/* ---------------------- */ +int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, + cnid_t did, const char *name, size_t len) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name) { + LOG(log_error, logtype_cnid, "cnid_update: Parameter error"); + errno = CNID_ERR_PARAM; + return -1; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_update: Path name is too long"); + errno = CNID_ERR_PATH; + return -1; + } + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_UPDATE; + rqst.cnid = id; + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { + rqst.dev = st->st_dev; + } + rqst.ino = st->st_ino; + rqst.type = S_ISDIR(st->st_mode)?1:0; + rqst.did = did; + rqst.name = name; + rqst.namelen = len; + + LOG(log_debug, logtype_cnid, "cnid_dbd_update: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)", + ntohl(id), name, (long long)st->st_ino, rqst.type); + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return -1; + } + + switch (rply.result) { + case CNID_DBD_RES_OK: + LOG(log_debug, logtype_cnid, "cnid_dbd_update: updated"); + case CNID_DBD_RES_NOTFOUND: + return 0; + case CNID_DBD_RES_ERR_DB: + errno = CNID_ERR_DB; + return -1; + default: + abort(); + } +} + +/* ---------------------- */ +cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, + cnid_t did, const char *name, size_t len, cnid_t hint) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + cnid_t id; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name || hint == CNID_INVALID) { + LOG(log_error, logtype_cnid, "cnid_rebuild_add: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_rebuild_add: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_REBUILD_ADD; + + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { + rqst.dev = st->st_dev; + } + + rqst.ino = st->st_ino; + rqst.type = S_ISDIR(st->st_mode)?1:0; + rqst.did = did; + rqst.name = name; + rqst.namelen = len; + rqst.cnid = hint; + + LOG(log_debug, logtype_cnid, "cnid_dbd_rebuild_add: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir), hint: %u", + ntohl(did), name, (long long)st->st_ino, rqst.type, hint); + + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + switch(rply.result) { + case CNID_DBD_RES_OK: + id = rply.cnid; + LOG(log_debug, logtype_cnid, "cnid_dbd_rebuild_add: got CNID: %u", ntohl(id)); + break; + case CNID_DBD_RES_ERR_MAX: + errno = CNID_ERR_MAX; + id = CNID_INVALID; + break; + case CNID_DBD_RES_ERR_DB: + case CNID_DBD_RES_ERR_DUPLCNID: + errno = CNID_ERR_DB; + id = CNID_INVALID; + break; + default: + abort(); + } + return id; +} + +/* ---------------------- */ +int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + + if (!cdb || !(db = cdb->cnid_db_private) || !id) { + LOG(log_error, logtype_cnid, "cnid_delete: Parameter error"); + errno = CNID_ERR_PARAM; + return -1; + } + + LOG(log_debug, logtype_cnid, "cnid_dbd_delete: delete CNID: %u", ntohl(id)); + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_DELETE; + rqst.cnid = id; + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return -1; + } + + switch (rply.result) { + case CNID_DBD_RES_OK: + LOG(log_debug, logtype_cnid, "cnid_dbd_delete: deleted CNID: %u", ntohl(id)); + case CNID_DBD_RES_NOTFOUND: + return 0; + case CNID_DBD_RES_ERR_DB: + errno = CNID_ERR_DB; + return -1; + default: + abort(); + } +} + +int cnid_dbd_wipe(struct _cnid_db *cdb) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + + if (!cdb || !(db = cdb->cnid_db_private)) { + LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error"); + errno = CNID_ERR_PARAM; + return -1; + } + + LOG(log_debug, logtype_cnid, "cnid_dbd_wipe"); + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_WIPE; + rqst.cnid = 0; + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return -1; + } + + if (rply.result != CNID_DBD_RES_OK) { + errno = CNID_ERR_DB; + return -1; + } + LOG(log_debug, logtype_cnid, "cnid_dbd_wipe: ok"); + + return cnid_dbd_stamp(db); +} + + +struct _cnid_module cnid_dbd_module = { + "dbd", + {NULL, NULL}, + cnid_dbd_open, + 0 +}; + +#endif /* CNID_DBD */ + diff --git a/libatalk/cnid/dbd/cnid_dbd.h b/libatalk/cnid/dbd/cnid_dbd.h new file mode 100644 index 0000000..69ff5a6 --- /dev/null +++ b/libatalk/cnid/dbd/cnid_dbd.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 + * All Rights Reserved. See COPYING. + */ + + +#ifndef _ATALK_CNID_DBD__H +#define _ATALK_CNID_DBD__H 1 + +#include +#include +#include +#include + +#include + +extern struct _cnid_module cnid_dbd_module; +extern struct _cnid_db *cnid_dbd_open (struct cnid_open_args *args); +extern void cnid_dbd_close (struct _cnid_db *); +extern cnid_t cnid_dbd_add (struct _cnid_db *, const struct stat *, cnid_t, + const char *, size_t, cnid_t); +extern cnid_t cnid_dbd_get (struct _cnid_db *, cnid_t, const char *, size_t); +extern char *cnid_dbd_resolve (struct _cnid_db *, cnid_t *, void *, size_t ); +extern int cnid_dbd_getstamp (struct _cnid_db *, void *, const size_t ); +extern cnid_t cnid_dbd_lookup (struct _cnid_db *, const struct stat *, cnid_t, + const char *, size_t); +extern int cnid_dbd_find (struct _cnid_db *cdb, const char *name, size_t namelen, + void *buffer, size_t buflen); +extern int cnid_dbd_update (struct _cnid_db *, cnid_t, const struct stat *, + cnid_t, const char *, size_t); +extern int cnid_dbd_delete (struct _cnid_db *, const cnid_t); +extern cnid_t cnid_dbd_rebuild_add(struct _cnid_db *, const struct stat *, + cnid_t, const char *, size_t, cnid_t); +extern int cnid_dbd_wipe (struct _cnid_db *cdb); +/* FIXME: These functions could be static in cnid_dbd.c */ + +#endif /* include/atalk/cnid_dbd.h */ + diff --git a/libatalk/cnid/last/Makefile.am b/libatalk/cnid/last/Makefile.am new file mode 100644 index 0000000..0d487b5 --- /dev/null +++ b/libatalk/cnid/last/Makefile.am @@ -0,0 +1,10 @@ +# Makefile.am for libatalk/cnid/ + +if USE_LAST_BACKEND +noinst_LTLIBRARIES = libcnid_last.la +endif + +libcnid_last_la_SOURCES = cnid_last.c \ + cnid_last.h + +EXTRA_DIST = README diff --git a/libatalk/cnid/last/Makefile.in b/libatalk/cnid/last/Makefile.in new file mode 100644 index 0000000..5e7f207 --- /dev/null +++ b/libatalk/cnid/last/Makefile.in @@ -0,0 +1,665 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/cnid/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/cnid/last +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcnid_last_la_LIBADD = +am_libcnid_last_la_OBJECTS = cnid_last.lo +libcnid_last_la_OBJECTS = $(am_libcnid_last_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +@USE_LAST_BACKEND_TRUE@am_libcnid_last_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcnid_last_la_SOURCES) +DIST_SOURCES = $(libcnid_last_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_LAST_BACKEND_TRUE@noinst_LTLIBRARIES = libcnid_last.la +libcnid_last_la_SOURCES = cnid_last.c \ + cnid_last.h + +EXTRA_DIST = README +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/cnid/last/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/cnid/last/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcnid_last.la: $(libcnid_last_la_OBJECTS) $(libcnid_last_la_DEPENDENCIES) $(EXTRA_libcnid_last_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(am_libcnid_last_la_rpath) $(libcnid_last_la_OBJECTS) $(libcnid_last_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cnid_last.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/cnid/last/README b/libatalk/cnid/last/README new file mode 100644 index 0000000..3fe80f6 --- /dev/null +++ b/libatalk/cnid/last/README @@ -0,0 +1,4 @@ +This is [last] DID scheme implementation. + +TODO: this scheme doesn't exactly mimic real, persistent CNID schemes, so + things like name mangling won't work. diff --git a/libatalk/cnid/last/cnid_last.c b/libatalk/cnid/last/cnid_last.c new file mode 100644 index 0000000..2314217 --- /dev/null +++ b/libatalk/cnid/last/cnid_last.c @@ -0,0 +1,173 @@ + +/* + * + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef CNID_BACKEND_LAST +#include +#include "cnid_last.h" +#include +#include + +#include +#include +#include +#include + +/* ------------------------ */ +cnid_t cnid_last_add(struct _cnid_db *cdb, const struct stat *st, + cnid_t did _U_, const char *name _U_, size_t len _U_, cnid_t hint _U_) +{ + + /* FIXME: it relies on fact, that this is never called twice for the same file/dir. */ + /* Propably we should look through DID tree. */ + + /* + * First thing: DID and FNUMs are + * in the same space for purposes of enumerate (and several + * other wierd places). While we consider this Apple's bug, + * this is the work-around: In order to maintain constant and + * unique DIDs and FNUMs, we monotonically generate the DIDs + * during the session, and derive the FNUMs from the filesystem. + * Since the DIDs are small, we insure that the FNUMs are fairly + * large by setting thier high bits to the device number. + * + * AFS already does something very similar to this for the + * inode number, so we don't repeat the procedure. + * + * new algorithm: + * due to complaints over did's being non-persistent, + * here's the current hack to provide semi-persistent + * did's: + * 1) we reserve the first bit for file ids. + * 2) the next 7 bits are for the device. + * 3) the remaining 24 bits are for the inode. + * + * both the inode and device information are actually hashes + * that are then truncated to the requisite bit length. + * + * it should be okay to use lstat to deal with symlinks. + */ + + struct _cnid_last_private *priv; + + if (!cdb || !(cdb->cnid_db_private)) + return CNID_INVALID; + + priv = (struct _cnid_last_private *) (cdb->cnid_db_private); + + if (S_ISDIR(st->st_mode)) + return htonl(priv->last_did++); + else + return htonl((st->st_dev << 16) | (st->st_ino & 0x0000ffff)); +} + + + +void cnid_last_close(struct _cnid_db *cdb) +{ + free(cdb->cnid_db_private); + free(cdb); +} + + + +int cnid_last_delete(struct _cnid_db *cdb _U_, const cnid_t id _U_) +{ + return CNID_INVALID; +} + + +/* Return CNID for a given did/name. */ +cnid_t cnid_last_get(struct _cnid_db *cdb _U_, cnid_t did _U_, const char *name _U_, size_t len _U_) +{ + /* FIXME: it relies on fact, that this is never called twice for the same file/dir. */ + /* Propably we should look through DID tree. */ + return CNID_INVALID; +} + + +/* */ +cnid_t cnid_last_lookup(struct _cnid_db *cdb _U_, const struct stat *st _U_, cnid_t did _U_, + const char *name _U_, size_t len _U_) +{ + /* FIXME: this function doesn't work in [last] scheme ! */ + /* Should be never called or CNID should be somewhat refactored again. */ + return CNID_INVALID; +} + + +static struct _cnid_db *cnid_last_new(struct vol *vol) +{ + struct _cnid_db *cdb; + struct _cnid_last_private *priv; + + if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL) + return NULL; + + if ((cdb->cnid_db_private = calloc(1, sizeof(struct _cnid_last_private))) == NULL) { + free(cdb); + return NULL; + } + + /* Set up private state */ + priv = (struct _cnid_last_private *) (cdb->cnid_db_private); + priv->last_did = 17; + + /* Set up standard fields */ + cdb->cnid_db_flags = 0; + cdb->cnid_add = cnid_last_add; + cdb->cnid_delete = cnid_last_delete; + cdb->cnid_get = cnid_last_get; + cdb->cnid_lookup = cnid_last_lookup; + cdb->cnid_nextid = NULL; /* cnid_last_nextid; */ + cdb->cnid_resolve = cnid_last_resolve; + cdb->cnid_update = cnid_last_update; + cdb->cnid_close = cnid_last_close; + cdb->cnid_wipe = NULL; + + return cdb; +} + +struct _cnid_db *cnid_last_open(struct cnid_open_args *args) +{ + struct _cnid_db *cdb; + + if ((cdb = cnid_last_new(args->cnid_args_vol)) == NULL) { + LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database"); + return NULL; + } + + return cdb; +} + +struct _cnid_module cnid_last_module = { + "last", + {NULL, NULL}, + cnid_last_open, + 0 +}; + +/* Return the did/name pair corresponding to a CNID. */ +char *cnid_last_resolve(struct _cnid_db *cdb _U_, cnid_t * id _U_, void *buffer _U_, size_t len _U_) +{ + /* FIXME: frankly, it does not work. As get, add and other functions. */ + return NULL; +} + + +int cnid_last_update(struct _cnid_db *cdb _U_, cnid_t id _U_, const struct stat *st _U_, + cnid_t did _U_, const char *name _U_, size_t len _U_) +{ + return 0; +} + + +#endif /* CNID_BACKEND_LAST */ diff --git a/libatalk/cnid/last/cnid_last.h b/libatalk/cnid/last/cnid_last.h new file mode 100644 index 0000000..7fce6e7 --- /dev/null +++ b/libatalk/cnid/last/cnid_last.h @@ -0,0 +1,31 @@ +/* + * interface for database access to cnids. i do it this way to abstract + * things a bit in case we want to change the underlying implementation. + */ + +#ifndef _ATALK_CNID_LAST__H +#define _ATALK_CNID_LAST__H 1 + +#include +#include +#include + +#include + +struct _cnid_last_private { + cnid_t last_did; +}; + +extern struct _cnid_module cnid_last_module; +extern struct _cnid_db *cnid_last_open (struct cnid_open_args *args); +extern void cnid_last_close (struct _cnid_db *); +extern cnid_t cnid_last_add (struct _cnid_db *, const struct stat *, cnid_t, + const char *, size_t, cnid_t); +extern cnid_t cnid_last_get (struct _cnid_db *, cnid_t, const char *, size_t); +extern char *cnid_last_resolve (struct _cnid_db *, cnid_t *, void *, size_t); +extern cnid_t cnid_last_lookup (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t); +extern int cnid_last_update (struct _cnid_db *, cnid_t, const struct stat *, + cnid_t, const char *, size_t); +extern int cnid_last_delete (struct _cnid_db *, cnid_t); + +#endif /* include/atalk/cnid_last.h */ diff --git a/libatalk/cnid/mysql/Makefile.am b/libatalk/cnid/mysql/Makefile.am new file mode 100644 index 0000000..df688b2 --- /dev/null +++ b/libatalk/cnid/mysql/Makefile.am @@ -0,0 +1,6 @@ +# Makefile.am for libatalk/cnid/mysql/ + +noinst_LTLIBRARIES = libcnid_mysql.la +libcnid_mysql_la_SOURCES = cnid_mysql.c +libcnid_mysql_la_CFLAGS = @MYSQL_CFLAGS@ +libcnid_mysql_la_LIBADD = @MYSQL_LIBS@ diff --git a/libatalk/cnid/mysql/Makefile.in b/libatalk/cnid/mysql/Makefile.in new file mode 100644 index 0000000..84cfb24 --- /dev/null +++ b/libatalk/cnid/mysql/Makefile.in @@ -0,0 +1,674 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/cnid/mysql/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/cnid/mysql +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcnid_mysql_la_DEPENDENCIES = +am_libcnid_mysql_la_OBJECTS = libcnid_mysql_la-cnid_mysql.lo +libcnid_mysql_la_OBJECTS = $(am_libcnid_mysql_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libcnid_mysql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libcnid_mysql_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcnid_mysql_la_SOURCES) +DIST_SOURCES = $(libcnid_mysql_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libcnid_mysql.la +libcnid_mysql_la_SOURCES = cnid_mysql.c +libcnid_mysql_la_CFLAGS = @MYSQL_CFLAGS@ +libcnid_mysql_la_LIBADD = @MYSQL_LIBS@ +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/cnid/mysql/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/cnid/mysql/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcnid_mysql.la: $(libcnid_mysql_la_OBJECTS) $(libcnid_mysql_la_DEPENDENCIES) $(EXTRA_libcnid_mysql_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcnid_mysql_la_LINK) $(libcnid_mysql_la_OBJECTS) $(libcnid_mysql_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_mysql_la-cnid_mysql.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libcnid_mysql_la-cnid_mysql.lo: cnid_mysql.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_mysql_la_CFLAGS) $(CFLAGS) -MT libcnid_mysql_la-cnid_mysql.lo -MD -MP -MF $(DEPDIR)/libcnid_mysql_la-cnid_mysql.Tpo -c -o libcnid_mysql_la-cnid_mysql.lo `test -f 'cnid_mysql.c' || echo '$(srcdir)/'`cnid_mysql.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_mysql_la-cnid_mysql.Tpo $(DEPDIR)/libcnid_mysql_la-cnid_mysql.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_mysql.c' object='libcnid_mysql_la-cnid_mysql.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_mysql_la_CFLAGS) $(CFLAGS) -c -o libcnid_mysql_la-cnid_mysql.lo `test -f 'cnid_mysql.c' || echo '$(srcdir)/'`cnid_mysql.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/cnid/mysql/cnid_mysql.c b/libatalk/cnid/mysql/cnid_mysql.c new file mode 100644 index 0000000..063d79f --- /dev/null +++ b/libatalk/cnid/mysql/cnid_mysql.c @@ -0,0 +1,954 @@ +/* + * Copyright (C) Ralph Boehme 2013 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#undef _FORTIFY_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +static MYSQL_BIND lookup_param[4], lookup_result[5]; +static MYSQL_BIND add_param[4], put_param[5]; + +/* + * Prepared statement parameters + */ +static char stmt_param_name[MAXPATHLEN]; +static unsigned long stmt_param_name_len; +static unsigned long long stmt_param_id; +static unsigned long long stmt_param_did; +static unsigned long long stmt_param_dev; +static unsigned long long stmt_param_ino; + +/* + * lookup result parameters + */ +static unsigned long long lookup_result_id; +static unsigned long long lookup_result_did; +static char lookup_result_name[MAXPATHLEN]; +static unsigned long lookup_result_name_len; +static unsigned long long lookup_result_dev; +static unsigned long long lookup_result_ino; + +static int init_prepared_stmt_lookup(CNID_mysql_private *db) +{ + EC_INIT; + char *sql = NULL; + + lookup_param[0].buffer_type = MYSQL_TYPE_STRING; + lookup_param[0].buffer = &stmt_param_name; + lookup_param[0].buffer_length = sizeof(stmt_param_name); + lookup_param[0].length = &stmt_param_name_len; + + lookup_param[1].buffer_type = MYSQL_TYPE_LONGLONG; + lookup_param[1].buffer = &stmt_param_did; + lookup_param[1].is_unsigned = true; + + lookup_param[2].buffer_type = MYSQL_TYPE_LONGLONG; + lookup_param[2].buffer = &stmt_param_dev; + lookup_param[2].is_unsigned = true; + + lookup_param[3].buffer_type = MYSQL_TYPE_LONGLONG; + lookup_param[3].buffer = &stmt_param_ino; + lookup_param[3].is_unsigned = true; + + lookup_result[0].buffer_type = MYSQL_TYPE_LONGLONG; + lookup_result[0].buffer = &lookup_result_id; + lookup_result[0].is_unsigned = true; + + lookup_result[1].buffer_type = MYSQL_TYPE_LONGLONG; + lookup_result[1].buffer = &lookup_result_did; + lookup_result[1].is_unsigned = true; + + lookup_result[2].buffer_type = MYSQL_TYPE_STRING; + lookup_result[2].buffer = &lookup_result_name; + lookup_result[2].buffer_length = sizeof(lookup_result_name); + lookup_result[2].length = &lookup_result_name_len; + + lookup_result[3].buffer_type = MYSQL_TYPE_LONGLONG; + lookup_result[3].buffer = &lookup_result_dev; + lookup_result[3].is_unsigned = true; + + lookup_result[4].buffer_type = MYSQL_TYPE_LONGLONG; + lookup_result[4].buffer = &lookup_result_ino; + lookup_result[4].is_unsigned = true; + + EC_NULL( db->cnid_lookup_stmt = mysql_stmt_init(db->cnid_mysql_con) ); + EC_NEG1( asprintf(&sql, + "SELECT Id,Did,Name,DevNo,InodeNo FROM %s " + "WHERE (Name=? AND Did=?) OR (DevNo=? AND InodeNo=?)", + db->cnid_mysql_voluuid_str) ); + EC_ZERO_LOG( mysql_stmt_prepare(db->cnid_lookup_stmt, sql, strlen(sql)) ); + EC_ZERO_LOG( mysql_stmt_bind_param(db->cnid_lookup_stmt, lookup_param) ); + +EC_CLEANUP: + if (sql) + free(sql); + EC_EXIT; +} + +static int init_prepared_stmt_add(CNID_mysql_private *db) +{ + EC_INIT; + char *sql = NULL; + + EC_NULL( db->cnid_add_stmt = mysql_stmt_init(db->cnid_mysql_con) ); + EC_NEG1( asprintf(&sql, + "INSERT INTO %s (Name,Did,DevNo,InodeNo) VALUES(?,?,?,?)", + db->cnid_mysql_voluuid_str) ); + + add_param[0].buffer_type = MYSQL_TYPE_STRING; + add_param[0].buffer = &stmt_param_name; + add_param[0].buffer_length = sizeof(stmt_param_name); + add_param[0].length = &stmt_param_name_len; + + add_param[1].buffer_type = MYSQL_TYPE_LONGLONG; + add_param[1].buffer = &stmt_param_did; + add_param[1].is_unsigned = true; + + add_param[2].buffer_type = MYSQL_TYPE_LONGLONG; + add_param[2].buffer = &stmt_param_dev; + add_param[2].is_unsigned = true; + + add_param[3].buffer_type = MYSQL_TYPE_LONGLONG; + add_param[3].buffer = &stmt_param_ino; + add_param[3].is_unsigned = true; + + EC_ZERO_LOG( mysql_stmt_prepare(db->cnid_add_stmt, sql, strlen(sql)) ); + EC_ZERO_LOG( mysql_stmt_bind_param(db->cnid_add_stmt, add_param) ); + +EC_CLEANUP: + if (sql) + free(sql); + EC_EXIT; +} + +static int init_prepared_stmt_put(CNID_mysql_private *db) +{ + EC_INIT; + char *sql = NULL; + + EC_NULL( db->cnid_put_stmt = mysql_stmt_init(db->cnid_mysql_con) ); + EC_NEG1( asprintf(&sql, + "INSERT INTO %s (Id,Name,Did,DevNo,InodeNo) VALUES(?,?,?,?,?)", + db->cnid_mysql_voluuid_str) ); + + put_param[0].buffer_type = MYSQL_TYPE_LONGLONG; + put_param[0].buffer = &stmt_param_id; + put_param[0].is_unsigned = true; + + put_param[1].buffer_type = MYSQL_TYPE_STRING; + put_param[1].buffer = &stmt_param_name; + put_param[1].buffer_length = sizeof(stmt_param_name); + put_param[1].length = &stmt_param_name_len; + + put_param[2].buffer_type = MYSQL_TYPE_LONGLONG; + put_param[2].buffer = &stmt_param_did; + put_param[2].is_unsigned = true; + + put_param[3].buffer_type = MYSQL_TYPE_LONGLONG; + put_param[3].buffer = &stmt_param_dev; + put_param[3].is_unsigned = true; + + put_param[4].buffer_type = MYSQL_TYPE_LONGLONG; + put_param[4].buffer = &stmt_param_ino; + put_param[4].is_unsigned = true; + + EC_ZERO_LOG( mysql_stmt_prepare(db->cnid_put_stmt, sql, strlen(sql)) ); + EC_ZERO_LOG( mysql_stmt_bind_param(db->cnid_put_stmt, put_param) ); + +EC_CLEANUP: + if (sql) + free(sql); + EC_EXIT; +} + +static int init_prepared_stmt(CNID_mysql_private *db) +{ + EC_INIT; + + EC_ZERO( init_prepared_stmt_lookup(db) ); + EC_ZERO( init_prepared_stmt_add(db) ); + EC_ZERO( init_prepared_stmt_put(db) ); + +EC_CLEANUP: + EC_EXIT; +} + +static void close_prepared_stmt(CNID_mysql_private *db) +{ + mysql_stmt_close(db->cnid_lookup_stmt); + mysql_stmt_close(db->cnid_add_stmt); + mysql_stmt_close(db->cnid_put_stmt); +} + +static int cnid_mysql_execute(MYSQL *con, char *fmt, ...) +{ + char *sql = NULL; + va_list ap; + int rv; + + va_start(ap, fmt); + if (vasprintf(&sql, fmt, ap) == -1) + return -1; + va_end(ap); + + LOG(log_maxdebug, logtype_cnid, "SQL: %s", sql); + + rv = mysql_query(con, sql); + + if (rv) { + LOG(log_info, logtype_cnid, "MySQL query \"%s\", error: %s", sql, mysql_error(con)); + errno = CNID_ERR_DB; + } + free(sql); + return rv; +} + +int cnid_mysql_delete(struct _cnid_db *cdb, const cnid_t id) +{ + EC_INIT; + CNID_mysql_private *db; + + if (!cdb || !(db = cdb->cnid_db_private) || !id) { + LOG(log_error, logtype_cnid, "cnid_mysql_delete: Parameter error"); + errno = CNID_ERR_PARAM; + EC_FAIL; + } + + LOG(log_debug, logtype_cnid, "cnid_mysql_delete(%" PRIu32 "): BEGIN", ntohl(id)); + + EC_NEG1( cnid_mysql_execute(db->cnid_mysql_con, + "DELETE FROM %s WHERE Id=%" PRIu32, + db->cnid_mysql_voluuid_str, + ntohl(id)) ); + + LOG(log_debug, logtype_cnid, "cnid_mysql_delete(%" PRIu32 "): END", ntohl(id)); + +EC_CLEANUP: + EC_EXIT; +} + +void cnid_mysql_close(struct _cnid_db *cdb) +{ + CNID_mysql_private *db; + + if (!cdb) { + LOG(log_error, logtype_cnid, "cnid_close called with NULL argument !"); + return; + } + + if ((db = cdb->cnid_db_private) != NULL) { + LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", + cdb->cnid_db_vol->v_localname); + + free(db->cnid_mysql_voluuid_str); + + close_prepared_stmt(db); + + if (db->cnid_mysql_con) + mysql_close(db->cnid_mysql_con); + free(db); + } + + free(cdb); + + return; +} + +int cnid_mysql_update(struct _cnid_db *cdb, + cnid_t id, + const struct stat *st, + cnid_t did, + const char *name, + size_t len) +{ + EC_INIT; + CNID_mysql_private *db; + cnid_t update_id; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name) { + LOG(log_error, logtype_cnid, "cnid_update: Parameter error"); + errno = CNID_ERR_PARAM; + EC_FAIL; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_update: Path name is too long"); + errno = CNID_ERR_PATH; + EC_FAIL; + } + + uint64_t dev = st->st_dev; + uint64_t ino = st->st_ino; + + do { + EC_NEG1( cnid_mysql_execute(db->cnid_mysql_con, + "DELETE FROM %s WHERE Id=%" PRIu32, + db->cnid_mysql_voluuid_str, + ntohl(id)) ); + EC_NEG1( cnid_mysql_execute(db->cnid_mysql_con, + "DELETE FROM %s WHERE Did=%" PRIu32 " AND Name='%s'", + db->cnid_mysql_voluuid_str, ntohl(did), name) ); + EC_NEG1( cnid_mysql_execute(db->cnid_mysql_con, + "DELETE FROM %s WHERE DevNo=%" PRIu64 " AND InodeNo=%" PRIu64, + db->cnid_mysql_voluuid_str, dev, ino) ); + + stmt_param_id = ntohl(id); + strncpy(stmt_param_name, name, sizeof(stmt_param_name)); + stmt_param_name_len = len; + stmt_param_did = ntohl(did); + stmt_param_dev = dev; + stmt_param_ino = ino; + + if (mysql_stmt_execute(db->cnid_put_stmt)) { + switch (mysql_stmt_errno(db->cnid_put_stmt)) { + case ER_DUP_ENTRY: + /* + * Race condition: + * between deletion and insert another process may have inserted + * this entry. + */ + continue; + case CR_SERVER_LOST: + close_prepared_stmt(db); + EC_ZERO( init_prepared_stmt(db) ); + continue; + default: + EC_FAIL; + } + } + update_id = mysql_stmt_insert_id(db->cnid_put_stmt); + } while (update_id != ntohl(id)); + +EC_CLEANUP: + EC_EXIT; +} + +cnid_t cnid_mysql_lookup(struct _cnid_db *cdb, + const struct stat *st, + cnid_t did, + const char *name, + size_t len) +{ + EC_INIT; + CNID_mysql_private *db; + cnid_t id = CNID_INVALID; + bool have_result = false; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { + LOG(log_error, logtype_cnid, "cnid_mysql_lookup: Parameter error"); + errno = CNID_ERR_PARAM; + EC_FAIL; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_mysql_lookup: Path name is too long"); + errno = CNID_ERR_PATH; + EC_FAIL; + } + + uint64_t dev = st->st_dev; + uint64_t ino = st->st_ino; + cnid_t hint = db->cnid_mysql_hint; + + LOG(log_maxdebug, logtype_cnid, "cnid_mysql_lookup(did: %" PRIu32 ", name: \"%s\", hint: %" PRIu32 "): START", + ntohl(did), name, ntohl(hint)); + + strncpy(stmt_param_name, name, sizeof(stmt_param_name)); + stmt_param_name_len = len; + stmt_param_did = ntohl(did); + stmt_param_dev = dev; + stmt_param_ino = ino; + +exec_stmt: + if (mysql_stmt_execute(db->cnid_lookup_stmt)) { + switch (mysql_stmt_errno(db->cnid_lookup_stmt)) { + case CR_SERVER_LOST: + close_prepared_stmt(db); + EC_ZERO( init_prepared_stmt(db) ); + goto exec_stmt; + default: + EC_FAIL; + } + } + EC_ZERO_LOG( mysql_stmt_store_result(db->cnid_lookup_stmt) ); + have_result = true; + EC_ZERO_LOG( mysql_stmt_bind_result(db->cnid_lookup_stmt, lookup_result) ); + + uint64_t retdev, retino; + cnid_t retid, retdid; + char *retname; + + switch (mysql_stmt_num_rows(db->cnid_lookup_stmt)) { + + case 0: + /* not found */ + LOG(log_debug, logtype_cnid, "cnid_mysql_lookup: name: '%s', did: %u is not in the CNID database", + name, ntohl(did)); + errno = CNID_DBD_RES_NOTFOUND; + EC_FAIL; + + case 1: + /* either both OR clauses matched the same id or only one matched, handled below */ + EC_ZERO( mysql_stmt_fetch(db->cnid_lookup_stmt) ); + break; + + case 2: + /* a mismatch, delete both and return not found */ + while (mysql_stmt_fetch(db->cnid_lookup_stmt) == 0) { + if (cnid_mysql_delete(cdb, htonl((cnid_t)lookup_result_id))) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + errno = CNID_ERR_DB; + EC_FAIL; + } + } + errno = CNID_DBD_RES_NOTFOUND; + EC_FAIL; + + default: + errno = CNID_ERR_DB; + EC_FAIL; + } + + retid = htonl(lookup_result_id); + retdid = htonl(lookup_result_did); + retname = lookup_result_name; + retdev = lookup_result_dev; + retino = lookup_result_ino; + + if (retdid != did || STRCMP(retname, !=, name)) { + LOG(log_debug, logtype_cnid, + "cnid_mysql_lookup(CNID hint: %" PRIu32 ", DID: %" PRIu32 ", name: \"%s\"): server side mv oder reused inode", + ntohl(hint), ntohl(did), name); + if (hint != retid) { + if (cnid_mysql_delete(cdb, retid) != 0) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + errno = CNID_ERR_DB; + EC_FAIL; + } + errno = CNID_DBD_RES_NOTFOUND; + EC_FAIL; + } + LOG(log_debug, logtype_cnid, "cnid_mysql_lookup: server side mv, got hint, updating"); + if (cnid_mysql_update(cdb, retid, st, did, name, len) != 0) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + errno = CNID_ERR_DB; + EC_FAIL; + } + id = retid; + } else if (retdev != dev || retino != ino) { + LOG(log_debug, logtype_cnid, "cnid_mysql_lookup(DID:%u, name: \"%s\"): changed dev/ino", + ntohl(did), name); + if (cnid_mysql_delete(cdb, retid) != 0) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + errno = CNID_ERR_DB; + EC_FAIL; + } + errno = CNID_DBD_RES_NOTFOUND; + EC_FAIL; + } else { + /* everythings good */ + id = retid; + } + +EC_CLEANUP: + LOG(log_debug, logtype_cnid, "cnid_mysql_lookup: id: %" PRIu32, ntohl(id)); + if (have_result) + mysql_stmt_free_result(db->cnid_lookup_stmt); + if (ret != 0) + id = CNID_INVALID; + return id; +} + +cnid_t cnid_mysql_add(struct _cnid_db *cdb, + const struct stat *st, + cnid_t did, + const char *name, + size_t len, + cnid_t hint) +{ + EC_INIT; + CNID_mysql_private *db; + cnid_t id = CNID_INVALID; + MYSQL_RES *result = NULL; + MYSQL_STMT *stmt; + my_ulonglong lastid; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { + LOG(log_error, logtype_cnid, "cnid_mysql_add: Parameter error"); + errno = CNID_ERR_PARAM; + EC_FAIL; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_mysql_add: Path name is too long"); + errno = CNID_ERR_PATH; + EC_FAIL; + } + + uint64_t dev = st->st_dev; + uint64_t ino = st->st_ino; + db->cnid_mysql_hint = hint; + + LOG(log_maxdebug, logtype_cnid, "cnid_mysql_add(did: %" PRIu32 ", name: \"%s\", hint: %" PRIu32 "): START", + ntohl(did), name, ntohl(hint)); + + do { + if ((id = cnid_mysql_lookup(cdb, st, did, name, len)) == CNID_INVALID) { + if (errno == CNID_ERR_DB) + EC_FAIL; + /* + * If the CNID set overflowed before (CNID_MYSQL_FLAG_DEPLETED) + * ignore the CNID "hint" taken from the AppleDouble file + */ + if (!db->cnid_mysql_hint || (db->cnid_mysql_flags & CNID_MYSQL_FLAG_DEPLETED)) { + stmt = db->cnid_add_stmt; + } else { + stmt = db->cnid_put_stmt; + stmt_param_id = ntohl(db->cnid_mysql_hint); + } + strncpy(stmt_param_name, name, sizeof(stmt_param_name)); + stmt_param_name_len = len; + stmt_param_did = ntohl(did); + stmt_param_dev = dev; + stmt_param_ino = ino; + + if (mysql_stmt_execute(stmt)) { + switch (mysql_stmt_errno(stmt)) { + case ER_DUP_ENTRY: + break; + case CR_SERVER_LOST: + close_prepared_stmt(db); + EC_ZERO( init_prepared_stmt(db) ); + continue; + default: + EC_FAIL; + } + /* + * Race condition: + * between lookup and insert another process may have inserted + * this entry. + */ + if (db->cnid_mysql_hint) + db->cnid_mysql_hint = CNID_INVALID; + continue; + } + + lastid = mysql_stmt_insert_id(stmt); + + if (lastid > 0xffffffff) { + /* CNID set ist depleted, restart from scratch */ + EC_NEG1( cnid_mysql_execute(db->cnid_mysql_con, + "START TRANSACTION;" + "UPDATE volumes SET Depleted=1 WHERE VolUUID='%s';" + "TRUNCATE TABLE %s;" + "ALTER TABLE %s AUTO_INCREMENT = 17;" + "COMMIT;", + db->cnid_mysql_voluuid_str, + db->cnid_mysql_voluuid_str, + db->cnid_mysql_voluuid_str) ); + db->cnid_mysql_flags |= CNID_MYSQL_FLAG_DEPLETED; + hint = CNID_INVALID; + do { + result = mysql_store_result(db->cnid_mysql_con); + if (result) + mysql_free_result(result); + } while (mysql_next_result(db->cnid_mysql_con) == 0); + continue; + } + + /* Finally assign our result */ + id = htonl((uint32_t)lastid); + } + } while (id == CNID_INVALID); + +EC_CLEANUP: + LOG(log_debug, logtype_cnid, "cnid_mysql_add: id: %" PRIu32, ntohl(id)); + + if (result) + mysql_free_result(result); + return id; +} + +cnid_t cnid_mysql_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len) +{ + EC_INIT; + CNID_mysql_private *db; + cnid_t id = CNID_INVALID; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + + if (!cdb || !(db = cdb->cnid_db_private) || !name) { + LOG(log_error, logtype_cnid, "cnid_mysql_get: Parameter error"); + errno = CNID_ERR_PARAM; + EC_FAIL; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_mysql_get: name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + LOG(log_debug, logtype_cnid, "cnid_mysql_get(did: %" PRIu32 ", name: \"%s\"): START", + ntohl(did),name); + + EC_NEG1( cnid_mysql_execute(db->cnid_mysql_con, + "SELECT Id FROM %s " + "WHERE Name='%s' AND Did=%" PRIu32, + db->cnid_mysql_voluuid_str, + name, + ntohl(did)) ); + + if ((result = mysql_store_result(db->cnid_mysql_con)) == NULL) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + errno = CNID_ERR_DB; + EC_FAIL; + } + + if (mysql_num_rows(result)) { + row = mysql_fetch_row(result); + id = htonl(atoi(row[0])); + } + +EC_CLEANUP: + LOG(log_debug, logtype_cnid, "cnid_mysql_get: id: %" PRIu32, ntohl(id)); + + if (result) + mysql_free_result(result); + + return id; +} + +char *cnid_mysql_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len) +{ + EC_INIT; + CNID_mysql_private *db; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + + if (!cdb || !(db = cdb->cnid_db_private)) { + LOG(log_error, logtype_cnid, "cnid_mysql_get: Parameter error"); + errno = CNID_ERR_PARAM; + EC_FAIL; + } + + EC_NEG1( cnid_mysql_execute( + db->cnid_mysql_con, + "SELECT Did,Name FROM %s WHERE Id=%" PRIu32, + db->cnid_mysql_voluuid_str, ntohl(*id)) ); + + EC_NULL( result = mysql_store_result(db->cnid_mysql_con) ); + + if (mysql_num_rows(result) != 1) + EC_FAIL; + + row = mysql_fetch_row(result); + + *id = htonl(atoi(row[0])); + strncpy(buffer, row[1], len); + +EC_CLEANUP: + if (result) + mysql_free_result(result); + + if (ret != 0) { + *id = CNID_INVALID; + return NULL; + } + return buffer; +} + +/** + * Caller passes buffer where we will store the db stamp + **/ +int cnid_mysql_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) +{ + EC_INIT; + CNID_mysql_private *db; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + + if (!cdb || !(db = cdb->cnid_db_private)) { + LOG(log_error, logtype_cnid, "cnid_find: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (!buffer) + EC_EXIT_STATUS(0); + + if (cnid_mysql_execute(db->cnid_mysql_con, + "SELECT Stamp FROM volumes WHERE VolPath='%s'", + cdb->cnid_db_vol->v_path)) { + if (mysql_errno(db->cnid_mysql_con) != ER_DUP_ENTRY) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + EC_FAIL; + } + } + + if ((result = mysql_store_result(db->cnid_mysql_con)) == NULL) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + errno = CNID_ERR_DB; + EC_FAIL; + } + if (!mysql_num_rows(result)) { + LOG(log_error, logtype_cnid, "Can't get DB stamp for volumes \"%s\"", cdb->cnid_db_vol->v_path); + EC_FAIL; + } + row = mysql_fetch_row(result); + memcpy(buffer, row[0], len); + +EC_CLEANUP: + if (result) + mysql_free_result(result); + EC_EXIT; +} + + +int cnid_mysql_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen) +{ + LOG(log_error, logtype_cnid, + "cnid_mysql_find(\"%s\"): not supported with MySQL CNID backend", name); + return -1; +} + +cnid_t cnid_mysql_rebuild_add(struct _cnid_db *cdb, const struct stat *st, + cnid_t did, const char *name, size_t len, cnid_t hint) +{ + LOG(log_error, logtype_cnid, + "cnid_mysql_rebuild_add(\"%s\"): not supported with MySQL CNID backend", name); + return CNID_INVALID; +} + +int cnid_mysql_wipe(struct _cnid_db *cdb) +{ + EC_INIT; + CNID_mysql_private *db; + MYSQL_RES *result = NULL; + + if (!cdb || !(db = cdb->cnid_db_private)) { + LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error"); + errno = CNID_ERR_PARAM; + return -1; + } + + LOG(log_debug, logtype_cnid, "cnid_dbd_wipe"); + + EC_NEG1( cnid_mysql_execute( + db->cnid_mysql_con, + "START TRANSACTION;" + "UPDATE volumes SET Depleted=0 WHERE VolUUID='%s';" + "TRUNCATE TABLE %s;" + "ALTER TABLE %s AUTO_INCREMENT = 17;" + "COMMIT;", + db->cnid_mysql_voluuid_str, + db->cnid_mysql_voluuid_str, + db->cnid_mysql_voluuid_str) ); + + do { + result = mysql_store_result(db->cnid_mysql_con); + if (result) + mysql_free_result(result); + } while (mysql_next_result(db->cnid_mysql_con) == 0); + +EC_CLEANUP: + EC_EXIT; +} + +static struct _cnid_db *cnid_mysql_new(struct vol *vol) +{ + struct _cnid_db *cdb; + + if ((cdb = (struct _cnid_db *)calloc(1, sizeof(struct _cnid_db))) == NULL) + return NULL; + + cdb->cnid_db_vol = vol; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; + cdb->cnid_add = cnid_mysql_add; + cdb->cnid_delete = cnid_mysql_delete; + cdb->cnid_get = cnid_mysql_get; + cdb->cnid_lookup = cnid_mysql_lookup; + cdb->cnid_find = cnid_mysql_find; + cdb->cnid_nextid = NULL; + cdb->cnid_resolve = cnid_mysql_resolve; + cdb->cnid_getstamp = cnid_mysql_getstamp; + cdb->cnid_update = cnid_mysql_update; + cdb->cnid_rebuild_add = cnid_mysql_rebuild_add; + cdb->cnid_close = cnid_mysql_close; + cdb->cnid_wipe = cnid_mysql_wipe; + return cdb; +} + +/* Return allocated UUID string with dashes stripped */ +static char *uuid_strip_dashes(const char *uuid) { + static char stripped[33]; + int i = 0; + + while (*uuid && i < 32) { + if (*uuid != '-') { + stripped[i++] = *uuid; + } + uuid++; + } + stripped[i] = 0; + return strdup(stripped); +} + +/* ---------------------- */ +struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args) +{ + EC_INIT; + CNID_mysql_private *db = NULL; + struct _cnid_db *cdb = NULL; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + struct vol *vol = args->cnid_args_vol; + + EC_NULL( cdb = cnid_mysql_new(vol) ); + EC_NULL( db = (CNID_mysql_private *)calloc(1, sizeof(CNID_mysql_private)) ); + cdb->cnid_db_private = db; + + EC_NULL( db->cnid_mysql_voluuid_str = uuid_strip_dashes(vol->v_uuid) ); + + /* Initialize and connect to MySQL server */ + EC_NULL( db->cnid_mysql_con = mysql_init(NULL) ); + my_bool my_recon = true; + EC_ZERO( mysql_options(db->cnid_mysql_con, MYSQL_OPT_RECONNECT, &my_recon) ); + int my_timeout = 600; + EC_ZERO( mysql_options(db->cnid_mysql_con, MYSQL_OPT_CONNECT_TIMEOUT, &my_timeout) ); + + const AFPObj *obj = vol->v_obj; + + EC_NULL( mysql_real_connect(db->cnid_mysql_con, + obj->options.cnid_mysql_host, + obj->options.cnid_mysql_user, + obj->options.cnid_mysql_pw, + obj->options.cnid_mysql_db, + 0, NULL, CLIENT_MULTI_STATEMENTS)); + + /* Add volume to volume table */ + if (cnid_mysql_execute(db->cnid_mysql_con, + "CREATE TABLE IF NOT EXISTS volumes" + "(VolUUID CHAR(32) PRIMARY KEY,VolPath TEXT(4096),Stamp BINARY(8),Depleted INT, INDEX(VolPath(64)))")) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + EC_FAIL; + } + time_t now = time(NULL); + char stamp[8]; + memset(stamp, 0, 8); + memcpy(stamp, &now, sizeof(time_t)); + char blob[16+1]; + mysql_real_escape_string(db->cnid_mysql_con, blob, stamp, 8); + + if (cnid_mysql_execute(db->cnid_mysql_con, + "INSERT INTO volumes (VolUUID,Volpath,Stamp,Depleted) " + "VALUES('%s','%s','%s',0)", + db->cnid_mysql_voluuid_str, + vol->v_path, + blob)) { + if (mysql_errno(db->cnid_mysql_con) != ER_DUP_ENTRY) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + EC_FAIL; + } + } + + /* + * Check whether CNID set overflowed before. + * If that's the case, in cnid_mysql_add() we'll ignore the CNID "hint" taken from the + * AppleDouble file. + */ + if (cnid_mysql_execute(db->cnid_mysql_con, + "SELECT Depleted FROM volumes WHERE VolUUID='%s'", + db->cnid_mysql_voluuid_str)) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + EC_FAIL; + } + if ((result = mysql_store_result(db->cnid_mysql_con)) == NULL) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + errno = CNID_ERR_DB; + EC_FAIL; + } + if (mysql_num_rows(result)) { + row = mysql_fetch_row(result); + int depleted = atoi(row[0]); + if (depleted) + db->cnid_mysql_flags |= CNID_MYSQL_FLAG_DEPLETED; + } + mysql_free_result(result); + result = NULL; + + /* Create volume table */ + if (cnid_mysql_execute(db->cnid_mysql_con, + "CREATE TABLE IF NOT EXISTS %s" + "(Id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT," + "Name VARCHAR(255) NOT NULL," + "Did INT UNSIGNED NOT NULL," + "DevNo BIGINT UNSIGNED NOT NULL," + "InodeNo BIGINT UNSIGNED NOT NULL," + "UNIQUE DidName(Did, Name), UNIQUE DevIno(DevNo, InodeNo)) " + "AUTO_INCREMENT=17", + db->cnid_mysql_voluuid_str)) { + LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con)); + EC_FAIL; + } + + EC_ZERO( init_prepared_stmt(db) ); + + LOG(log_debug, logtype_cnid, "Finished initializing MySQL CNID module for volume '%s'", + vol->v_path); + +EC_CLEANUP: + if (result) + mysql_free_result(result); + if (ret != 0) { + if (cdb) + free(cdb); + cdb = NULL; + if (db) + free(db); + } + return cdb; +} + +struct _cnid_module cnid_mysql_module = { + "mysql", + {NULL, NULL}, + cnid_mysql_open, + 0 +}; diff --git a/libatalk/cnid/tdb/Makefile.am b/libatalk/cnid/tdb/Makefile.am new file mode 100644 index 0000000..93c289a --- /dev/null +++ b/libatalk/cnid/tdb/Makefile.am @@ -0,0 +1,20 @@ +# Makefile.am for libatalk/cnid/ + +if USE_TDB_BACKEND +noinst_LTLIBRARIES = libcnid_tdb.la +endif + +libcnid_tdb_la_SOURCES = cnid_tdb_add.c \ + cnid_tdb_close.c \ + cnid_tdb_delete.c \ + cnid_tdb_get.c \ + cnid_tdb_lookup.c \ + cnid_tdb_open.c \ + cnid_tdb_resolve.c \ + cnid_tdb_update.c \ + cnid_tdb.h + +libcnid_tdb_la_CFLAGS = @TDB_CFLAGS@ +libcnid_tdb_la_LIBADD = @TDB_LIBS@ + +EXTRA_DIST = README cnid_tdb_nextid.c diff --git a/libatalk/cnid/tdb/Makefile.in b/libatalk/cnid/tdb/Makefile.in new file mode 100644 index 0000000..262ec6e --- /dev/null +++ b/libatalk/cnid/tdb/Makefile.in @@ -0,0 +1,748 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/cnid/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/cnid/tdb +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcnid_tdb_la_DEPENDENCIES = +am_libcnid_tdb_la_OBJECTS = libcnid_tdb_la-cnid_tdb_add.lo \ + libcnid_tdb_la-cnid_tdb_close.lo \ + libcnid_tdb_la-cnid_tdb_delete.lo \ + libcnid_tdb_la-cnid_tdb_get.lo \ + libcnid_tdb_la-cnid_tdb_lookup.lo \ + libcnid_tdb_la-cnid_tdb_open.lo \ + libcnid_tdb_la-cnid_tdb_resolve.lo \ + libcnid_tdb_la-cnid_tdb_update.lo +libcnid_tdb_la_OBJECTS = $(am_libcnid_tdb_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libcnid_tdb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libcnid_tdb_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ + $@ +@USE_TDB_BACKEND_TRUE@am_libcnid_tdb_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcnid_tdb_la_SOURCES) +DIST_SOURCES = $(libcnid_tdb_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@USE_TDB_BACKEND_TRUE@noinst_LTLIBRARIES = libcnid_tdb.la +libcnid_tdb_la_SOURCES = cnid_tdb_add.c \ + cnid_tdb_close.c \ + cnid_tdb_delete.c \ + cnid_tdb_get.c \ + cnid_tdb_lookup.c \ + cnid_tdb_open.c \ + cnid_tdb_resolve.c \ + cnid_tdb_update.c \ + cnid_tdb.h + +libcnid_tdb_la_CFLAGS = @TDB_CFLAGS@ +libcnid_tdb_la_LIBADD = @TDB_LIBS@ +EXTRA_DIST = README cnid_tdb_nextid.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/cnid/tdb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/cnid/tdb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcnid_tdb.la: $(libcnid_tdb_la_OBJECTS) $(libcnid_tdb_la_DEPENDENCIES) $(EXTRA_libcnid_tdb_la_DEPENDENCIES) + $(AM_V_CCLD)$(libcnid_tdb_la_LINK) $(am_libcnid_tdb_la_rpath) $(libcnid_tdb_la_OBJECTS) $(libcnid_tdb_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_add.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_close.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_delete.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_get.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_lookup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_open.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_resolve.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcnid_tdb_la-cnid_tdb_update.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libcnid_tdb_la-cnid_tdb_add.lo: cnid_tdb_add.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_add.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_add.Tpo -c -o libcnid_tdb_la-cnid_tdb_add.lo `test -f 'cnid_tdb_add.c' || echo '$(srcdir)/'`cnid_tdb_add.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_add.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_add.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_add.c' object='libcnid_tdb_la-cnid_tdb_add.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_add.lo `test -f 'cnid_tdb_add.c' || echo '$(srcdir)/'`cnid_tdb_add.c + +libcnid_tdb_la-cnid_tdb_close.lo: cnid_tdb_close.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_close.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_close.Tpo -c -o libcnid_tdb_la-cnid_tdb_close.lo `test -f 'cnid_tdb_close.c' || echo '$(srcdir)/'`cnid_tdb_close.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_close.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_close.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_close.c' object='libcnid_tdb_la-cnid_tdb_close.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_close.lo `test -f 'cnid_tdb_close.c' || echo '$(srcdir)/'`cnid_tdb_close.c + +libcnid_tdb_la-cnid_tdb_delete.lo: cnid_tdb_delete.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_delete.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_delete.Tpo -c -o libcnid_tdb_la-cnid_tdb_delete.lo `test -f 'cnid_tdb_delete.c' || echo '$(srcdir)/'`cnid_tdb_delete.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_delete.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_delete.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_delete.c' object='libcnid_tdb_la-cnid_tdb_delete.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_delete.lo `test -f 'cnid_tdb_delete.c' || echo '$(srcdir)/'`cnid_tdb_delete.c + +libcnid_tdb_la-cnid_tdb_get.lo: cnid_tdb_get.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_get.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_get.Tpo -c -o libcnid_tdb_la-cnid_tdb_get.lo `test -f 'cnid_tdb_get.c' || echo '$(srcdir)/'`cnid_tdb_get.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_get.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_get.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_get.c' object='libcnid_tdb_la-cnid_tdb_get.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_get.lo `test -f 'cnid_tdb_get.c' || echo '$(srcdir)/'`cnid_tdb_get.c + +libcnid_tdb_la-cnid_tdb_lookup.lo: cnid_tdb_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_lookup.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_lookup.Tpo -c -o libcnid_tdb_la-cnid_tdb_lookup.lo `test -f 'cnid_tdb_lookup.c' || echo '$(srcdir)/'`cnid_tdb_lookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_lookup.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_lookup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_lookup.c' object='libcnid_tdb_la-cnid_tdb_lookup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_lookup.lo `test -f 'cnid_tdb_lookup.c' || echo '$(srcdir)/'`cnid_tdb_lookup.c + +libcnid_tdb_la-cnid_tdb_open.lo: cnid_tdb_open.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_open.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_open.Tpo -c -o libcnid_tdb_la-cnid_tdb_open.lo `test -f 'cnid_tdb_open.c' || echo '$(srcdir)/'`cnid_tdb_open.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_open.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_open.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_open.c' object='libcnid_tdb_la-cnid_tdb_open.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_open.lo `test -f 'cnid_tdb_open.c' || echo '$(srcdir)/'`cnid_tdb_open.c + +libcnid_tdb_la-cnid_tdb_resolve.lo: cnid_tdb_resolve.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_resolve.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_resolve.Tpo -c -o libcnid_tdb_la-cnid_tdb_resolve.lo `test -f 'cnid_tdb_resolve.c' || echo '$(srcdir)/'`cnid_tdb_resolve.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_resolve.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_resolve.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_resolve.c' object='libcnid_tdb_la-cnid_tdb_resolve.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_resolve.lo `test -f 'cnid_tdb_resolve.c' || echo '$(srcdir)/'`cnid_tdb_resolve.c + +libcnid_tdb_la-cnid_tdb_update.lo: cnid_tdb_update.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -MT libcnid_tdb_la-cnid_tdb_update.lo -MD -MP -MF $(DEPDIR)/libcnid_tdb_la-cnid_tdb_update.Tpo -c -o libcnid_tdb_la-cnid_tdb_update.lo `test -f 'cnid_tdb_update.c' || echo '$(srcdir)/'`cnid_tdb_update.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcnid_tdb_la-cnid_tdb_update.Tpo $(DEPDIR)/libcnid_tdb_la-cnid_tdb_update.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid_tdb_update.c' object='libcnid_tdb_la-cnid_tdb_update.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcnid_tdb_la_CFLAGS) $(CFLAGS) -c -o libcnid_tdb_la-cnid_tdb_update.lo `test -f 'cnid_tdb_update.c' || echo '$(srcdir)/'`cnid_tdb_update.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/cnid/tdb/README b/libatalk/cnid/tdb/README new file mode 100644 index 0000000..b39889b --- /dev/null +++ b/libatalk/cnid/tdb/README @@ -0,0 +1,35 @@ +the catalog database keeps track of three mappings: + CNID -> dev/ino and did/name + dev/ino -> CNID + did/name -> CNID + +dev/ino is used to keep track of magically moved files. did/name is +for quick lookups of CNIDs. + +NOTE: the database will append a nul byte to the end of name. in +addition, name should be given as it appears on disk. this allows the +creation of cnid updating/cleaning programs that don't have to deal +with knowing what the particular codepage is. + +here's the ritual: + 1) open a volume. call cnid_open. + 2) every time you need a CNID, call cnid_add(). it will + automatically look for an existing cnid and add a new one + if one isn't already there. you can pass a hint if you + want. the only use this has right now is to enable + consistency between AFP and HFS. in the future, it would + allow people to write conversion utilities that + pre-instantiate a database without needing to re-assign + CNIDs. + 3) if you want to just look for a CNID without automatically + adding one in, you have two choices: + a) cnid_resolve takes a CNID, returns name, and + over-writes the CNID given with the parent DID. this + is good for FPResolveID. + b) cnid_lookup returns a CNID corresponding to the + dev/ino,did/name keys. it will auto-update the catalog + database if there's a discrepancy. + NOTE: cnid_add calls this before adding a new CNID. + 4) when you delete a file or directory, you need to call + cnid_delete with the CNID for that file/directory. + 5) call cnid_close when closing the volume. diff --git a/libatalk/cnid/tdb/cnid_tdb.h b/libatalk/cnid/tdb/cnid_tdb.h new file mode 100644 index 0000000..64cc214 --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb.h @@ -0,0 +1,75 @@ +/* + * interface for database access to cnids. i do it this way to abstract + * things a bit in case we want to change the underlying implementation. + */ + +#ifndef _ATALK_CNID_TDB__H +#define _ATALK_CNID_TDB__H 1 + +#include +#include +#include +#include +#include + +#include +#include +#define STANDALONE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TDB_ERROR_LINK 1 +#define TDB_ERROR_DEV 2 +#define TDB_ERROR_INODE 4 + +struct _cnid_tdb_private { + dev_t st_dev; + int st_set; + int error; + int flags; + TDB_CONTEXT *tdb_cnid; + TDB_CONTEXT *tdb_didname; + TDB_CONTEXT *tdb_devino; + +}; + +/* cnid_open.c */ +extern struct _cnid_module cnid_tdb_module; +extern struct _cnid_db *cnid_tdb_open (struct cnid_open_args *args); + +/* cnid_close.c */ +extern void cnid_tdb_close (struct _cnid_db *); + +/* cnid_add.c */ +extern cnid_t cnid_tdb_add (struct _cnid_db *, const struct stat *, cnid_t, + const char *, size_t, cnid_t); + +/* cnid_get.c */ +extern cnid_t cnid_tdb_get (struct _cnid_db *, cnid_t, const char *, size_t); +extern char *cnid_tdb_resolve (struct _cnid_db *, cnid_t *, void *, size_t); +extern cnid_t cnid_tdb_lookup (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t); + +/* cnid_update.c */ +extern int cnid_tdb_update (struct _cnid_db *, cnid_t, const struct stat *, + cnid_t, const char *, size_t); + +/* cnid_delete.c */ +extern int cnid_tdb_delete (struct _cnid_db *, const cnid_t); + +/* cnid_nextid.c */ +extern cnid_t cnid_tdb_nextid (struct _cnid_db *); + +/* construct db_cnid data. NOTE: this is not re-entrant. */ +extern unsigned char *make_tdb_data(uint32_t flags, const struct stat *st, const cnid_t did, const char *name, const size_t len); + +#endif /* include/atalk/cnid_tdb.h */ diff --git a/libatalk/cnid/tdb/cnid_tdb_add.c b/libatalk/cnid/tdb/cnid_tdb_add.c new file mode 100644 index 0000000..b3babcd --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_add.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB +#include "cnid_tdb.h" +#include +#include +#include +#include +#include +#include + +static void make_devino_data(unsigned char *buf, dev_t dev, ino_t ino) +{ + buf[CNID_DEV_LEN - 1] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 2] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 3] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 4] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 5] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 6] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 7] = dev; dev >>= 8; + buf[CNID_DEV_LEN - 8] = dev; + + buf[CNID_DEV_LEN + CNID_INO_LEN - 1] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 2] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 3] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 4] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 5] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 6] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 7] = ino; ino >>= 8; + buf[CNID_DEV_LEN + CNID_INO_LEN - 8] = ino; +} + +unsigned char *make_tdb_data(uint32_t flags, const struct stat *st,const cnid_t did, + const char *name, const size_t len) +{ + static unsigned char start[CNID_HEADER_LEN + MAXPATHLEN + 1]; + unsigned char *buf = start +CNID_LEN; + uint32_t i; + + if (len > MAXPATHLEN) + return NULL; + + make_devino_data(buf, !(flags & CNID_FLAG_NODEV)?st->st_dev:0, st->st_ino); + buf += CNID_DEVINO_LEN; + + i = S_ISDIR(st->st_mode)?1:0; + i = htonl(i); + memcpy(buf, &i, sizeof(i)); + buf += sizeof(i); + + /* did is already in network byte order */ + memcpy(buf, &did, sizeof(did)); + buf += sizeof(did); + + memcpy(buf, name, len); + *(buf + len) = '\0'; + + return start; +} + +/* add an entry to the CNID databases. we do this as a transaction + * to prevent messiness. + * key: cnid + * data: + */ +static int add_cnid (struct _cnid_tdb_private *db, TDB_DATA *key, TDB_DATA *data) { + TDB_DATA altkey, altdata; + + memset(&altkey, 0, sizeof(altkey)); + memset(&altdata, 0, sizeof(altdata)); + + + /* main database */ + if (tdb_store(db->tdb_cnid, *key, *data, TDB_REPLACE)) { + goto abort; + } + + /* dev/ino database */ + altkey.dptr = data->dptr +CNID_DEVINO_OFS; + altkey.dsize = CNID_DEVINO_LEN; + altdata.dptr = key->dptr; + altdata.dsize = key->dsize; + if (tdb_store(db->tdb_devino, altkey, altdata, TDB_REPLACE)) { + goto abort; + } + + /* did/name database */ + altkey.dptr = data->dptr +CNID_DID_OFS; + altkey.dsize = data->dsize -CNID_DID_OFS; + if (tdb_store(db->tdb_didname, altkey, altdata, TDB_REPLACE)) { + goto abort; + } + return 0; + +abort: + return -1; +} + +/* ----------------------- */ +static cnid_t get_cnid(struct _cnid_tdb_private *db) +{ + TDB_DATA rootinfo_key, data; + cnid_t hint,id; + + memset(&rootinfo_key, 0, sizeof(rootinfo_key)); + memset(&data, 0, sizeof(data)); + rootinfo_key.dptr = (unsigned char *)ROOTINFO_KEY; + rootinfo_key.dsize = ROOTINFO_KEYLEN; + + tdb_chainlock(db->tdb_didname, rootinfo_key); + data = tdb_fetch(db->tdb_didname, rootinfo_key); + if (data.dptr) + { + memcpy(&hint, data.dptr, sizeof(cnid_t)); + free(data.dptr); + id = ntohl(hint); + /* If we've hit the max CNID allowed, we return a fatal error. CNID + * needs to be recycled before proceding. */ + if (++id == CNID_INVALID) { + LOG(log_error, logtype_default, "cnid_add: FATAL: CNID database has reached its limit."); + errno = CNID_ERR_MAX; + goto cleanup; + } + hint = htonl(id); + } + else { + hint = htonl(CNID_START); + } + + memset(&data, 0, sizeof(data)); + data.dptr = (unsigned char *)&hint; + data.dsize = sizeof(hint); + if (tdb_store(db->tdb_didname, rootinfo_key, data, TDB_REPLACE)) { + goto cleanup; + } + + tdb_chainunlock(db->tdb_didname, rootinfo_key ); + return hint; +cleanup: + tdb_chainunlock(db->tdb_didname, rootinfo_key); + return CNID_INVALID; +} + + +/* ------------------------ */ +cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st, + cnid_t did, const char *name, size_t len, cnid_t hint) +{ + const struct stat *lstp; + cnid_t id; + struct _cnid_tdb_private *priv; + TDB_DATA key, data; + int rc; + + if (!cdb || !(priv = cdb->cnid_db_private) || !st || !name) { + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + /* Do a lookup. */ + id = cnid_tdb_lookup(cdb, st, did, name, len); + /* ... Return id if it is valid, or if Rootinfo is read-only. */ + if (id || (priv->flags & CNIDFLAG_DB_RO)) { + return id; + } + +#if 0 + struct stat lst; + lstp = lstat(name, &lst) < 0 ? st : &lst; +#endif + lstp = st; + + /* Initialize our DBT data structures. */ + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.dptr = (unsigned char *)&hint; + key.dsize = sizeof(cnid_t); + if ((data.dptr = make_tdb_data(cdb->cnid_db_flags, lstp, did, name, len)) == NULL) { + LOG(log_error, logtype_default, "tdb_add: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + data.dsize = CNID_HEADER_LEN + len + 1; + hint = get_cnid(priv); + if (hint == 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + memcpy(data.dptr, &hint, sizeof(hint)); + + /* Now we need to add the CNID data to the databases. */ + rc = add_cnid(priv, &key, &data); + if (rc) { + LOG(log_error, logtype_default, "tdb_add: Failed to add CNID for %s to database using hint %u", name, ntohl(hint)); + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + return hint; +} + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_close.c b/libatalk/cnid/tdb/cnid_tdb_close.c new file mode 100644 index 0000000..4879e10 --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_close.c @@ -0,0 +1,22 @@ +/* + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB + +#include "cnid_tdb.h" + +void cnid_tdb_close(struct _cnid_db *cdb) +{ + struct _cnid_tdb_private *db; + + db = (struct _cnid_tdb_private *)cdb->cnid_db_private; + tdb_close(db->tdb_cnid); + free(cdb->cnid_db_private); + free(cdb); +} + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_delete.c b/libatalk/cnid/tdb/cnid_tdb_delete.c new file mode 100644 index 0000000..9544109 --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_delete.c @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + * cnid_delete: delete a CNID from the database + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB + +#include "cnid_tdb.h" + +int cnid_tdb_delete(struct _cnid_db *cdb, const cnid_t id) +{ + struct _cnid_tdb_private *db; + TDB_DATA key, data; + + if (!cdb || !(db = cdb->cnid_db_private) || !id) { + return -1; + } + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + key.dptr = (unsigned char *)&id; + key.dsize = sizeof(cnid_t); + data = tdb_fetch(db->tdb_cnid, key); + if (!data.dptr) + { + return 0; + } + + tdb_delete(db->tdb_cnid, key); + + key.dptr = data.dptr +CNID_DEVINO_OFS; + key.dsize = CNID_DEVINO_LEN; + tdb_delete(db->tdb_devino, key); + + key.dptr = data.dptr +CNID_DID_OFS; + key.dsize = data.dsize -CNID_DID_OFS; + tdb_delete(db->tdb_didname, key); + + free(data.dptr); + return 0; +} + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_get.c b/libatalk/cnid/tdb/cnid_tdb_get.c new file mode 100644 index 0000000..5c75367 --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_get.c @@ -0,0 +1,40 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB + +#include "cnid_tdb.h" + +/* Return CNID for a given did/name. */ +cnid_t cnid_tdb_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len) +{ + char start[CNID_DID_LEN + MAXPATHLEN + 1], *buf; + struct _cnid_tdb_private *db; + TDB_DATA key, data; + cnid_t id; + + if (!cdb || !(db = cdb->cnid_db_private) || (len > MAXPATHLEN)) { + return 0; + } + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + + buf = start; + memcpy(buf, &did, sizeof(did)); + buf += sizeof(did); + memcpy(buf, name, len); + *(buf + len) = '\0'; /* Make it a C-string. */ + key.dptr = (unsigned char *)start; + key.dsize = CNID_DID_LEN + len + 1; + data = tdb_fetch(db->tdb_didname, key); + if (!data.dptr) + return 0; + + memcpy(&id, data.dptr, sizeof(id)); + free(data.dptr); + return id; +} + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_lookup.c b/libatalk/cnid/tdb/cnid_tdb_lookup.c new file mode 100644 index 0000000..7c7bdff --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_lookup.c @@ -0,0 +1,152 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB + +#include "cnid_tdb.h" +#include + +cnid_t cnid_tdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, const char *name, size_t len) +{ + char *buf; + struct _cnid_tdb_private *db; + TDB_DATA key, devdata, diddata, cniddata; + int devino = 1, didname = 1; + char dev[CNID_DEV_LEN]; + char ino[CNID_INO_LEN]; + uint32_t type_devino = (unsigned)-1; + uint32_t type_didname = (unsigned)-1; + uint32_t type; + int update = 0; + cnid_t id_devino = 0, id_didname = 0,id = 0; + + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { + return 0; + } + + if ((buf = (char *)make_tdb_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) { + LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long"); + return 0; + } + memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type)); + type = ntohl(type); + + memset(&key, 0, sizeof(key)); + memset(&devdata, 0, sizeof(devdata)); + memset(&diddata, 0, sizeof(diddata)); + memset(&cniddata, 0, sizeof(cniddata)); + + /* Look for a CNID. We have two options: dev/ino or did/name. If we + * only get a match in one of them, that means a file has moved. */ + memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN); + memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN); + + key.dptr = (unsigned char *)buf + CNID_DEVINO_OFS; + key.dsize = CNID_DEVINO_LEN; + cniddata = tdb_fetch(db->tdb_devino, key); + if (!cniddata.dptr) { + devino = 0; + } + else { + + key.dptr = cniddata.dptr; + key.dsize = sizeof(id); + + devdata = tdb_fetch(db->tdb_cnid, key); + free(cniddata.dptr); + if (devdata.dptr) { + memcpy(&id_devino, devdata.dptr, sizeof(cnid_t)); + memcpy(&type_devino, (char *)devdata.dptr +CNID_TYPE_OFS, sizeof(type_devino)); + type_devino = ntohl(type_devino); + } + else { + devino = 0; + } + } + + /* did/name now */ + key.dptr = (unsigned char *)buf + CNID_DID_OFS; + key.dsize = CNID_DID_LEN + len + 1; + cniddata = tdb_fetch(db->tdb_didname, key); + if (!cniddata.dptr) { + didname = 0; + } + else { + + key.dptr = cniddata.dptr; + key.dsize = sizeof(id); + + diddata = tdb_fetch(db->tdb_cnid, key); + free(cniddata.dptr); + if (diddata.dptr) { + memcpy(&id_didname, diddata.dptr, sizeof(cnid_t)); + memcpy(&type_didname, (char *)diddata.dptr +CNID_TYPE_OFS, sizeof(type_didname)); + type_didname = ntohl(type_didname); + } + else { + didname = 0; + } + } + /* Set id. Honor did/name over dev/ino as dev/ino isn't necessarily + * 1-1. */ + if (!devino && !didname) { + free(devdata.dptr); + free(diddata.dptr); + return 0; + } + + if (devino && didname && id_devino == id_didname && type_devino == type) { + /* the same */ + free(devdata.dptr); + free(diddata.dptr); + return id_didname; + } + + if (didname) { + id = id_didname; + /* we have a did:name + * if it's the same dev or not the same type + * just delete it + */ + if (!memcmp(dev, (char *)diddata.dptr + CNID_DEV_OFS, CNID_DEV_LEN) || + type_didname != type) { + if (cnid_tdb_delete(cdb, id) < 0) { + free(devdata.dptr); + free(diddata.dptr); + return 0; + } + } + else { + update = 1; + } + } + + if (devino) { + id = id_devino; + if (type_devino != type) { + /* same dev:inode but not same type one is a folder the other + * is a file,it's an inode reused, delete the record + */ + if (cnid_tdb_delete(cdb, id) < 0) { + free(devdata.dptr); + free(diddata.dptr); + return 0; + } + } + else { + update = 1; + } + } + free(devdata.dptr); + free(diddata.dptr); + if (!update) { + return 0; + } + + /* Fix up the database. */ + cnid_tdb_update(cdb, id, st, did, name, len); + return id; +} + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_nextid.c b/libatalk/cnid/tdb/cnid_tdb_nextid.c new file mode 100644 index 0000000..8e7b126 --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_nextid.c @@ -0,0 +1,17 @@ +/* + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB + +#include "cnid_tdb.h" + +cnid_t cnid_tdb_nextid(struct _cnid_db *cdb) +{ + return CNID_INVALID; +} + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_open.c b/libatalk/cnid/tdb/cnid_tdb_open.c new file mode 100644 index 0000000..7e2558f --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_open.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu) + * All Rights Reserved. See COPYRIGHT. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB +#include + +#include "cnid_tdb.h" +#include +#include + +#include +#define DBHOME ".AppleDB" +#define DBHOMELEN 9 /* strlen(DBHOME) +1 for / */ +#define DBLEN 12 +#define DBCNID "cnid2.tdb" + +#define DBVERSION_KEY "\0\0\0\0Version" +#define DBVERSION_KEYLEN (sizeof(DBVERSION_KEY)) +#define DBVERSION2 0x00000002U +#define DBVERSION DBVERSION2 + +static struct _cnid_db *cnid_tdb_new(struct vol *vol) +{ + struct _cnid_db *cdb; + + if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL) + return NULL; + + cdb->cnid_db_vol = vol; + + if ((cdb->cnid_db_private = calloc(1, sizeof(struct _cnid_tdb_private))) == NULL) { + free(cdb); + return NULL; + } + + /* Set up standard fields */ + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT; + + cdb->cnid_add = cnid_tdb_add; + cdb->cnid_delete = cnid_tdb_delete; + cdb->cnid_get = cnid_tdb_get; + cdb->cnid_lookup = cnid_tdb_lookup; + cdb->cnid_nextid = NULL; /*cnid_tdb_nextid;*/ + cdb->cnid_resolve = cnid_tdb_resolve; + cdb->cnid_update = cnid_tdb_update; + cdb->cnid_close = cnid_tdb_close; + cdb->cnid_wipe = NULL; + + return cdb; +} + +/* ---------------------------- */ +struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args) +{ + struct stat st; + struct _cnid_db *cdb; + struct _cnid_tdb_private *db; + size_t len; + char path[MAXPATHLEN + 1]; + TDB_DATA key, data; + int hash_size = 131071; + int tdb_flags = 0; + struct vol *vol = args->cnid_args_vol; + + if ((cdb = cnid_tdb_new(vol)) == NULL) { + LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb"); + return NULL; + } + + if ((len = strlen(vol->v_path)) > (MAXPATHLEN - DBLEN - 1)) { + LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", vol->v_path); + return NULL; + } + + strcpy(path, vol->v_path); + if (path[len - 1] != '/') { + strcat(path, "/"); + len++; + } + + strcpy(path + len, DBHOME); + if (!(args->cnid_args_flags & CNID_FLAG_MEMORY)) { + if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~vol->v_umask) < 0)) { + LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path); + goto fail; + } + } + else { + hash_size = 0; + tdb_flags = TDB_INTERNAL; + } + strcat(path, "/"); + + db = (struct _cnid_tdb_private *)cdb->cnid_db_private; + + path[len + DBHOMELEN] = '\0'; + strcat(path, DBCNID); + + db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~vol->v_umask); + if (!db->tdb_cnid) { + LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path); + goto fail; + } + /* ------------- */ + db->tdb_didname = db->tdb_cnid; + db->tdb_devino = db->tdb_cnid; + + /* Check for version. This way we can update the database if we need + * to change the format in any way. */ + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + key.dptr = (unsigned char *)DBVERSION_KEY; + key.dsize = DBVERSION_KEYLEN; + + data = tdb_fetch(db->tdb_didname, key); + if (!data.dptr) { + uint32_t version = htonl(DBVERSION); + + data.dptr = (unsigned char *)&version; + data.dsize = sizeof(version); + if (tdb_store(db->tdb_didname, key, data, TDB_REPLACE)) { + LOG(log_error, logtype_default, "tdb_open: Error putting new version"); + goto fail; + } + } + else { + free(data.dptr); + } + + return cdb; + +fail: + free(cdb->cnid_db_private); + free(cdb); + + return NULL; +} + +struct _cnid_module cnid_tdb_module = { + "tdb", + {NULL, NULL}, + cnid_tdb_open, + CNID_FLAG_SETUID | CNID_FLAG_BLOCK +}; + + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_resolve.c b/libatalk/cnid/tdb/cnid_tdb_resolve.c new file mode 100644 index 0000000..b999ca3 --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_resolve.c @@ -0,0 +1,37 @@ +/* + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB + +#include "cnid_tdb.h" + +/* Return the did/name pair corresponding to a CNID. */ +char *cnid_tdb_resolve(struct _cnid_db *cdb, cnid_t * id, void *buffer, size_t len) +{ + struct _cnid_tdb_private *db; + TDB_DATA key, data; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) { + return NULL; + } + key.dptr = (unsigned char *)id; + key.dsize = sizeof(cnid_t); + data = tdb_fetch(db->tdb_cnid, key); + if (data.dptr) + { + if (data.dsize < len && data.dsize > sizeof(cnid_t)) { + memcpy(id, (char *)data.dptr + +CNID_DID_OFS, sizeof(cnid_t)); + strcpy(buffer, (char *)data.dptr + CNID_NAME_OFS); + free(data.dptr); + return buffer; + } + free(data.dptr); + } + return NULL; +} + +#endif diff --git a/libatalk/cnid/tdb/cnid_tdb_update.c b/libatalk/cnid/tdb/cnid_tdb_update.c new file mode 100644 index 0000000..9688d86 --- /dev/null +++ b/libatalk/cnid/tdb/cnid_tdb_update.c @@ -0,0 +1,108 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef CNID_BACKEND_TDB + +#include "cnid_tdb.h" +#include + +int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, + cnid_t did, const char *name, size_t len) +{ + struct _cnid_tdb_private *db; + TDB_DATA key, data, altdata; + + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) { + return -1; + } + + memset(&key, 0, sizeof(key)); + memset(&altdata, 0, sizeof(altdata)); + + + /* Get the old info. search by dev/ino */ + data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len); + data.dsize = CNID_HEADER_LEN + len + 1; + key.dptr = data.dptr +CNID_DEVINO_OFS; + key.dsize = CNID_DEVINO_LEN; + altdata = tdb_fetch(db->tdb_devino, key); + if (altdata.dptr) { + tdb_delete(db->tdb_devino, key); + + key.dptr = altdata.dptr; + key.dsize = sizeof(id); + + data = tdb_fetch(db->tdb_cnid, key); + tdb_delete(db->tdb_cnid, key); + free(altdata.dptr); + + if (data.dptr) { + key.dptr = (unsigned char *)data.dptr +CNID_DID_OFS; + key.dsize = data.dsize - CNID_DID_OFS; + tdb_delete(db->tdb_didname, key); + + free(data.dptr); + } + } + + /* search by did/name */ + data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len); + data.dsize = CNID_HEADER_LEN + len + 1; + key.dptr = (unsigned char *)data.dptr +CNID_DID_OFS; + key.dsize = data.dsize - CNID_DID_OFS; + altdata = tdb_fetch(db->tdb_didname, key); + if (altdata.dptr) { + tdb_delete(db->tdb_didname, key); + + key.dptr = altdata.dptr; + key.dsize = sizeof(id); + data = tdb_fetch(db->tdb_cnid, key); + tdb_delete(db->tdb_cnid, key); + free(altdata.dptr); + + if (data.dptr) { + key.dptr = data.dptr +CNID_DEVINO_OFS; + key.dsize = CNID_DEVINO_LEN; + tdb_delete(db->tdb_devino, key); + free(data.dptr); + } + } + + + /* Make a new entry. */ + data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len); + data.dsize = CNID_HEADER_LEN + len + 1; + memcpy(data.dptr, &id, sizeof(id)); + + /* Update the old CNID with the new info. */ + key.dptr = (unsigned char *) &id; + key.dsize = sizeof(id); + if (tdb_store(db->tdb_cnid, key, data, TDB_REPLACE)) { + goto update_err; + } + + /* Put in a new dev/ino mapping. */ + key.dptr = data.dptr +CNID_DEVINO_OFS; + key.dsize = CNID_DEVINO_LEN; + altdata.dptr = (unsigned char *) &id; + altdata.dsize = sizeof(id); + if (tdb_store(db->tdb_devino, key, altdata, TDB_REPLACE)) { + goto update_err; + } + /* put in a new did/name mapping. */ + key.dptr = (unsigned char *) data.dptr +CNID_DID_OFS; + key.dsize = data.dsize -CNID_DID_OFS; + + if (tdb_store(db->tdb_didname, key, altdata, TDB_REPLACE)) { + goto update_err; + } + + return 0; +update_err: + LOG(log_error, logtype_default, "cnid_update: Unable to update CNID %u", ntohl(id)); + return -1; + +} + +#endif diff --git a/libatalk/compat/Makefile.am b/libatalk/compat/Makefile.am new file mode 100644 index 0000000..810a6c6 --- /dev/null +++ b/libatalk/compat/Makefile.am @@ -0,0 +1,11 @@ +# Makefile.am for libatalk/compat/ + +noinst_LTLIBRARIES = libcompat.la + +libcompat_la_SOURCES = \ + misc.c \ + mktemp.c \ + getusershell.c \ + rquota_xdr.c \ + pselect.c \ + strlcpy.c diff --git a/libatalk/compat/Makefile.in b/libatalk/compat/Makefile.in new file mode 100644 index 0000000..247ebad --- /dev/null +++ b/libatalk/compat/Makefile.in @@ -0,0 +1,674 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/compat/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/compat +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcompat_la_LIBADD = +am_libcompat_la_OBJECTS = misc.lo mktemp.lo getusershell.lo \ + rquota_xdr.lo pselect.lo strlcpy.lo +libcompat_la_OBJECTS = $(am_libcompat_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcompat_la_SOURCES) +DIST_SOURCES = $(libcompat_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libcompat.la +libcompat_la_SOURCES = \ + misc.c \ + mktemp.c \ + getusershell.c \ + rquota_xdr.c \ + pselect.c \ + strlcpy.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/compat/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/compat/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcompat.la: $(libcompat_la_OBJECTS) $(libcompat_la_DEPENDENCIES) $(EXTRA_libcompat_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libcompat_la_OBJECTS) $(libcompat_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getusershell.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktemp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pselect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rquota_xdr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlcpy.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/compat/getusershell.c b/libatalk/compat/getusershell.c new file mode 100644 index 0000000..481978b --- /dev/null +++ b/libatalk/compat/getusershell.c @@ -0,0 +1,136 @@ +/* + * + * Copyright (c) 1985 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)getusershell.c 5.6 (Berkeley) 6/1/90"; +#endif /* LIBC_SCCS and not lint */ + +#if defined(ultrix) || defined(_IBMR2) || defined(NEED_GETUSERSHELL) + +#include +#include +#include +#include +#include + +#define SHELLS "/etc/shells" + +/* + * Do not add local shells here. They should be added in /etc/shells + */ +static char *okshells[] = { + "/bin/sh", "/bin/csh", +#ifdef _IBMR2 + "/bin/ksh", +#endif /* _IBMR2 */ + 0 +}; + +static char **shells, *strings; +static char **curshell = NULL; +extern char **initshells(); + +/* + * Get a list of shells from SHELLS, if it exists. + */ +char * +getusershell() +{ + char *ret; + + if (curshell == NULL) + curshell = initshells(); + ret = *curshell; + if (ret != NULL) + curshell++; + return (ret); +} + +endusershell() +{ + + if (shells != NULL) + free((char *)shells); + shells = NULL; + if (strings != NULL) + free(strings); + strings = NULL; + curshell = NULL; +} + +setusershell() +{ + + curshell = initshells(); +} + +static char ** +initshells() +{ + register char **sp, *cp; + register FILE *fp; + struct stat statb; + extern char *malloc(), *calloc(); + + if (shells != NULL) + free((char *)shells); + shells = NULL; + if (strings != NULL) + free(strings); + strings = NULL; + if ((fp = fopen(SHELLS, "r")) == (FILE *)0) + return(okshells); + if (fstat(fileno(fp), &statb) == -1) { + (void)fclose(fp); + return(okshells); + } + if ((strings = malloc((unsigned)statb.st_size)) == NULL) { + (void)fclose(fp); + return(okshells); + } + shells = (char **)calloc((unsigned)statb.st_size / 3, sizeof (char *)); + if (shells == NULL) { + (void)fclose(fp); + free(strings); + strings = NULL; + return(okshells); + } + sp = shells; + cp = strings; + while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { + while (*cp != '#' && *cp != '/' && *cp != '\0') + cp++; + if (*cp == '#' || *cp == '\0') + continue; + *sp++ = cp; + while (!isspace(*cp) && *cp != '#' && *cp != '\0') + cp++; + *cp++ = '\0'; + } + *sp = (char *)0; + (void)fclose(fp); + return (shells); +} + +# endif /* ultrix */ diff --git a/libatalk/compat/misc.c b/libatalk/compat/misc.c new file mode 100644 index 0000000..614c6f2 --- /dev/null +++ b/libatalk/compat/misc.c @@ -0,0 +1,77 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include + +#if !defined HAVE_DIRFD && defined SOLARIS +#include +int dirfd(DIR *dir) +{ + return dir->d_fd; +} +#endif + +#ifndef HAVE_STRNLEN +size_t strnlen(const char *s, size_t max) +{ + size_t len; + + for (len = 0; len < max; len++) { + if (s[len] == '\0') { + break; + } + } + return len; +} +#endif + +#ifndef HAVE_VASPRINTF +int vasprintf(char **ret, const char *fmt, va_list ap) +{ + int n, size = 64; + char *p, *np; + + if ((p = malloc(size)) == NULL) + return NULL; + + while (1) { + /* Try to print in the allocated space. */ + n = vsnprintf(p, size, fmt, ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) { + *ret = p; + return n; + } + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((np = realloc (p, size)) == NULL) { + free(p); + *ret = NULL; + return -1; + } else { + p = np; + } + } +} +#endif + +#ifndef HAVE_ASPRINTF +int asprintf(char **strp, const char *fmt, ...) +{ + va_list ap; + int len; + + va_start(ap, fmt); + len = vasprintf(strp, fmt, ap); + va_end(ap); + + return len; +} +#endif diff --git a/libatalk/compat/mktemp.c b/libatalk/compat/mktemp.c new file mode 100644 index 0000000..8faae19 --- /dev/null +++ b/libatalk/compat/mktemp.c @@ -0,0 +1,119 @@ +/* + * + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)mktemp.c 5.9 (Berkeley) 6/1/90"; +#endif /* LIBC_SCCS and not lint */ + +# ifdef ultrix + +#include +#include +#include +#include +#include +#include + +mkstemp(path) + char *path; +{ + int fd; + + return (_gettemp(path, &fd) ? fd : -1); +} + +char * +mktemp(path) + char *path; +{ + return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); +} + +static +_gettemp(path, doopen) + char *path; + register int *doopen; +{ + extern int errno; + register char *start, *trv; + struct stat sbuf; + u_int pid; + + pid = getpid(); + for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } + else if (stat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return(0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} + +# endif /* ultrix */ diff --git a/libatalk/compat/pselect.c b/libatalk/compat/pselect.c new file mode 100644 index 0000000..0f887e4 --- /dev/null +++ b/libatalk/compat/pselect.c @@ -0,0 +1,81 @@ +/* + * Copyright 2000 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. 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. + */ + +/* $FreeBSD: src/lib/libc/gen/pselect.c,v 1.6 2002/10/12 16:13:37 mike Exp $ */ +/* modified for OpenBSD by Masahito Yamaga (2010-02-02) */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if !defined(HAVE_PSELECT) || defined(__OpenBSD__) + +#include +#include +#include +#include + +/* + * Emulate the POSIX 1003.1g-2000 `pselect' interface. This is the + * same as the traditional BSD `select' function, except that it uses + * a timespec rather than a timeval, doesn't modify the timeout argument, + * and allows the user to specify a signal mask to apply during the select. + */ +int +pselect(int count, fd_set * restrict rfds, fd_set * restrict wfds, + fd_set * restrict efds, const struct timespec * restrict timo, + const sigset_t * restrict mask) +{ + sigset_t omask; + struct timeval tvtimo, *tvp; + int rv, sverrno; + + if (timo) { + TIMESPEC_TO_TIMEVAL(&tvtimo, timo); + tvp = &tvtimo; + } else + tvp = 0; + + if (mask != 0) { + rv = pthread_sigmask(SIG_SETMASK, mask, &omask); + if (rv != 0) + return rv; + } + + rv = select(count, rfds, wfds, efds, tvp); + if (mask != 0) { + sverrno = errno; + pthread_sigmask(SIG_SETMASK, &omask, (sigset_t *)0); + errno = sverrno; + } + + return rv; +} + +#endif /* not HAVE_PSELECT || __OpenBSD__ */ diff --git a/libatalk/compat/rquota_xdr.c b/libatalk/compat/rquota_xdr.c new file mode 100644 index 0000000..eb73c97 --- /dev/null +++ b/libatalk/compat/rquota_xdr.c @@ -0,0 +1,122 @@ +/* + * + * taken from the quota-1.55 used on linux. here's the bsd copyright: + * + * Copyright (c) 1980, 1990 Regents of the University of California. All + * rights reserved. + * + * This code is derived from software contributed to Berkeley by Robert Elz at + * The University of Melbourne. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include /* to get __GNU_LIBRARY__ */ + +/* list of machines that don't have these functions: + solaris + linux libc5 +*/ +#if defined(NEED_RQUOTA) || defined(SOLARIS) || (defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 6) + +#include +#include + +#ifndef u_int +#define u_int unsigned +#endif + +bool_t +xdr_getquota_args(xdrs, objp) + XDR *xdrs; + getquota_args *objp; +{ + if (!xdr_string(xdrs, &objp->gqa_pathp, RQ_PATHLEN)) { + return (FALSE); + } + if (!xdr_int(xdrs, &objp->gqa_uid)) { + return (FALSE); + } + return (TRUE); +} + + +bool_t +xdr_rquota(xdrs, objp) + XDR *xdrs; + rquota *objp; +{ + if (!xdr_int(xdrs, &objp->rq_bsize)) { + return (FALSE); + } + if (!xdr_bool(xdrs, &objp->rq_active)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_bhardlimit)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_bsoftlimit)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_curblocks)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_fhardlimit)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_fsoftlimit)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_curfiles)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_btimeleft)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->rq_ftimeleft)) { + return (FALSE); + } + return (TRUE); +} + + + + +bool_t +xdr_gqr_status(xdrs, objp) + XDR *xdrs; + gqr_status *objp; +{ + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + + +bool_t +xdr_getquota_rslt(xdrs, objp) + XDR *xdrs; + getquota_rslt *objp; +{ + if (!xdr_gqr_status(xdrs, &objp->status)) { + return (FALSE); + } + switch (objp->status) { + case Q_OK: + if (!xdr_rquota(xdrs, &objp->getquota_rslt_u.gqr_rquota)) { + return (FALSE); + } + break; + case Q_NOQUOTA: + break; + case Q_EPERM: + break; + default: + return (FALSE); + } + return (TRUE); +} +#endif diff --git a/libatalk/compat/strlcpy.c b/libatalk/compat/strlcpy.c new file mode 100644 index 0000000..314b039 --- /dev/null +++ b/libatalk/compat/strlcpy.c @@ -0,0 +1,74 @@ +/* + Copy from samba lib/replace.c + + Unix SMB/CIFS implementation. + replacement routines for broken systems + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + strlcpy strlcat functions. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifndef HAVE_STRLCPY +/* like strncpy but does not 0 fill the buffer and always null + terminates. bufsize is the size of the destination buffer */ + size_t strlcpy(char *d, const char *s, size_t bufsize) +{ + size_t len = strlen(s); + size_t ret = len; + + if (bufsize <= 0) + return 0; + + if (len >= bufsize) + len = bufsize-1; + + memcpy(d, s, len); + d[len] = 0; + return ret; +} +#endif + +#ifndef HAVE_STRLCAT +/* like strncat but does not 0 fill the buffer and always null + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ + size_t strlcat(char *d, const char *s, size_t bufsize) +{ + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1 >= bufsize) { + return 0; + } + if (len1+len2 >= bufsize) { + len2 = bufsize - (len1+1); + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } + return ret; +} +#endif diff --git a/libatalk/dsi/Makefile.am b/libatalk/dsi/Makefile.am new file mode 100644 index 0000000..34fa76e --- /dev/null +++ b/libatalk/dsi/Makefile.am @@ -0,0 +1,9 @@ +# Makefile.am for libatalk/dsi/ + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/sys + +LIBS = @LIBS@ + +noinst_LTLIBRARIES = libdsi.la + +libdsi_la_SOURCES = dsi_attn.c dsi_close.c dsi_cmdreply.c dsi_getsess.c dsi_getstat.c dsi_init.c dsi_opensess.c dsi_read.c dsi_tcp.c dsi_tickle.c dsi_write.c dsi_stream.c diff --git a/libatalk/dsi/Makefile.in b/libatalk/dsi/Makefile.in new file mode 100644 index 0000000..6500616 --- /dev/null +++ b/libatalk/dsi/Makefile.in @@ -0,0 +1,676 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/dsi/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/dsi +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdsi_la_LIBADD = +am_libdsi_la_OBJECTS = dsi_attn.lo dsi_close.lo dsi_cmdreply.lo \ + dsi_getsess.lo dsi_getstat.lo dsi_init.lo dsi_opensess.lo \ + dsi_read.lo dsi_tcp.lo dsi_tickle.lo dsi_write.lo \ + dsi_stream.lo +libdsi_la_OBJECTS = $(am_libdsi_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libdsi_la_SOURCES) +DIST_SOURCES = $(libdsi_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/sys +noinst_LTLIBRARIES = libdsi.la +libdsi_la_SOURCES = dsi_attn.c dsi_close.c dsi_cmdreply.c dsi_getsess.c dsi_getstat.c dsi_init.c dsi_opensess.c dsi_read.c dsi_tcp.c dsi_tickle.c dsi_write.c dsi_stream.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/dsi/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/dsi/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libdsi.la: $(libdsi_la_OBJECTS) $(libdsi_la_DEPENDENCIES) $(EXTRA_libdsi_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libdsi_la_OBJECTS) $(libdsi_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_attn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_close.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_cmdreply.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_getsess.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_getstat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_init.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_opensess.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_read.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_tcp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_tickle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsi_write.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/dsi/README b/libatalk/dsi/README new file mode 100644 index 0000000..a929097 --- /dev/null +++ b/libatalk/dsi/README @@ -0,0 +1,45 @@ +SIGNALS AND WRITES TO CLIENT: +because AFP/TCP uses a streaming protocol, we need to make sure that +writes to the client are atomic. notably, signal handlers which write +data can't interrupt data currently being written. in addition, some +functions get called from the signal handlers or can write partial +packets. we need to SIG_BLOCK/SIG_SETMASK those functions instead of +SIG_BLOCK/SIG_UNBLOCK'ing them. furthermore, certain functions which +write to the client can get called at any time. to avoid corruption, +we need to make sure that these functions DO NOT touch any common-use +buffers. + +signals that send data to the client and should block other signals +(afp_dsi.c): + SIGALRM (tickle handler) + SIGHUP (attention) + SIGTERM (attention) + +functions which need SIG_BLOCK/SIG_SETMASK: dsi_send, dsi_attention +functions which can use SIG_BLOCK/SIG_UNBLOCK: dsi_read + +functions which need their own buffers: dsi_attention, dsi_tickle + + +PERFORMANCE TWEAKING: +sending complete packets or the header and a partial packet to the +client should always be handled by proto_send. for dsi_tcp.c, +proto_send will coalesce the header and data by using writev. +in addition, appleshare sessions often involve +the sending and receiving of many small packets. as a consequence, i +use TCP_NODELAY to speed up the turnaround time. + +because dsi_read can send incomplete packets, proto_send should not +use the length parameter to specify the dsi_len field in the +header. instead, anything that uses proto_send needs to specify +dsi_len (in network byte order) before calling proto_send. the +dsi_send() macro already does this. + +functions that need to specify .dsi_len: dsi_readinit, dsi_cmdreply + +mmap doesn't actually help things that much, so i don't use it. + +to reduce the amount of tickles generated on a slow link, i actually +turn off SIGALRM for the duration of a "known" large file transfer +(i.e., dsi_read/write). + diff --git a/libatalk/dsi/dsi_attn.c b/libatalk/dsi/dsi_attn.c new file mode 100644 index 0000000..8075771 --- /dev/null +++ b/libatalk/dsi/dsi_attn.c @@ -0,0 +1,58 @@ +/* + * + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#include +#include + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif /* MIN */ + +/* send an attention. this may get called at any time, so we can't use + * DSI buffers to send one. + return 0 on error + + */ +int dsi_attention(DSI *dsi, AFPUserBytes flags) +{ + /* header + AFPUserBytes */ + char block[DSI_BLOCKSIZ + sizeof(AFPUserBytes)]; + uint32_t len, nlen; + uint16_t id; + + if (dsi->flags & DSI_SLEEPING) + return 1; + + if (dsi->in_write) { + return -1; + } + id = htons(dsi_serverID(dsi)); + flags = htons(flags); + len = MIN(sizeof(flags), dsi->attn_quantum); + nlen = htonl(len); + + memset(block, 0, sizeof(block)); + block[0] = DSIFL_REQUEST; /* sending a request */ + block[1] = DSIFUNC_ATTN; /* it's an attention */ + memcpy(block + 2, &id, sizeof(id)); + /* code = 0 */ + memcpy(block + 8, &nlen, sizeof(nlen)); + memcpy(block + 16, &flags, sizeof(flags)); + /* reserved = 0 */ + + /* send an attention */ + return dsi_stream_write(dsi, block, DSI_BLOCKSIZ + len, DSI_NOWAIT); +} diff --git a/libatalk/dsi/dsi_close.c b/libatalk/dsi/dsi_close.c new file mode 100644 index 0000000..199954f --- /dev/null +++ b/libatalk/dsi/dsi_close.c @@ -0,0 +1,30 @@ +/* + * + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include + +void dsi_close(DSI *dsi) +{ + /* server generated. need to set all the fields. */ + if (!(dsi->flags & DSI_SLEEPING) && !(dsi->flags & DSI_DISCONNECTED)) { + dsi->header.dsi_flags = DSIFL_REQUEST; + dsi->header.dsi_command = DSIFUNC_CLOSE; + dsi->header.dsi_requestID = htons(dsi_serverID(dsi)); + dsi->header.dsi_data.dsi_code = dsi->header.dsi_reserved = htonl(0); + dsi->cmdlen = 0; + dsi_send(dsi); + dsi->proto_close(dsi); + } + free(dsi); +} diff --git a/libatalk/dsi/dsi_cmdreply.c b/libatalk/dsi/dsi_cmdreply.c new file mode 100644 index 0000000..04d1708 --- /dev/null +++ b/libatalk/dsi/dsi_cmdreply.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include +#include + +/* this assumes that the reply follows right after the command, saving + * on a couple assignments. specifically, command, requestID, and + * reserved field are assumed to already be set. */ +int dsi_cmdreply(DSI *dsi, const int err) +{ + int ret; + + LOG(log_debug, logtype_dsi, "dsi_cmdreply(DSI ID: %u, len: %zd): START", + dsi->clientID, dsi->datalen); + + dsi->header.dsi_flags = DSIFL_REPLY; + dsi->header.dsi_len = htonl(dsi->datalen); + dsi->header.dsi_data.dsi_code = htonl(err); + + ret = dsi_stream_send(dsi, dsi->data, dsi->datalen); + + LOG(log_debug, logtype_dsi, "dsi_cmdreply(DSI ID: %u, len: %zd): END", + dsi->clientID, dsi->datalen); + + return ret; +} diff --git a/libatalk/dsi/dsi_getsess.c b/libatalk/dsi/dsi_getsess.c new file mode 100644 index 0000000..89af152 --- /dev/null +++ b/libatalk/dsi/dsi_getsess.c @@ -0,0 +1,125 @@ +/* + * + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +/*! + * Start a DSI session, fork an afpd process + * + * @param childp (w) after fork: parent return pointer to child, child returns NULL + * @returns 0 on sucess, any other value denotes failure + */ +int dsi_getsession(DSI *dsi, server_child_t *serv_children, int tickleval, afp_child_t **childp) +{ + pid_t pid; + int ipc_fds[2]; + afp_child_t *child; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) { + LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); + return -1; + } + + if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) { + LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno)); + return -1; + } + + switch (pid = dsi->proto_open(dsi)) { /* in libatalk/dsi/dsi_tcp.c */ + case -1: + /* if we fail, just return. it might work later */ + LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); + return -1; + + case 0: /* child. mostly handled below. */ + break; + + default: /* parent */ + /* using SIGKILL is hokey, but the child might not have + * re-established its signal handler for SIGTERM yet. */ + close(ipc_fds[1]); + if ((child = server_child_add(serv_children, pid, ipc_fds[0])) == NULL) { + LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); + close(ipc_fds[0]); + dsi->header.dsi_flags = DSIFL_REPLY; + dsi->header.dsi_data.dsi_code = htonl(DSIERR_SERVBUSY); + dsi_send(dsi); + dsi->header.dsi_data.dsi_code = DSIERR_OK; + kill(pid, SIGKILL); + } + dsi->proto_close(dsi); + *childp = child; + return 0; + } + + /* Save number of existing and maximum connections */ + dsi->AFPobj->cnx_cnt = serv_children->servch_count; + dsi->AFPobj->cnx_max = serv_children->servch_nsessions; + + /* get rid of some stuff */ + dsi->AFPobj->ipc_fd = ipc_fds[1]; + close(ipc_fds[0]); + close(dsi->serversock); + dsi->serversock = -1; + server_child_free(serv_children); + + switch (dsi->header.dsi_command) { + case DSIFUNC_STAT: /* send off status and return */ + { + /* OpenTransport 1.1.2 bug workaround: + * + * OT code doesn't currently handle close sockets well. urk. + * the workaround: wait for the client to close its + * side. timeouts prevent indefinite resource use. + */ + + static struct timeval timeout = {120, 0}; + fd_set readfds; + + dsi_getstatus(dsi); + + FD_ZERO(&readfds); + FD_SET(dsi->socket, &readfds); + free(dsi); + select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); + exit(0); + } + break; + + case DSIFUNC_OPEN: /* setup session */ + /* set up the tickle timer */ + dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval; + dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0; + dsi_opensession(dsi); + *childp = NULL; + return 0; + + default: /* just close */ + LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command); + dsi->proto_close(dsi); + exit(EXITERR_CLNT); + } +} diff --git a/libatalk/dsi/dsi_getstat.c b/libatalk/dsi/dsi_getstat.c new file mode 100644 index 0000000..4be9b80 --- /dev/null +++ b/libatalk/dsi/dsi_getstat.c @@ -0,0 +1,28 @@ +/* + * + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#include + +/* return the status and then delete the connection. most of the + * fields are already set. */ +void dsi_getstatus(DSI *dsi) +{ + dsi->header.dsi_flags = DSIFL_REPLY; + /*dsi->header.dsi_command = DSIFUNC_STAT;*/ + dsi->header.dsi_data.dsi_code = dsi->header.dsi_reserved = 0; + + memcpy(dsi->commands, dsi->status, dsi->statuslen); + dsi->cmdlen = dsi->statuslen; + dsi_send(dsi); +} diff --git a/libatalk/dsi/dsi_init.c b/libatalk/dsi/dsi_init.c new file mode 100644 index 0000000..824d31f --- /dev/null +++ b/libatalk/dsi/dsi_init.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, Frank Lahm + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +DSI *dsi_init(AFPObj *obj, const char *hostname, const char *address, const char *port) +{ + DSI *dsi; + + if ((dsi = (DSI *)calloc(1, sizeof(DSI))) == NULL) + return NULL; + + dsi->attn_quantum = DSI_DEFQUANT; + dsi->server_quantum = obj->options.server_quantum; + dsi->dsireadbuf = obj->options.dsireadbuf; + + /* currently the only transport protocol that exists for dsi */ + if (dsi_tcp_init(dsi, hostname, address, port) != 0) { + free(dsi); + dsi = NULL; + } + + return dsi; +} diff --git a/libatalk/dsi/dsi_opensess.c b/libatalk/dsi/dsi_opensess.c new file mode 100644 index 0000000..2945f9b --- /dev/null +++ b/libatalk/dsi/dsi_opensess.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include +#include +#include + +/* OpenSession. set up the connection */ +void dsi_opensession(DSI *dsi) +{ + uint32_t i = 0; /* this serves double duty. it must be 4-bytes long */ + int offs; + + if (setnonblock(dsi->socket, 1) < 0) { + LOG(log_error, logtype_dsi, "dsi_opensession: setnonblock: %s", strerror(errno)); + AFP_PANIC("setnonblock error"); + } + + /* parse options */ + while (i < dsi->cmdlen) { + switch (dsi->commands[i++]) { + case DSIOPT_ATTNQUANT: + memcpy(&dsi->attn_quantum, dsi->commands + i + 1, dsi->commands[i]); + dsi->attn_quantum = ntohl(dsi->attn_quantum); + + case DSIOPT_SERVQUANT: /* just ignore these */ + default: + i += dsi->commands[i] + 1; /* forward past length tag + length */ + break; + } + } + + /* let the client know the server quantum. we don't use the + * max server quantum due to a bug in appleshare client 3.8.6. */ + dsi->header.dsi_flags = DSIFL_REPLY; + dsi->header.dsi_data.dsi_code = 0; + /* dsi->header.dsi_command = DSIFUNC_OPEN;*/ + + dsi->cmdlen = 2 * (2 + sizeof(i)); /* length of data. dsi_send uses it. */ + + /* DSI Option Server Request Quantum */ + dsi->commands[0] = DSIOPT_SERVQUANT; + dsi->commands[1] = sizeof(i); + i = htonl(( dsi->server_quantum < DSI_SERVQUANT_MIN || + dsi->server_quantum > DSI_SERVQUANT_MAX ) ? + DSI_SERVQUANT_DEF : dsi->server_quantum); + memcpy(dsi->commands + 2, &i, sizeof(i)); + + /* AFP replaycache size option */ + offs = 2 + sizeof(i); + dsi->commands[offs] = DSIOPT_REPLCSIZE; + dsi->commands[offs+1] = sizeof(i); + i = htonl(REPLAYCACHE_SIZE); + memcpy(dsi->commands + offs + 2, &i, sizeof(i)); + dsi_send(dsi); +} diff --git a/libatalk/dsi/dsi_read.c b/libatalk/dsi/dsi_read.c new file mode 100644 index 0000000..31ee3bd --- /dev/null +++ b/libatalk/dsi/dsi_read.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* streaming i/o for afp_read. this is all from the perspective of the + * client. it basically does the reverse of dsi_write. on first entry, + * it will send off the header plus whatever is in its command + * buffer. it returns the amount of stuff still to be read + * (constrained by the buffer size). */ +ssize_t dsi_readinit(DSI *dsi, void *buf, const size_t buflen, const size_t size, const int err) +{ + LOG(log_maxdebug, logtype_dsi, "dsi_readinit: sending %zd bytes from buffer, total size: %zd", + buflen, size); + + dsi->flags |= DSI_NOREPLY; /* we will handle our own replies */ + dsi->header.dsi_flags = DSIFL_REPLY; + dsi->header.dsi_len = htonl(size); + dsi->header.dsi_data.dsi_code = htonl(err); + + dsi->in_write++; + if (dsi_stream_send(dsi, buf, buflen)) { + dsi->datasize = size - buflen; + LOG(log_maxdebug, logtype_dsi, "dsi_readinit: remaining data for sendfile: %zd", dsi->datasize); + return MIN(dsi->datasize, buflen); + } + + return -1; /* error */ +} + +void dsi_readdone(DSI *dsi) +{ + dsi->in_write--; +} + +/* send off the data */ +ssize_t dsi_read(DSI *dsi, void *buf, const size_t buflen) +{ + size_t len; + + len = dsi_stream_write(dsi, buf, buflen, 0); + + if (len == buflen) { + dsi->datasize -= len; + return MIN(dsi->datasize, buflen); + } + + return -1; +} diff --git a/libatalk/dsi/dsi_stream.c b/libatalk/dsi/dsi_stream.c new file mode 100644 index 0000000..c8f859c --- /dev/null +++ b/libatalk/dsi/dsi_stream.c @@ -0,0 +1,640 @@ +/* + * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu) + * Copyright (c) 2010,2011,2012 Frank Lahm +> * All rights reserved. See COPYRIGHT. + * + * this file provides the following functions: + * dsi_stream_write: just write a bunch of bytes. + * dsi_stream_read: just read a bunch of bytes. + * dsi_stream_send: send a DSI header + data. + * dsi_stream_receive: read a DSI header + data. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SENDFILEV +#include +#endif + +#include +#include +#include + +#ifndef MSG_MORE +#define MSG_MORE 0x8000 +#endif + +#ifndef MSG_DONTWAIT +#define MSG_DONTWAIT 0x40 +#endif + +/* Pack a DSI header in wire format */ +static void dsi_header_pack_reply(const DSI *dsi, char *buf) +{ + buf[0] = dsi->header.dsi_flags; + buf[1] = dsi->header.dsi_command; + memcpy(buf + 2, &dsi->header.dsi_requestID, sizeof(dsi->header.dsi_requestID)); + memcpy(buf + 4, &dsi->header.dsi_data.dsi_code, sizeof(dsi->header.dsi_data.dsi_code)); + memcpy(buf + 8, &dsi->header.dsi_len, sizeof(dsi->header.dsi_len)); + memcpy(buf + 12, &dsi->header.dsi_reserved, sizeof(dsi->header.dsi_reserved)); +} + +/* + * afpd is sleeping too much while trying to send something. + * May be there's no reader or the reader is also sleeping in write, + * look if there's some data for us to read, hopefully it will wake up + * the reader so we can write again. + * + * @returns 0 when is possible to send again, -1 on error + */ +static int dsi_peek(DSI *dsi) +{ + static int warned = 0; + fd_set readfds, writefds; + int len; + int maxfd; + int ret; + + LOG(log_debug, logtype_dsi, "dsi_peek"); + + maxfd = dsi->socket + 1; + + while (1) { + if (dsi->socket == -1) + /* eg dsi_disconnect() might have disconnected us */ + return -1; + FD_ZERO(&readfds); + FD_ZERO(&writefds); + + if (dsi->eof < dsi->end) { + /* space in read buffer */ + FD_SET( dsi->socket, &readfds); + } else { + if (!warned) { + warned = 1; + LOG(log_note, logtype_dsi, "dsi_peek: readahead buffer is full, possibly increase -dsireadbuf option"); + LOG(log_note, logtype_dsi, "dsi_peek: dsireadbuf: %d, DSI quantum: %d, effective buffer size: %d", + dsi->dsireadbuf, + dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF, + dsi->end - dsi->buffer); + } + } + + FD_SET( dsi->socket, &writefds); + + /* No timeout: if there's nothing to read nor nothing to write, + * we've got nothing to do at all */ + if ((ret = select( maxfd, &readfds, &writefds, NULL, NULL)) <= 0) { + if (ret == -1 && errno == EINTR) + /* we might have been interrupted by out timer, so restart select */ + continue; + /* give up */ + LOG(log_error, logtype_dsi, "dsi_peek: unexpected select return: %d %s", + ret, ret < 0 ? strerror(errno) : ""); + return -1; + } + + if (FD_ISSET(dsi->socket, &writefds)) { + /* we can write again */ + LOG(log_debug, logtype_dsi, "dsi_peek: can write again"); + break; + } + + /* Check if there's sth to read, hopefully reading that will unblock the client */ + if (FD_ISSET(dsi->socket, &readfds)) { + len = dsi->end - dsi->eof; /* it's ensured above that there's space */ + + if ((len = recv(dsi->socket, dsi->eof, len, 0)) <= 0) { + if (len == 0) { + LOG(log_error, logtype_dsi, "dsi_peek: EOF"); + return -1; + } + LOG(log_error, logtype_dsi, "dsi_peek: read: %s", strerror(errno)); + if (errno == EAGAIN) + continue; + return -1; + } + LOG(log_debug, logtype_dsi, "dsi_peek: read %d bytes", len); + + dsi->eof += len; + } + } + + return 0; +} + +/* + * Return all bytes up to count from dsi->buffer if there are any buffered there + */ +static size_t from_buf(DSI *dsi, uint8_t *buf, size_t count) +{ + size_t nbe = 0; + + if (dsi->buffer == NULL) + /* afpd master has no DSI buffering */ + return 0; + + LOG(log_maxdebug, logtype_dsi, "from_buf: %u bytes", count); + + nbe = dsi->eof - dsi->start; + + if (nbe > 0) { + nbe = MIN((size_t)nbe, count); + memcpy(buf, dsi->start, nbe); + dsi->start += nbe; + + if (dsi->eof == dsi->start) + dsi->start = dsi->eof = dsi->buffer; + } + + LOG(log_debug, logtype_dsi, "from_buf(read: %u, unread:%u , space left: %u): returning %u", + dsi->start - dsi->buffer, dsi->eof - dsi->start, dsi->end - dsi->eof, nbe); + + return nbe; +} + +/* + * Get bytes from buffer dsi->buffer or read from socket + * + * 1. Check if there are bytes in the the dsi->buffer buffer. + * 2. Return bytes from (1) if yes. + * Note: this may return fewer bytes then requested in count !! + * 3. If the buffer was empty, read from the socket. + */ +static ssize_t buf_read(DSI *dsi, uint8_t *buf, size_t count) +{ + ssize_t len; + + LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes)", count); + + if (!count) + return 0; + + len = from_buf(dsi, buf, count); /* 1. */ + if (len) + return len; /* 2. */ + + len = readt(dsi->socket, buf, count, 0, 0); /* 3. */ + + LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes): got: %d", count, len); + + return len; +} + +/* + * Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads + * this tries to read larger chunks (8192 bytes) into a buffer. + */ +static size_t dsi_buffered_stream_read(DSI *dsi, uint8_t *data, const size_t length) +{ + size_t len; + size_t buflen; + + LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length); + + len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */ + dsi->read_count += len; + if (len == length) { /* got enough bytes from there ? */ + return len; /* yes */ + } + + /* fill the buffer with 8192 bytes or until buffer is full */ + buflen = MIN(8192, dsi->end - dsi->eof); + if (buflen > 0) { + ssize_t ret; + ret = recv(dsi->socket, dsi->eof, buflen, 0); + if (ret > 0) + dsi->eof += ret; + } + + /* now get the remaining data */ + if ((buflen = dsi_stream_read(dsi, data + len, length - len)) != length - len) + return 0; + len += buflen; + + return len; +} + +/* --------------------------------------- +*/ +static void block_sig(DSI *dsi) +{ + dsi->in_write++; +} + +/* --------------------------------------- +*/ +static void unblock_sig(DSI *dsi) +{ + dsi->in_write--; +} + +/********************************************************************************* + * Public functions + *********************************************************************************/ + +/*! + * Communication error with the client, enter disconnected state + * + * 1. close the socket + * 2. set the DSI_DISCONNECTED flag, remove possible sleep flags + * + * @returns 0 if successfully entered disconnected state + * -1 if ppid is 1 which means afpd master died + * or euid == 0 ie where still running as root (unauthenticated session) + */ +int dsi_disconnect(DSI *dsi) +{ + LOG(log_note, logtype_dsi, "dsi_disconnect: entering disconnected state"); + dsi->proto_close(dsi); /* 1 */ + dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP); /* 2 */ + dsi->flags |= DSI_DISCONNECTED; + if (geteuid() == 0) + return -1; + return 0; +} + +/* ------------------------------ + * write raw data. return actual bytes read. checks against EINTR + * aren't necessary if all of the signals have SA_RESTART + * specified. */ +ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode) +{ + size_t written; + ssize_t len; + unsigned int flags; + + dsi->in_write++; + written = 0; + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): START", length); + + if (dsi->flags & DSI_DISCONNECTED) + return -1; + + if (mode & DSI_MSG_MORE) + flags = MSG_MORE; + else + flags = 0; + + while (written < length) { + len = send(dsi->socket, (uint8_t *) data + written, length - written, flags); + if (len >= 0) { + written += len; + continue; + } + + if (errno == EINTR) + continue; + + if (errno == EAGAIN || errno == EWOULDBLOCK) { + LOG(log_debug, logtype_dsi, "dsi_stream_write: send: %s", strerror(errno)); + + if (mode == DSI_NOWAIT && written == 0) { + /* DSI_NOWAIT is used by attention give up in this case. */ + written = -1; + goto exit; + } + + /* Try to read sth. in order to break up possible deadlock */ + if (dsi_peek(dsi) != 0) { + written = -1; + goto exit; + } + /* Now try writing again */ + continue; + } + + LOG(log_error, logtype_dsi, "dsi_stream_write: %s", strerror(errno)); + written = -1; + goto exit; + } + + dsi->write_count += written; + LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): END", length); + +exit: + dsi->in_write--; + return written; +} + +/* --------------------------------- +*/ +#ifdef WITH_SENDFILE +ssize_t dsi_stream_read_file(DSI *dsi, const int fromfd, off_t offset, const size_t length, const int err) +{ + int ret = 0; + size_t written = 0; + size_t total = length; + ssize_t len; + off_t pos = offset; + char block[DSI_BLOCKSIZ]; +#ifdef HAVE_SENDFILEV + int sfvcnt; + struct sendfilevec vec[2]; + ssize_t nwritten; +#elif defined(FREEBSD) + ssize_t nwritten; + void *hdrp; + struct sf_hdtr hdr; + struct iovec iovec; + hdr.headers = &iovec; + hdr.hdr_cnt = 1; + hdr.trailers = NULL; + hdr.trl_cnt = 0; + hdrp = &hdr; +#endif + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file(off: %jd, len: %zu)", (intmax_t)offset, length); + + if (dsi->flags & DSI_DISCONNECTED) + return -1; + + dsi->in_write++; + + dsi->flags |= DSI_NOREPLY; + dsi->header.dsi_flags = DSIFL_REPLY; + dsi->header.dsi_len = htonl(length); + dsi->header.dsi_data.dsi_code = htonl(err); + dsi_header_pack_reply(dsi, block); + +#ifdef HAVE_SENDFILEV + total += DSI_BLOCKSIZ; + sfvcnt = 2; + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + /* Cast to unsigned long to prevent sign extension of the + * pointer value for the LFS case; see Apache PR 39463. */ + vec[0].sfv_off = (unsigned long)block; + vec[0].sfv_len = DSI_BLOCKSIZ; + vec[1].sfv_fd = fromfd; + vec[1].sfv_flag = 0; + vec[1].sfv_off = offset; + vec[1].sfv_len = length; +#elif defined(FREEBSD) + iovec.iov_base = block; + iovec.iov_len = DSI_BLOCKSIZ; +#else + dsi_stream_write(dsi, block, sizeof(block), DSI_MSG_MORE); +#endif + + while (written < total) { +#ifdef HAVE_SENDFILEV + nwritten = 0; + len = sendfilev(dsi->socket, vec, sfvcnt, &nwritten); +#elif defined(FREEBSD) + len = sendfile(fromfd, dsi->socket, pos, total - written, hdrp, &nwritten, 0); + if (len == 0) + len = nwritten; +#else + len = sys_sendfile(dsi->socket, fromfd, &pos, total - written); +#endif + if (len < 0) { + switch (errno) { + case EINTR: + case EAGAIN: + len = 0; +#if defined(HAVE_SENDFILEV) || defined(FREEBSD) + len = (size_t)nwritten; +#elif defined(SOLARIS) + if (pos > offset) { + /* we actually have sent sth., adjust counters and keep trying */ + len = pos - offset; + offset = pos; + } +#endif /* HAVE_SENDFILEV */ + + if (dsi_peek(dsi) != 0) { + ret = -1; + goto exit; + } + break; + default: + LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno)); + ret = -1; + goto exit; + } + } else if (len == 0) { + /* afpd is going to exit */ + ret = -1; + goto exit; + } +#ifdef HAVE_SENDFILEV + if (sfvcnt == 2 && len >= vec[0].sfv_len) { + vec[1].sfv_off += len - vec[0].sfv_len; + vec[1].sfv_len -= len - vec[0].sfv_len; + + vec[0] = vec[1]; + sfvcnt = 1; + } else { + vec[0].sfv_off += len; + vec[0].sfv_len -= len; + } +#elif defined(FREEBSD) + if (hdrp) { + if (len >= iovec.iov_len) { + hdrp = NULL; + len -= iovec.iov_len; /* len now contains how much sendfile() actually sent from the file */ + } else { + iovec.iov_len -= len; + iovec.iov_base += len; + len = 0; + } + } + pos += len; +#endif /* HAVE_SENDFILEV */ + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: wrote: %zd", len); + written += len; + } +#ifdef HAVE_SENDFILEV + written -= DSI_BLOCKSIZ; +#endif + dsi->write_count += written; + +exit: + dsi->in_write--; + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: written: %zd", written); + if (ret != 0) + return -1; + return written; +} +#endif + + +/* + * Essentially a loop around buf_read() to ensure "length" bytes are read + * from dsi->buffer and/or the socket. + * + * @returns length on success, some value smaller then length indicates an error + */ +size_t dsi_stream_read(DSI *dsi, void *data, const size_t length) +{ + size_t stored; + ssize_t len; + + if (dsi->flags & DSI_DISCONNECTED) + return 0; + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes)", length); + + stored = 0; + while (stored < length) { + len = buf_read(dsi, (uint8_t *) data + stored, length - stored); + if (len == -1 && (errno == EINTR || errno == EAGAIN)) { + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read: select read loop"); + continue; + } else if (len > 0) { + stored += len; + } else { /* eof or error */ + /* don't log EOF error if it's just after connect (OSX 10.3 probe) */ + if (len || stored || dsi->read_count) { + if (! (dsi->flags & DSI_DISCONNECTED)) { + LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s", + len, (len < 0) ? strerror(errno) : "unexpected EOF"); + } + return 0; + } + break; + } + } + + dsi->read_count += stored; + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes): got: %u", length, stored); + return stored; +} + +/* --------------------------------------- + * write data. 0 on failure. this assumes that dsi_len will never + * cause an overflow in the data buffer. + */ +int dsi_stream_send(DSI *dsi, void *buf, size_t length) +{ + char block[DSI_BLOCKSIZ]; + struct iovec iov[2]; + int iovecs = 2; + size_t towrite; + ssize_t len; + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): START", length); + + if (dsi->flags & DSI_DISCONNECTED) + return 0; + + dsi_header_pack_reply(dsi, block); + + if (!length) { /* just write the header */ + LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): DSI header, no data", sizeof(block)); + length = (dsi_stream_write(dsi, block, sizeof(block), 0) == sizeof(block)); + return length; /* really 0 on failure, 1 on success */ + } + + /* block signals */ + block_sig(dsi); + iov[0].iov_base = block; + iov[0].iov_len = sizeof(block); + iov[1].iov_base = buf; + iov[1].iov_len = length; + + towrite = sizeof(block) + length; + dsi->write_count += towrite; + while (towrite > 0) { + if (((len = writev(dsi->socket, iov, iovecs)) == -1 && errno == EINTR) || (len == 0)) + continue; + + if ((size_t)len == towrite) /* wrote everything out */ + break; + else if (len < 0) { /* error */ + if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (dsi_peek(dsi) == 0) { + continue; + } + } + LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno)); + unblock_sig(dsi); + return 0; + } + + towrite -= len; + if (towrite > length) { /* skip part of header */ + iov[0].iov_base = (char *) iov[0].iov_base + len; + iov[0].iov_len -= len; + } else { /* skip to data */ + if (iovecs == 2) { + iovecs = 1; + len -= iov[0].iov_len; + iov[0] = iov[1]; + } + iov[0].iov_base = (char *) iov[0].iov_base + len; + iov[0].iov_len -= len; + } + } + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): END", length); + + unblock_sig(dsi); + return 1; +} + + +/*! + * Read DSI command and data + * + * @param dsi (rw) DSI handle + * + * @return DSI function on success, 0 on failure + */ +int dsi_stream_receive(DSI *dsi) +{ + char block[DSI_BLOCKSIZ]; + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: START"); + + if (dsi->flags & DSI_DISCONNECTED) + return 0; + + /* read in the header */ + if (dsi_buffered_stream_read(dsi, (uint8_t *)block, sizeof(block)) != sizeof(block)) + return 0; + + dsi->header.dsi_flags = block[0]; + dsi->header.dsi_command = block[1]; + + if (dsi->header.dsi_command == 0) + return 0; + + memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID)); + memcpy(&dsi->header.dsi_data.dsi_doff, block + 4, sizeof(dsi->header.dsi_data.dsi_doff)); + dsi->header.dsi_data.dsi_doff = htonl(dsi->header.dsi_data.dsi_doff); + memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len)); + + memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved)); + dsi->clientID = ntohs(dsi->header.dsi_requestID); + + /* make sure we don't over-write our buffers. */ + dsi->cmdlen = MIN(ntohl(dsi->header.dsi_len), dsi->server_quantum); + + /* Receiving DSIWrite data is done in AFP function, not here */ + if (dsi->header.dsi_data.dsi_doff) { + LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: write request"); + dsi->cmdlen = dsi->header.dsi_data.dsi_doff; + } + + if (dsi_stream_read(dsi, dsi->commands, dsi->cmdlen) != dsi->cmdlen) + return 0; + + LOG(log_debug, logtype_dsi, "dsi_stream_receive: DSI cmdlen: %zd", dsi->cmdlen); + + return block[1]; +} diff --git a/libatalk/dsi/dsi_tcp.c b/libatalk/dsi/dsi_tcp.c new file mode 100644 index 0000000..24fde97 --- /dev/null +++ b/libatalk/dsi/dsi_tcp.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 1997, 1998 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + * + * this provides both proto_open() and proto_close() to account for + * protocol specific initialization and shutdown procedures. all the + * read/write stuff is done in dsi_stream.c. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#ifdef HAVE_NETDB_H +#include +#endif /* HAVE_NETDB_H */ +#include +#include +#include +#include + +#include +#ifdef TRU64 +#include +#include +#endif /* TRU64 */ +#include +#include +#include +#include + +#include +#include + +#ifdef __svr4__ +#include +#endif /* __svr4__ */ + +#ifdef TCPWRAP +#include +int allow_severity = log_info; +int deny_severity = log_warning; +#endif /* TCPWRAP */ + +#include +#include +#include +#include + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#ifndef DSI_TCPMAXPEND +#define DSI_TCPMAXPEND 20 /* max # of pending connections */ +#endif /* DSI_TCPMAXPEND */ + +#ifndef DSI_TCPTIMEOUT +#define DSI_TCPTIMEOUT 120 /* timeout in seconds for connections */ +#endif /* ! DSI_TCPTIMEOUT */ + + +/* FIXME/SOCKLEN_T: socklen_t is a unix98 feature. */ +#ifndef SOCKLEN_T +#define SOCKLEN_T unsigned int +#endif /* ! SOCKLEN_T */ + +static void dsi_tcp_close(DSI *dsi) +{ + if (dsi->socket == -1) + return; + + close(dsi->socket); + dsi->socket = -1; +} + +/* alarm handler for tcp_open */ +static void timeout_handler(int sig _U_) +{ + LOG(log_error, logtype_dsi, "dsi_tcp_open: connection timed out"); + exit(EXITERR_CLNT); +} + +/*! + * Allocate DSI read buffer and read-ahead buffer + */ +static void dsi_init_buffer(DSI *dsi) +{ + if ((dsi->commands = malloc(dsi->server_quantum)) == NULL) { + LOG(log_error, logtype_dsi, "dsi_init_buffer: OOM"); + AFP_PANIC("OOM in dsi_init_buffer"); + } + + /* dsi_peek() read ahead buffer, default is 12 * 300k = 3,6 MB (Apr 2011) */ + if ((dsi->buffer = malloc(dsi->dsireadbuf * dsi->server_quantum)) == NULL) { + LOG(log_error, logtype_dsi, "dsi_init_buffer: OOM"); + AFP_PANIC("OOM in dsi_init_buffer"); + } + dsi->start = dsi->buffer; + dsi->eof = dsi->buffer; + dsi->end = dsi->buffer + (dsi->dsireadbuf * dsi->server_quantum); +} + +/*! + * Free any allocated ressources of the master afpd DSI objects and close server socket + */ +void dsi_free(DSI *dsi) +{ + close(dsi->serversock); + dsi->serversock = -1; + + free(dsi->commands); + dsi->commands = NULL; + + free(dsi->buffer); + dsi->buffer = NULL; + +#ifdef USE_ZEROCONF + free(dsi->bonjourname); + dsi->bonjourname = NULL; +#endif +} + +static struct itimerval itimer; +/* accept the socket and do a little sanity checking */ +static pid_t dsi_tcp_open(DSI *dsi) +{ + pid_t pid; + SOCKLEN_T len; + + len = sizeof(dsi->client); + dsi->socket = accept(dsi->serversock, (struct sockaddr *) &dsi->client, &len); + +#ifdef TCPWRAP + { + struct request_info req; + request_init(&req, RQ_DAEMON, "afpd", RQ_FILE, dsi->socket, NULL); + fromhost(&req); + if (!hosts_access(&req)) { + LOG(deny_severity, logtype_dsi, "refused connect from %s", eval_client(&req)); + close(dsi->socket); + errno = ECONNREFUSED; + dsi->socket = -1; + } + } +#endif /* TCPWRAP */ + + if (dsi->socket < 0) + return -1; + + getitimer(ITIMER_PROF, &itimer); + if (0 == (pid = fork()) ) { /* child */ + static struct itimerval timer = {{0, 0}, {DSI_TCPTIMEOUT, 0}}; + struct sigaction newact, oldact; + uint8_t block[DSI_BLOCKSIZ]; + size_t stored; + + /* reset signals */ + server_reset_signal(); + +#ifndef DEBUGGING + /* install an alarm to deal with non-responsive connections */ + newact.sa_handler = timeout_handler; + sigemptyset(&newact.sa_mask); + newact.sa_flags = 0; + sigemptyset(&oldact.sa_mask); + oldact.sa_flags = 0; + setitimer(ITIMER_PROF, &itimer, NULL); + + if ((sigaction(SIGALRM, &newact, &oldact) < 0) || + (setitimer(ITIMER_REAL, &timer, NULL) < 0)) { + LOG(log_error, logtype_dsi, "dsi_tcp_open: %s", strerror(errno)); + exit(EXITERR_SYS); + } +#endif + + dsi_init_buffer(dsi); + + /* read in commands. this is similar to dsi_receive except + * for the fact that we do some sanity checking to prevent + * delinquent connections from causing mischief. */ + + /* read in the first two bytes */ + len = dsi_stream_read(dsi, block, 2); + if (!len ) { + /* connection already closed, don't log it (normal OSX 10.3 behaviour) */ + exit(EXITERR_CLOSED); + } + if (len < 2 || (block[0] > DSIFL_MAX) || (block[1] > DSIFUNC_MAX)) { + LOG(log_error, logtype_dsi, "dsi_tcp_open: invalid header"); + exit(EXITERR_CLNT); + } + + /* read in the rest of the header */ + stored = 2; + while (stored < DSI_BLOCKSIZ) { + len = dsi_stream_read(dsi, block + stored, sizeof(block) - stored); + if (len > 0) + stored += len; + else { + LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno)); + exit(EXITERR_CLNT); + } + } + + dsi->header.dsi_flags = block[0]; + dsi->header.dsi_command = block[1]; + memcpy(&dsi->header.dsi_requestID, block + 2, + sizeof(dsi->header.dsi_requestID)); + memcpy(&dsi->header.dsi_data.dsi_code, block + 4, sizeof(dsi->header.dsi_data.dsi_code)); + memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len)); + memcpy(&dsi->header.dsi_reserved, block + 12, + sizeof(dsi->header.dsi_reserved)); + dsi->clientID = ntohs(dsi->header.dsi_requestID); + + /* make sure we don't over-write our buffers. */ + dsi->cmdlen = min(ntohl(dsi->header.dsi_len), dsi->server_quantum); + + stored = 0; + while (stored < dsi->cmdlen) { + len = dsi_stream_read(dsi, dsi->commands + stored, dsi->cmdlen - stored); + if (len > 0) + stored += len; + else { + LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno)); + exit(EXITERR_CLNT); + } + } + + /* stop timer and restore signal handler */ +#ifndef DEBUGGING + memset(&timer, 0, sizeof(timer)); + setitimer(ITIMER_REAL, &timer, NULL); + sigaction(SIGALRM, &oldact, NULL); +#endif + + LOG(log_info, logtype_dsi, "AFP/TCP session from %s:%u", + getip_string((struct sockaddr *)&dsi->client), + getip_port((struct sockaddr *)&dsi->client)); + } + + /* send back our pid */ + return pid; +} + +/* get it from the interface list */ +#ifndef IFF_SLAVE +#define IFF_SLAVE 0 +#endif + +static void guess_interface(DSI *dsi, const char *hostname, const char *port) +{ + int fd; + char **start, **list; + struct ifreq ifr; + struct sockaddr_in *sa = (struct sockaddr_in *)&dsi->server; + + start = list = getifacelist(); + if (!start) + return; + + fd = socket(PF_INET, SOCK_STREAM, 0); + + while (list && *list) { + strlcpy(ifr.ifr_name, *list, sizeof(ifr.ifr_name)); + list++; + + + if (ioctl(dsi->serversock, SIOCGIFFLAGS, &ifr) < 0) + continue; + + if (ifr.ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_SLAVE)) + continue; + + if (!(ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) ) + continue; + + if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) + continue; + + memset(&dsi->server, 0, sizeof(struct sockaddr_storage)); + sa->sin_family = AF_INET; + sa->sin_port = htons(atoi(port)); + sa->sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + + LOG(log_info, logtype_dsi, "dsi_tcp: '%s:%s' on interface '%s' will be used instead.", + getip_string((struct sockaddr *)&dsi->server), port, ifr.ifr_name); + goto iflist_done; + } + + LOG(log_note, logtype_dsi, "dsi_tcp: couldn't find network interface with IP address to advertice, " + "check to make sure \"%s\" is in /etc/hosts or can be resolved with DNS, or " + "add a netinterface that is not a loopback or point-2-point type", hostname); + +iflist_done: + close(fd); + freeifacelist(start); +} + + +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0 +#endif + +/*! + * Initialize DSI over TCP + * + * @param dsi (rw) DSI handle + * @param hostname (r) pointer to hostname string + * @param inaddress (r) Optional IPv4 or IPv6 address with an optional port, may be NULL + * @param inport (r) pointer to port string + * + * Creates listening AFP/DSI socket. If the parameter inaddress is NULL, then we listen + * on the wildcard address, ie on all interfaces. That should mean listening on the IPv6 + * address "::" on IPv4/IPv6 dual stack kernels, accepting both v4 and v6 requests. + * + * If the parameter inaddress is not NULL, then we only listen on the given address. + * The parameter may contain a port number using the URL format for address and port: + * + * IPv4, IPv4:port, IPv6, [IPv6], [IPv6]:port + * + * Parameter inport must be a valid pointer to a port string and is used if the inaddress + * parameter doesn't contain a port. + * + * @returns 0 on success, -1 on failure + */ +int dsi_tcp_init(DSI *dsi, const char *hostname, const char *inaddress, const char *inport) +{ + EC_INIT; + int flag, err; + char *address = NULL, *port = NULL; + struct addrinfo hints, *servinfo, *p; + + /* inaddress may be NULL */ + AFP_ASSERT(dsi && hostname && inport); + + if (inaddress) + /* Check whether address is of the from IP:PORT and split */ + EC_ZERO( tokenize_ip_port(inaddress, &address, &port) ); + + if (port == NULL) + /* inport is supposed to always contain a valid port string */ + EC_NULL( port = strdup(inport) ); + + /* Prepare hint for getaddrinfo */ + memset(&hints, 0, sizeof hints); +#if !defined(FREEBSD) + hints.ai_family = AF_UNSPEC; +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICSERV; + + if ( ! address) { + hints.ai_flags |= AI_PASSIVE; +#if defined(FREEBSD) + hints.ai_family = AF_INET6; +#endif + } else { + hints.ai_flags |= AI_NUMERICHOST; +#if defined(FREEBSD) + hints.ai_family = AF_UNSPEC; +#endif + } + if ((ret = getaddrinfo(address, port, &hints, &servinfo)) != 0) { + LOG(log_error, logtype_dsi, "dsi_tcp_init(%s): getaddrinfo: %s\n", address ? address : "*", gai_strerror(ret)); + EC_FAIL; + } + + /* loop through all the results and bind to the first we can */ + for (p = servinfo; p != NULL; p = p->ai_next) { + if ((dsi->serversock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + LOG(log_info, logtype_dsi, "dsi_tcp_init: socket: %s", strerror(errno)); + continue; + } + + /* + * Set some socket options: + * SO_REUSEADDR deals w/ quick close/opens + * TCP_NODELAY diables Nagle + */ +#ifdef SO_REUSEADDR + flag = 1; + setsockopt(dsi->serversock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); +#endif +#if defined(FREEBSD) && defined(IPV6_BINDV6ONLY) + int on = 0; + setsockopt(dsi->serversock, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char *)&on, sizeof (on)); +#endif + +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + flag = 1; + setsockopt(dsi->serversock, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag)); + + if (bind(dsi->serversock, p->ai_addr, p->ai_addrlen) == -1) { + close(dsi->serversock); + LOG(log_info, logtype_dsi, "dsi_tcp_init: bind: %s\n", strerror(errno)); + continue; + } + + if (listen(dsi->serversock, DSI_TCPMAXPEND) < 0) { + close(dsi->serversock); + LOG(log_info, logtype_dsi, "dsi_tcp_init: listen: %s\n", strerror(errno)); + continue; + } + + break; + } + + if (p == NULL) { + LOG(log_error, logtype_dsi, "dsi_tcp_init: no suitable network config for TCP socket"); + freeaddrinfo(servinfo); + EC_FAIL; + } + + /* Copy struct sockaddr to struct sockaddr_storage */ + memcpy(&dsi->server, p->ai_addr, p->ai_addrlen); + freeaddrinfo(servinfo); + + /* Point protocol specific functions to tcp versions */ + dsi->proto_open = dsi_tcp_open; + dsi->proto_close = dsi_tcp_close; + + /* get real address for GetStatus. */ + + if (address) { + /* address is a parameter, use it 'as is' */ + goto EC_CLEANUP; + } + + /* Prepare hint for getaddrinfo */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ((err = getaddrinfo(hostname, port, &hints, &servinfo)) != 0) { + LOG(log_info, logtype_dsi, "dsi_tcp_init: getaddrinfo '%s': %s\n", hostname, gai_strerror(err)); + goto interfaces; + } + + for (p = servinfo; p != NULL; p = p->ai_next) { + if (p->ai_family == AF_INET) { // IPv4 + struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; + if ( (ipv4->sin_addr.s_addr & htonl(0x7f000000)) != htonl(0x7f000000) ) + break; + } else { // IPv6 + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; + unsigned char ipv6loopb[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; + if ((memcmp(ipv6->sin6_addr.s6_addr, ipv6loopb, 16)) != 0) + break; + } + } + + if (p) { + /* Store found address in dsi->server */ + memcpy(&dsi->server, p->ai_addr, p->ai_addrlen); + freeaddrinfo(servinfo); + goto EC_CLEANUP; + } + LOG(log_info, logtype_dsi, "dsi_tcp: hostname '%s' resolves to loopback address", hostname); + freeaddrinfo(servinfo); + +interfaces: + guess_interface(dsi, hostname, port ? port : "548"); + +EC_CLEANUP: + if (address) + free(address); + if (port) + free(port); + EC_EXIT; +} + diff --git a/libatalk/dsi/dsi_tickle.c b/libatalk/dsi/dsi_tickle.c new file mode 100644 index 0000000..a283d40 --- /dev/null +++ b/libatalk/dsi/dsi_tickle.c @@ -0,0 +1,38 @@ +/* + * + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include + +/* server generated tickles. as this is only called by the tickle handler, + * we don't need to block signals. */ +int dsi_tickle(DSI *dsi) +{ + char block[DSI_BLOCKSIZ]; + uint16_t id; + + if ((dsi->flags & DSI_SLEEPING) || dsi->in_write) + return 1; + + id = htons(dsi_serverID(dsi)); + + memset(block, 0, sizeof(block)); + block[0] = DSIFL_REQUEST; + block[1] = DSIFUNC_TICKLE; + memcpy(block + 2, &id, sizeof(id)); + /* code = len = reserved = 0 */ + + return dsi_stream_write(dsi, block, DSI_BLOCKSIZ, DSI_NOWAIT); +} + diff --git a/libatalk/dsi/dsi_write.c b/libatalk/dsi/dsi_write.c new file mode 100644 index 0000000..fd8fe2c --- /dev/null +++ b/libatalk/dsi/dsi_write.c @@ -0,0 +1,79 @@ +/* + * + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + * + * 7 Oct 1997 added checks for 0 data. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +/* this streams writes */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +size_t dsi_writeinit(DSI *dsi, void *buf, const size_t buflen _U_) +{ + size_t bytes = 0; + dsi->datasize = ntohl(dsi->header.dsi_len) - dsi->header.dsi_data.dsi_doff; + + if (dsi->eof > dsi->start) { + /* We have data in the buffer */ + bytes = MIN(dsi->eof - dsi->start, dsi->datasize); + memmove(buf, dsi->start, bytes); + dsi->start += bytes; + dsi->datasize -= bytes; + if (dsi->start >= dsi->eof) + dsi->start = dsi->eof = dsi->buffer; + } + + LOG(log_maxdebug, logtype_dsi, "dsi_writeinit: remaining DSI datasize: %jd", (intmax_t)dsi->datasize); + + return bytes; +} + + +/* fill up buf and then return. this should be called repeatedly + * until all the data has been read. i block alarm processing + * during the transfer to avoid sending unnecessary tickles. */ +size_t dsi_write(DSI *dsi, void *buf, const size_t buflen) +{ + size_t length; + + LOG(log_maxdebug, logtype_dsi, "dsi_write: remaining DSI datasize: %jd", (intmax_t)dsi->datasize); + + if ((length = MIN(buflen, dsi->datasize)) > 0) { + if ((length = dsi_stream_read(dsi, buf, length)) > 0) { + LOG(log_maxdebug, logtype_dsi, "dsi_write: received: %ju", (intmax_t)length); + dsi->datasize -= length; + return length; + } + } + return 0; +} + +/* flush any unread buffers. */ +void dsi_writeflush(DSI *dsi) +{ + size_t length; + + while (dsi->datasize > 0) { + length = dsi_stream_read(dsi, dsi->data, + MIN(sizeof(dsi->data), dsi->datasize)); + if (length > 0) + dsi->datasize -= length; + else + break; + } +} diff --git a/libatalk/dummy.c b/libatalk/dummy.c new file mode 100644 index 0000000..e69de29 diff --git a/libatalk/iniparser/Makefile.am b/libatalk/iniparser/Makefile.am new file mode 100644 index 0000000..a0789af --- /dev/null +++ b/libatalk/iniparser/Makefile.am @@ -0,0 +1,7 @@ +# Makefile.am for libatalk/iniparser/ + +noinst_LTLIBRARIES = libiniparser.la + +libiniparser_la_SOURCES = \ + dictionary.c \ + iniparser.c diff --git a/libatalk/iniparser/Makefile.in b/libatalk/iniparser/Makefile.in new file mode 100644 index 0000000..3162c00 --- /dev/null +++ b/libatalk/iniparser/Makefile.in @@ -0,0 +1,665 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/iniparser/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/iniparser +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libiniparser_la_LIBADD = +am_libiniparser_la_OBJECTS = dictionary.lo iniparser.lo +libiniparser_la_OBJECTS = $(am_libiniparser_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libiniparser_la_SOURCES) +DIST_SOURCES = $(libiniparser_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libiniparser.la +libiniparser_la_SOURCES = \ + dictionary.c \ + iniparser.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/iniparser/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/iniparser/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libiniparser.la: $(libiniparser_la_OBJECTS) $(libiniparser_la_DEPENDENCIES) $(EXTRA_libiniparser_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libiniparser_la_OBJECTS) $(libiniparser_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dictionary.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iniparser.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/iniparser/dictionary.c b/libatalk/iniparser/dictionary.c new file mode 100644 index 0000000..191db57 --- /dev/null +++ b/libatalk/iniparser/dictionary.c @@ -0,0 +1,377 @@ +/*-------------------------------------------------------------------------*/ +/** + @file dictionary.c + @author N. Devillard + @date Sep 2007 + @brief Implements a dictionary for string variables. + + This module implements a simple dictionary object, i.e. a list + of string/string associations. This object is useful to store e.g. + informations retrieved from a configuration file (ini files). +*/ +/*--------------------------------------------------------------------------*/ + +/* +*/ +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include + +#include +#include +#include +#include + +/** Maximum value size for integers and doubles. */ +#define MAXVALSZ 1024 + +/** Minimal allocated number of entries in a dictionary */ +#define DICTMINSZ 128 + +/** Invalid key token */ +#define DICT_INVALID_KEY ((char*)-1) + +/*--------------------------------------------------------------------------- + Private functions + ---------------------------------------------------------------------------*/ + +#define MAXKEYSIZE 1024 +static char *makekey(const char *section, const char *entry) +{ + static char buf[MAXKEYSIZE]; + + strlcpy(buf, section, MAXKEYSIZE); + if (entry) { + strlcat(buf, ":", MAXKEYSIZE); + strlcat(buf, entry, MAXKEYSIZE); + } + + return buf; +} + +/* Doubles the allocated size associated to a pointer */ +/* 'size' is the current allocated size. */ +static void * mem_double(void * ptr, int size) +{ + void * newptr ; + + newptr = calloc(2*size, 1); + if (newptr==NULL) { + return NULL ; + } + memcpy(newptr, ptr, size); + free(ptr); + return newptr ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Duplicate a string + @param s String to duplicate + @return Pointer to a newly allocated string, to be freed with free() + + This is a replacement for strdup(). This implementation is provided + for systems that do not have it. + */ +/*--------------------------------------------------------------------------*/ +static char * xstrdup(char * s) +{ + char * t ; + if (!s) + return NULL ; + t = malloc(strlen(s)+1) ; + if (t) { + strcpy(t,s); + } + return t ; +} + +/*--------------------------------------------------------------------------- + Function codes + ---------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/ +/** + @brief Compute the hash key for a string. + @param key Character string to use for key. + @return 1 unsigned int on at least 32 bits. + + This hash function has been taken from an Article in Dr Dobbs Journal. + This is normally a collision-free function, distributing keys evenly. + The key is stored anyway in the struct so that collision can be avoided + by comparing the key itself in last resort. + */ +/*--------------------------------------------------------------------------*/ +unsigned atalkdict_hash(char * key) +{ + int len ; + unsigned hash ; + int i ; + + len = strlen(key); + for (hash=0, i=0 ; i>6) ; + } + hash += (hash <<3); + hash ^= (hash >>11); + hash += (hash <<15); + return hash ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Create a new dictionary object. + @param size Optional initial size of the dictionary. + @return 1 newly allocated dictionary objet. + + This function allocates a new dictionary object of given size and returns + it. If you do not know in advance (roughly) the number of entries in the + dictionary, give size=0. + */ +/*--------------------------------------------------------------------------*/ +dictionary * atalkdict_new(int size) +{ + dictionary * d ; + + /* If no size was specified, allocate space for DICTMINSZ */ + if (sizesize = size ; + d->val = (char **)calloc(size, sizeof(char*)); + d->key = (char **)calloc(size, sizeof(char*)); + d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); + return d ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a dictionary object + @param d dictionary object to deallocate. + @return void + + Deallocate a dictionary object and all memory associated to it. + */ +/*--------------------------------------------------------------------------*/ +void atalkdict_del(dictionary * d) +{ + int i ; + + if (d==NULL) return ; + for (i=0 ; isize ; i++) { + if (d->key[i]!=NULL) + free(d->key[i]); + if (d->val[i]!=NULL) + free(d->val[i]); + } + free(d->val); + free(d->key); + free(d->hash); + free(d); + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get a value from a dictionary. + @param d dictionary object to search. + @param key Key to look for in the dictionary. + @param def Default value to return if key not found. + @return 1 pointer to internally allocated character string. + + This function locates a key in a dictionary and returns a pointer to its + value, or the passed 'def' pointer if no such key can be found in + dictionary. The returned character pointer points to data internal to the + dictionary object, you should not try to free it or modify it. + */ +/*--------------------------------------------------------------------------*/ +const char * atalkdict_get(const dictionary * d, const char *section, const char * key, const char * def) +{ + unsigned hash ; + int i ; + + hash = atalkdict_hash(makekey(section, key)); + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + /* Compare hash */ + if (hash==d->hash[i]) { + /* Compare string, to avoid hash collisions */ + if (!strcmp(makekey(section, key), d->key[i])) { + return d->val[i] ; + } + } + } + return def ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Set a value in a dictionary. + @param d dictionary object to modify. + @param key Key to modify or add. + @param val Value to add. + @return int 0 if Ok, anything else otherwise + + If the given key is found in the dictionary, the associated value is + replaced by the provided one. If the key cannot be found in the + dictionary, it is added to it. + + It is Ok to provide a NULL value for val, but NULL values for the dictionary + or the key are considered as errors: the function will return immediately + in such a case. + + Notice that if you atalkdict_set a variable to NULL, a call to + atalkdict_get will return a NULL value: the variable will be found, and + its value (NULL) is returned. In other words, setting the variable + content to NULL is equivalent to deleting the variable from the + dictionary. It is not possible (in this implementation) to have a key in + the dictionary without value. + + This function returns non-zero in case of failure. + */ +/*--------------------------------------------------------------------------*/ +int atalkdict_set(dictionary * d, char *section, char * key, char * val) +{ + int i ; + unsigned hash ; + + if (d==NULL || section==NULL) return -1 ; + + /* Compute hash for this key */ + hash = atalkdict_hash(makekey(section, key)); + /* Find if value is already in dictionary */ + if (d->n>0) { + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (hash==d->hash[i]) { /* Same hash value */ + if (!strcmp(makekey(section, key), d->key[i])) { /* Same key */ + /* Found a value: modify and return */ + if (d->val[i]!=NULL) + free(d->val[i]); + d->val[i] = val ? xstrdup(val) : NULL ; + /* Value has been modified: return */ + return 0 ; + } + } + } + } + /* Add a new value */ + /* See if dictionary needs to grow */ + if (d->n==d->size) { + + /* Reached maximum size: reallocate dictionary */ + d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; + d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; + d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; + if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) { + /* Cannot grow dictionary */ + return -1 ; + } + /* Double size */ + d->size *= 2 ; + } + + /* Insert key in the first empty slot */ + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) { + /* Add key here */ + break ; + } + } + /* Copy key */ + d->key[i] = xstrdup(makekey(section, key)); + d->val[i] = val ? xstrdup(val) : NULL ; + d->hash[i] = hash; + d->n ++ ; + return 0 ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a key in a dictionary + @param d dictionary object to modify. + @param key Key to remove. + @return void + + This function deletes a key in a dictionary. Nothing is done if the + key cannot be found. + */ +/*--------------------------------------------------------------------------*/ +void atalkdict_unset(dictionary * d, char *section, char * key) +{ + unsigned hash ; + int i ; + + if (key == NULL) { + return; + } + + hash = atalkdict_hash(makekey(section, key)); + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + /* Compare hash */ + if (hash==d->hash[i]) { + /* Compare string, to avoid hash collisions */ + if (!strcmp(makekey(section, key), d->key[i])) { + /* Found key */ + break ; + } + } + } + if (i>=d->size) + /* Key not found */ + return ; + + free(d->key[i]); + d->key[i] = NULL ; + if (d->val[i]!=NULL) { + free(d->val[i]); + d->val[i] = NULL ; + } + d->hash[i] = 0 ; + d->n -- ; + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump + @param f Opened file pointer. + @return void + + Dumps a dictionary onto an opened file pointer. Key pairs are printed out + as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as + output file pointers. + */ +/*--------------------------------------------------------------------------*/ +void atalkdict_dump(dictionary * d, FILE * out) +{ + int i ; + + if (d==NULL || out==NULL) return ; + if (d->n<1) { + fprintf(out, "empty dictionary\n"); + return ; + } + for (i=0 ; isize ; i++) { + if (d->key[i]) { + fprintf(out, "%20s\t[%s]\n", + d->key[i], + d->val[i] ? d->val[i] : "UNDEF"); + } + } + return ; +} diff --git a/libatalk/iniparser/iniparser.c b/libatalk/iniparser/iniparser.c new file mode 100644 index 0000000..343a6d0 --- /dev/null +++ b/libatalk/iniparser/iniparser.c @@ -0,0 +1,652 @@ +/*-------------------------------------------------------------------------*/ +/** + @file iniparser.c + @author N. Devillard + @date Sep 2007 + @version 3.0 + @brief Parser for ini files. +*/ + +/*---------------------------- Includes ------------------------------------*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include +#include + +/*---------------------------- Defines -------------------------------------*/ +#define ASCIILINESZ (1024) +#define INI_INVALID_KEY ((char*)-1) + +/*--------------------------------------------------------------------------- + Private to this module + ---------------------------------------------------------------------------*/ +/** + * This enum stores the status for each parsed line (internal use only). + */ +typedef enum _line_status_ { + LINE_UNPROCESSED, + LINE_ERROR, + LINE_EMPTY, + LINE_COMMENT, + LINE_SECTION, + LINE_VALUE +} line_status ; + +/*-------------------------------------------------------------------------*/ +/** + @brief Remove blanks at the beginning and the end of a string. + @param s String to parse. + @return ptr to statically allocated string. + + This function returns a pointer to a statically allocated string, + which is identical to the input string, except that all blank + characters at the end and the beg. of the string have been removed. + Do not free or modify the returned string! Since the returned string + is statically allocated, it will be modified at each function call + (not re-entrant). + */ +/*--------------------------------------------------------------------------*/ +static char * strstrip(char * s) +{ + static char l[ASCIILINESZ+1]; + char * last ; + + if (s==NULL) return NULL ; + + while (isspace((int)*s) && *s) s++; + memset(l, 0, ASCIILINESZ+1); + strcpy(l, s); + last = l + strlen(l); + while (last > l) { + if (!isspace((int)*(last-1))) + break ; + last -- ; + } + *last = (char)0; + return (char*)l ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get number of sections in a dictionary + @param d Dictionary to examine + @return int Number of sections found in dictionary + + This function returns the number of sections found in a dictionary. + The test to recognize sections is done on the string stored in the + dictionary: a section name is given as "section" whereas a key is + stored as "section:key", thus the test looks for entries that do not + contain a colon. + + This clearly fails in the case a section name contains a colon, but + this should simply be avoided. + + This function returns -1 in case of error. + */ +/*--------------------------------------------------------------------------*/ +int atalk_iniparser_getnsec(const dictionary * d) +{ + int i ; + int nsec ; + + if (d==NULL) return -1 ; + nsec=0 ; + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (strchr(d->key[i], ':')==NULL) { + nsec ++ ; + } + } + return nsec ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get name for section n in a dictionary. + @param d Dictionary to examine + @param n Section number (from 0 to nsec-1). + @return Pointer to char string + + This function locates the n-th section in a dictionary and returns + its name as a pointer to a string statically allocated inside the + dictionary. Do not free or modify the returned string! + + This function returns NULL in case of error. + */ +/*--------------------------------------------------------------------------*/ +const char * atalk_iniparser_getsecname(const dictionary * d, int n) +{ + int i ; + int foundsec ; + + if (d==NULL || n<0) return NULL ; + foundsec=0 ; + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (strchr(d->key[i], ':')==NULL) { + foundsec++ ; + if (foundsec>n) + break ; + } + } + if (foundsec<=n) { + return NULL ; + } + return d->key[i] ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump. + @param f Opened file pointer to dump to. + @return void + + This function prints out the contents of a dictionary, one element by + line, onto the provided file pointer. It is OK to specify @c stderr + or @c stdout as output files. This function is meant for debugging + purposes mostly. + */ +/*--------------------------------------------------------------------------*/ +void atalk_iniparser_dump(const dictionary * d, FILE * f) +{ + int i ; + + if (d==NULL || f==NULL) return ; + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (d->val[i]!=NULL) { + fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); + } else { + fprintf(f, "[%s]=UNDEF\n", d->key[i]); + } + } + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Save a dictionary to a loadable ini file + @param d Dictionary to dump + @param f Opened file pointer to dump to + @return void + + This function dumps a given dictionary into a loadable ini file. + It is Ok to specify @c stderr or @c stdout as output files. + */ +/*--------------------------------------------------------------------------*/ +void atalk_iniparser_dump_ini(const dictionary * d, FILE * f) +{ + int i, j ; + char keym[ASCIILINESZ+1]; + int nsec ; + const char * secname ; + int seclen ; + + if (d==NULL || f==NULL) return ; + + nsec = atalk_iniparser_getnsec(d); + if (nsec<1) { + /* No section in file: dump all keys as they are */ + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + fprintf(f, "%s = %s\n", d->key[i], d->val[i]); + } + return ; + } + for (i=0 ; isize ; j++) { + if (d->key[j]==NULL) + continue ; + if (!strncmp(d->key[j], keym, seclen+1)) { + fprintf(f, + "%-30s = %s\n", + d->key[j]+seclen+1, + d->val[j] ? d->val[j] : ""); + } + } + } + fprintf(f, "\n"); + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key + @param d Dictionary to search + @param section Section to search + @param key Key string to look for + @param def Default value to return if key not found. + @return pointer to statically allocated character string + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the pointer passed as 'def' is returned. + The returned char pointer is pointing to a string allocated in + the dictionary, do not free or modify it. + */ +/*--------------------------------------------------------------------------*/ +const char * atalk_iniparser_getstring(const dictionary * d, const char *section, const char * key, const char * def) +{ + const char * sval ; + + if (d==NULL || key==NULL) + return def ; + + sval = atalkdict_get(d, section, key, def); + return sval ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key + @param d Dictionary to search + @param section Section to search + @param key Key string to look for + @param def Default value to return if key not found. + @return pointer to statically allocated character string + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the pointer passed as 'def' is returned. + The returned char pointer a strdup'ed allocated string, so the caller must free it. + */ +/*--------------------------------------------------------------------------*/ +char * atalk_iniparser_getstrdup(const dictionary * d, const char *section, const char * key, const char * def) +{ + const char * sval ; + + if (d==NULL || key==NULL) + return NULL; + + if ((sval = atalkdict_get(d, section, key, def))) + return strdup(sval); + return NULL; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to an int + @param d Dictionary to search + @param section Section to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + Supported values for integers include the usual C notation + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) + are supported. Examples: + + "42" -> 42 + "042" -> 34 (octal -> decimal) + "0x42" -> 66 (hexa -> decimal) + + Warning: the conversion may overflow in various ways. Conversion is + totally outsourced to strtol(), see the associated man page for overflow + handling. + + Credits: Thanks to A. Becker for suggesting strtol() + */ +/*--------------------------------------------------------------------------*/ +int atalk_iniparser_getint(const dictionary * d, const char *section, const char * key, int notfound) +{ + const char * str ; + + str = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY); + if (str==INI_INVALID_KEY) return notfound ; + return (int)strtol(str, NULL, 0); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a double + @param d Dictionary to search + @param section Section to search + @param key Key string to look for + @param notfound Value to return in case of error + @return double + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + */ +/*--------------------------------------------------------------------------*/ +double atalk_iniparser_getdouble(const dictionary * d, const char *section, const char * key, double notfound) +{ + const char * str ; + + str = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY); + if (str==INI_INVALID_KEY) return notfound ; + return atof(str); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a boolean + @param d Dictionary to search + @param section Section to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + A true boolean is found if one of the following is matched: + + - A string starting with 'y' + - A string starting with 'Y' + - A string starting with 't' + - A string starting with 'T' + - A string starting with '1' + + A false boolean is found if one of the following is matched: + + - A string starting with 'n' + - A string starting with 'N' + - A string starting with 'f' + - A string starting with 'F' + - A string starting with '0' + + The notfound value returned if no boolean is identified, does not + necessarily have to be 0 or 1. + */ +/*--------------------------------------------------------------------------*/ +int atalk_iniparser_getboolean(const dictionary * d, const char *section, const char * key, int notfound) +{ + const char * c ; + int ret ; + + c = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY); + if (c==INI_INVALID_KEY) return notfound ; + if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { + ret = 1 ; + } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { + ret = 0 ; + } else { + ret = notfound ; + } + return ret; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Finds out if a given entry exists in a dictionary + @param ini Dictionary to search + @param entry Name of the entry to look for + @return integer 1 if entry exists, 0 otherwise + + Finds out if a given entry exists in the dictionary. Since sections + are stored as keys with NULL associated values, this is the only way + of querying for the presence of sections in a dictionary. + */ +/*--------------------------------------------------------------------------*/ +int atalk_iniparser_find_entry(const dictionary *ini, const char *entry) +{ + int found=0 ; + if (atalk_iniparser_getstring(ini, entry, NULL, INI_INVALID_KEY)!=INI_INVALID_KEY) { + found = 1 ; + } + return found ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Set an entry in a dictionary. + @param ini Dictionary to modify. + @param section Entry to modify (entry section) + @param key Entry to modify (entry key) + @param val New value to associate to the entry. + @return int 0 if Ok, -1 otherwise. + + If the given entry can be found in the dictionary, it is modified to + contain the provided value. If it cannot be found, -1 is returned. + It is Ok to set val to NULL. + */ +/*--------------------------------------------------------------------------*/ +int atalk_iniparser_set(dictionary * ini, char *section, char * key, char * val) +{ + return atalkdict_set(ini, section, key, val) ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete an entry in a dictionary + @param ini Dictionary to modify + @param section Entry to delete (entry section) + @param key Entry to delete (entry key) + @return void + + If the given entry can be found, it is deleted from the dictionary. + */ +/*--------------------------------------------------------------------------*/ +void atalk_iniparser_unset(dictionary * ini, char *section, char * key) +{ + atalkdict_unset(ini, section, key); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Load a single line from an INI file + @param input_line Input line, may be concatenated multi-line input + @param section Output space to store section + @param key Output space to store key + @param value Output space to store value + @return line_status value + */ +/*--------------------------------------------------------------------------*/ +static line_status atalk_iniparser_line( + char * input_line, + char * section, + char * key, + char * value) +{ + line_status sta ; + char line[ASCIILINESZ+1]; + int len ; + + strcpy(line, strstrip(input_line)); + len = (int)strlen(line); + + sta = LINE_UNPROCESSED ; + if (len<1) { + /* Empty line */ + sta = LINE_EMPTY ; + } else if (line[0]=='#' || line[0]==';') { + /* Comment line */ + sta = LINE_COMMENT ; + } else if (line[0]=='[' && line[len-1]==']') { + /* Section name */ + sscanf(line, "[%[^]]", section); + strcpy(section, strstrip(section)); + strcpy(section, section); + sta = LINE_SECTION ; + } else if (sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 + || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { + /* Usual key=value, with or without comments */ + strcpy(key, strstrip(key)); + strcpy(key, key); + strcpy(value, strstrip(value)); + /* + * sscanf cannot handle '' or "" as empty values + * this is done here + */ + if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { + value[0]=0 ; + } + sta = LINE_VALUE ; + } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 + || sscanf(line, "%[^=] %[=]", key, value) == 2) { + /* + * Special cases: + * key= + * key=; + * key=# + */ + strcpy(key, strstrip(key)); + strcpy(key, key); + value[0]=0 ; + sta = LINE_VALUE ; + } else { + /* Generate syntax error */ + sta = LINE_ERROR ; + } + return sta ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Parse an ini file and return an allocated dictionary object + @param ininame Name of the ini file to read. + @return Pointer to newly allocated dictionary + + This is the parser for ini files. This function is called, providing + the name of the file to be read. It returns a dictionary object that + should not be accessed directly, but through accessor functions + instead. + + The returned dictionary must be freed using atalk_iniparser_freedict(). + */ +/*--------------------------------------------------------------------------*/ +dictionary * atalk_iniparser_load(const char * ininame) +{ + FILE *in, *include = NULL, *inifile; + + char line [ASCIILINESZ+1] ; + char section [ASCIILINESZ+1] ; + char key [ASCIILINESZ+1] ; + char val [ASCIILINESZ+1] ; + + int last=0 ; + int len ; + int lineno=0 ; + int errs=0; + + dictionary * dict ; + + if ((inifile=fopen(ininame, "r"))==NULL) { + LOG(log_error, logtype_default, "iniparser: cannot open \"%s\"", ininame); + return NULL ; + } + + dict = atalkdict_new(0) ; + if (!dict) { + fclose(inifile); + return NULL ; + } + + memset(line, 0, ASCIILINESZ); + memset(section, 0, ASCIILINESZ); + memset(key, 0, ASCIILINESZ); + memset(val, 0, ASCIILINESZ); + last=0 ; + + in = inifile; + while (1) { + if (fgets(line+last, ASCIILINESZ-last, in) == NULL) { + if (include) { + fclose(include); + include = NULL; + in = inifile; + continue; + } + break; + } + lineno++ ; + len = (int)strlen(line)-1; + if (len==0) + continue; + /* Get rid of \n and spaces at end of line */ + while ((len>=0) && + ((line[len]=='\n') || (isspace(line[len])))) { + line[len]=0 ; + len-- ; + } + /* Detect multi-line */ + if (line[len]=='\\') { + /* Multi-line value */ + last=len ; + continue ; + } else { + last=0 ; + } + switch (atalk_iniparser_line(line, section, key, val)) { + case LINE_EMPTY: + case LINE_COMMENT: + break ; + case LINE_SECTION: + if (strchr(section, ':') != NULL) + LOG(log_error, logtype_default, "iniparser: syntax error \"%s\" section name must not contain \":\".", section); + errs = atalkdict_set(dict, section, NULL, NULL); + break ; + case LINE_VALUE: + if (strcmp(key, "include") == 0) { + errs = atalkdict_set(dict, section, key, val); + if (errs < 0) { + LOG(log_error, logtype_default, "iniparser: memory allocation failure"); + } + if ((include = fopen(val, "r")) == NULL) { + LOG(log_error, logtype_default, "iniparser: cannot open \"%s\"", val); + continue; + } + in = include; + continue; + } + errs = atalkdict_set(dict, section, key, val) ; + break ; + case LINE_ERROR: + LOG(log_error, logtype_default, "iniparser: syntax error in %s (lineno: %d): %s", + ininame, lineno, line); + errs++ ; + break; + default: + break ; + } + memset(line, 0, ASCIILINESZ); + last=0; + if (errs<0) { + LOG(log_error, logtype_default, "iniparser: memory allocation failure"); + break ; + } + } + if (errs) { + atalkdict_del(dict); + dict = NULL ; + } + fclose(in); + return dict ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Free all memory associated to an ini dictionary + @param d Dictionary to free + @return void + + Free all memory associated to an ini dictionary. + It is mandatory to call this function before the dictionary object + gets out of the current context. + */ +/*--------------------------------------------------------------------------*/ +void atalk_iniparser_freedict(dictionary * d) +{ + atalkdict_del(d); +} + diff --git a/libatalk/libatalk-3.0.1.abi b/libatalk/libatalk-3.0.1.abi new file mode 100644 index 0000000..2030200 --- /dev/null +++ b/libatalk/libatalk-3.0.1.abi @@ -0,0 +1,549 @@ +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_rtruncate: int (struct adouble *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dictionary_del: void (dictionary *) +dictionary_dump: void (dictionary *, FILE *) +dictionary_get: const char *(const dictionary *, const char *, const char *, const char *) +dictionary_hash: unsigned int (char *) +dictionary_new: dictionary *(int) +dictionary_set: int (dictionary *, char *, char *, char *) +dictionary_unset: void (dictionary *, char *, char *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_getsession: int (DSI *, server_child *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +iniparser_dump: void (const dictionary *, FILE *) +iniparser_dump_ini: void (const dictionary *, FILE *) +iniparser_find_entry: int (const dictionary *, const char *) +iniparser_freedict: void (dictionary *) +iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +iniparser_getint: int (const dictionary *, const char *, const char *, int) +iniparser_getnsec: int (const dictionary *) +iniparser_getsecname: const char *(const dictionary *, int) +iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +iniparser_load: dictionary *(const char *) +iniparser_set: int (dictionary *, char *, char *, char *) +iniparser_unset: void (dictionary *, char *, char *) +_init: +init_iconv: void (void) +initvol_vfs: void (struct vol *) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_client_uds: int (const char *) +ipc_server_read: int (server_child *, int) +ipc_server_uds: int (const char *) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +lchdir: int (const char *) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = -1}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, void (*)(const AFPObj *, struct vol *)) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +lstatat: int (int, const char *, struct stat *) +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +reconnect_ipc: int (AFPObj *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child *, int, pid_t, int) +server_child_alloc: server_child *(const int, const int) +server_child_free: void (server_child *) +server_child_kill: void (server_child *, int, int) +server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child *, const int, pid_t) +server_child_setup: void (server_child *, const int, void (*)(const pid_t)) +server_child_transfer_session: int (server_child *, int, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const char *, mode_t, struct stat *, mode_t) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0.2.abi b/libatalk/libatalk-3.0.2.abi new file mode 100644 index 0000000..8e73229 --- /dev/null +++ b/libatalk/libatalk-3.0.2.abi @@ -0,0 +1,565 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_rtruncate: int (struct adouble *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dictionary_del: void (dictionary *) +dictionary_dump: void (dictionary *, FILE *) +dictionary_get: const char *(const dictionary *, const char *, const char *, const char *) +dictionary_hash: unsigned int (char *) +dictionary_new: dictionary *(int) +dictionary_set: int (dictionary *, char *, char *, char *) +dictionary_unset: void (dictionary *, char *, char *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +iniparser_dump: void (const dictionary *, FILE *) +iniparser_dump_ini: void (const dictionary *, FILE *) +iniparser_find_entry: int (const dictionary *, const char *) +iniparser_freedict: void (dictionary *) +iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +iniparser_getint: int (const dictionary *, const char *, const char *, int) +iniparser_getnsec: int (const dictionary *) +iniparser_getsecname: const char *(const dictionary *, int) +iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +iniparser_load: dictionary *(const char *) +iniparser_set: int (dictionary *, char *, char *, char *) +iniparser_unset: void (dictionary *, char *, char *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_client_uds: int (const char *) +ipc_server_read: int (server_child *, int) +ipc_server_uds: int (const char *) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +reconnect_ipc: int (AFPObj *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child *, int, pid_t, int) +server_child_alloc: server_child *(const int, const int) +server_child_free: void (server_child *) +server_child_kill: void (server_child *, int, int) +server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child *, const int, pid_t) +server_child_setup: void (server_child *, const int, void (*)(const pid_t)) +server_child_transfer_session: int (server_child *, int, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0.3.abi b/libatalk/libatalk-3.0.3.abi new file mode 100644 index 0000000..17e9539 --- /dev/null +++ b/libatalk/libatalk-3.0.3.abi @@ -0,0 +1,566 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dictionary_del: void (dictionary *) +dictionary_dump: void (dictionary *, FILE *) +dictionary_get: const char *(const dictionary *, const char *, const char *, const char *) +dictionary_hash: unsigned int (char *) +dictionary_new: dictionary *(int) +dictionary_set: int (dictionary *, char *, char *, char *) +dictionary_unset: void (dictionary *, char *, char *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +iniparser_dump: void (const dictionary *, FILE *) +iniparser_dump_ini: void (const dictionary *, FILE *) +iniparser_find_entry: int (const dictionary *, const char *) +iniparser_freedict: void (dictionary *) +iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +iniparser_getint: int (const dictionary *, const char *, const char *, int) +iniparser_getnsec: int (const dictionary *) +iniparser_getsecname: const char *(const dictionary *, int) +iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +iniparser_load: dictionary *(const char *) +iniparser_set: int (dictionary *, char *, char *, char *) +iniparser_unset: void (dictionary *, char *, char *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0.4.abi b/libatalk/libatalk-3.0.4.abi new file mode 100644 index 0000000..33e4f92 --- /dev/null +++ b/libatalk/libatalk-3.0.4.abi @@ -0,0 +1,566 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dictionary_del: void (dictionary *) +dictionary_dump: void (dictionary *, FILE *) +dictionary_get: const char *(const dictionary *, const char *, const char *, const char *) +dictionary_hash: unsigned int (char *) +dictionary_new: dictionary *(int) +dictionary_set: int (dictionary *, char *, char *, char *) +dictionary_unset: void (dictionary *, char *, char *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +iniparser_dump: void (const dictionary *, FILE *) +iniparser_dump_ini: void (const dictionary *, FILE *) +iniparser_find_entry: int (const dictionary *, const char *) +iniparser_freedict: void (dictionary *) +iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +iniparser_getint: int (const dictionary *, const char *, const char *, int) +iniparser_getnsec: int (const dictionary *) +iniparser_getsecname: const char *(const dictionary *, int) +iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +iniparser_load: dictionary *(const char *) +iniparser_set: int (dictionary *, char *, char *, char *) +iniparser_unset: void (dictionary *, char *, char *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0.5.abi b/libatalk/libatalk-3.0.5.abi new file mode 100644 index 0000000..2425dc6 --- /dev/null +++ b/libatalk/libatalk-3.0.5.abi @@ -0,0 +1,568 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0.6.abi b/libatalk/libatalk-3.0.6.abi new file mode 100644 index 0000000..57fa789 --- /dev/null +++ b/libatalk/libatalk-3.0.6.abi @@ -0,0 +1,570 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0.abi b/libatalk/libatalk-3.0.abi new file mode 100644 index 0000000..0d9dc70 --- /dev/null +++ b/libatalk/libatalk-3.0.abi @@ -0,0 +1,548 @@ +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_rtruncate: int (struct adouble *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dictionary_del: void (dictionary *) +dictionary_dump: void (dictionary *, FILE *) +dictionary_get: const char *(const dictionary *, const char *, const char *, const char *) +dictionary_hash: unsigned int (char *) +dictionary_new: dictionary *(int) +dictionary_set: int (dictionary *, char *, char *, char *) +dictionary_unset: void (dictionary *, char *, char *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_getsession: int (DSI *, server_child *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +iniparser_dump: void (const dictionary *, FILE *) +iniparser_dump_ini: void (const dictionary *, FILE *) +iniparser_find_entry: int (const dictionary *, const char *) +iniparser_freedict: void (dictionary *) +iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +iniparser_getint: int (const dictionary *, const char *, const char *, int) +iniparser_getnsec: int (const dictionary *) +iniparser_getsecname: const char *(const dictionary *, int) +iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +iniparser_load: dictionary *(const char *) +iniparser_set: int (dictionary *, char *, char *, char *) +iniparser_unset: void (dictionary *, char *, char *) +_init: +init_iconv: void (void) +initvol_vfs: void (struct vol *) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_client_uds: int (const char *) +ipc_server_read: int (server_child *, int) +ipc_server_uds: int (const char *) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +lchdir: int (const char *) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = -1}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, void (*)(const AFPObj *, struct vol *)) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +lstatat: int (int, const char *, struct stat *) +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +reconnect_ipc: int (AFPObj *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child *, int, pid_t, int) +server_child_alloc: server_child *(const int, const int) +server_child_free: void (server_child *) +server_child_kill: void (server_child *, int, int) +server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child *, const int, pid_t) +server_child_setup: void (server_child *, const int, void (*)(const pid_t)) +server_child_transfer_session: int (server_child *, int, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const char *, mode_t, struct stat *, mode_t) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0beta1.abi b/libatalk/libatalk-3.0beta1.abi new file mode 100644 index 0000000..f87258d --- /dev/null +++ b/libatalk/libatalk-3.0beta1.abi @@ -0,0 +1,550 @@ +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_rtruncate: int (struct adouble *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_names: +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dictionary_del: void (dictionary *) +dictionary_dump: void (dictionary *, FILE *) +dictionary_get: const char *(const dictionary *, const char *, const char *, const char *) +dictionary_hash: unsigned int (char *) +dictionary_new: dictionary *(int) +dictionary_set: int (dictionary *, char *, char *, char *) +dictionary_unset: void (dictionary *, char *, char *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_getsession: int (DSI *, server_child *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +iniparser_dump: void (const dictionary *, FILE *) +iniparser_dump_ini: void (const dictionary *, FILE *) +iniparser_find_entry: int (const dictionary *, const char *) +iniparser_freedict: void (dictionary *) +iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +iniparser_getint: int (const dictionary *, const char *, const char *, int) +iniparser_getnsec: int (const dictionary *) +iniparser_getsecname: const char *(const dictionary *, int) +iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +iniparser_load: dictionary *(const char *) +iniparser_set: int (dictionary *, char *, char *, char *) +iniparser_unset: void (dictionary *, char *, char *) +_init: +init_iconv: void (void) +initvol_vfs: void (struct vol *) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_client_uds: int (const char *) +ipc_server_read: int (server_child *, int) +ipc_server_uds: int (const char *) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +lchdir: int (const char *) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = -1}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, void (*)(const AFPObj *, struct vol *)) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +lstatat: int (int, const char *, struct stat *) +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +namecache: {} +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +reconnect_ipc: int (AFPObj *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child *, int, pid_t, int) +server_child_alloc: server_child *(const int, const int) +server_child_free: void (server_child *) +server_child_kill: void (server_child *, int, int) +server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child *, const int, pid_t) +server_child_setup: void (server_child *, const int, void (*)(const pid_t)) +server_child_transfer_session: int (server_child *, int, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const char *, mode_t, struct stat *, mode_t) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache: {} +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.0beta2.abi b/libatalk/libatalk-3.0beta2.abi new file mode 100644 index 0000000..0d9dc70 --- /dev/null +++ b/libatalk/libatalk-3.0beta2.abi @@ -0,0 +1,548 @@ +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_rtruncate: int (struct adouble *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dictionary_del: void (dictionary *) +dictionary_dump: void (dictionary *, FILE *) +dictionary_get: const char *(const dictionary *, const char *, const char *, const char *) +dictionary_hash: unsigned int (char *) +dictionary_new: dictionary *(int) +dictionary_set: int (dictionary *, char *, char *, char *) +dictionary_unset: void (dictionary *, char *, char *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_getsession: int (DSI *, server_child *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +iniparser_dump: void (const dictionary *, FILE *) +iniparser_dump_ini: void (const dictionary *, FILE *) +iniparser_find_entry: int (const dictionary *, const char *) +iniparser_freedict: void (dictionary *) +iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +iniparser_getint: int (const dictionary *, const char *, const char *, int) +iniparser_getnsec: int (const dictionary *) +iniparser_getsecname: const char *(const dictionary *, int) +iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +iniparser_load: dictionary *(const char *) +iniparser_set: int (dictionary *, char *, char *, char *) +iniparser_unset: void (dictionary *, char *, char *) +_init: +init_iconv: void (void) +initvol_vfs: void (struct vol *) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_client_uds: int (const char *) +ipc_server_read: int (server_child *, int) +ipc_server_uds: int (const char *) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +lchdir: int (const char *) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = -1}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, void (*)(const AFPObj *, struct vol *)) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +lstatat: int (int, const char *, struct stat *) +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +reconnect_ipc: int (AFPObj *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child *, int, pid_t, int) +server_child_alloc: server_child *(const int, const int) +server_child_free: void (server_child *) +server_child_kill: void (server_child *, int, int) +server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child *, const int, pid_t) +server_child_setup: void (server_child *, const int, void (*)(const pid_t)) +server_child_transfer_session: int (server_child *, int, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const char *, mode_t, struct stat *, mode_t) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.1.0.abi b/libatalk/libatalk-3.1.0.abi new file mode 100644 index 0000000..ebbfd6c --- /dev/null +++ b/libatalk/libatalk-3.1.0.abi @@ -0,0 +1,651 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +apply_ip_mask: void (struct sockaddr *, int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = , flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = , flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_mysql_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_close: void (struct _cnid_db *) +cnid_mysql_delete: int (struct _cnid_db *, const cnid_t) +cnid_mysql_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_mysql_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_mysql_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_mysql_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_module: {name = "mysql", db_list = {next = 0x0, prev = 0x0}, cnid_open = , flags = 0} +cnid_mysql_open: struct _cnid_db *(struct cnid_open_args *) +cnid_mysql_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_mysql_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_wipe: int (struct _cnid_db *) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *, const void *, char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = , flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t) +dalloc_get: void *(const DALLOC_CTX *, ...) +dalloc_size: int (DALLOC_CTX *) +dalloc_strdup: char *(const void *, const char *) +dalloc_strndup: char *(const void *, const char *, size_t) +dalloc_value_for_key: void *(const DALLOC_CTX *, ...) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +_talloc: void *(const void *, size_t) +_talloc_array: void *(const void *, size_t, unsigned int, const char *) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +_talloc_free: int (void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +_talloc_get_type_abort: void *(const void *, const char *, const char *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +_talloc_memdup: void *(const void *, const void *, size_t, const char *) +_talloc_move: void *(const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +_talloc_realloc: void *(const void *, void *, size_t, const char *) +_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +_talloc_reference_loc: void *(const void *, const void *, const char *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +_talloc_set_destructor: void (const void *, int (*)(void *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +_talloc_steal_loc: void *(const void *, const void *, const char *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, struct __va_list_tag *) +talloc_vasprintf_append: char *(char *, const char *, struct __va_list_tag *) +talloc_vasprintf_append_buffer: char *(char *, const char *, struct __va_list_tag *) +talloc_version_major: int (void) +talloc_version_minor: int (void) +_talloc_zero: void *(const void *, size_t, const char *) +_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.1.1.abi b/libatalk/libatalk-3.1.1.abi new file mode 100644 index 0000000..11fb887 --- /dev/null +++ b/libatalk/libatalk-3.1.1.abi @@ -0,0 +1,639 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_osx: int (struct adouble *, char *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +apply_ip_mask: void (struct sockaddr *, int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, va_list) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *, const void *, char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t) +dalloc_get: void *(const DALLOC_CTX *, ...) +dalloc_size: int (DALLOC_CTX *) +dalloc_strdup: char *(const void *, const char *) +dalloc_strndup: char *(const void *, const char *, size_t) +dalloc_value_for_key: void *(const DALLOC_CTX *, ...) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, lv_flags_t) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +_talloc: void *(const void *, size_t) +_talloc_array: void *(const void *, size_t, unsigned int, const char *) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +_talloc_free: int (void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +_talloc_get_type_abort: void *(const void *, const char *, const char *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +_talloc_memdup: void *(const void *, const void *, size_t, const char *) +_talloc_move: void *(const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +_talloc_realloc: void *(const void *, void *, size_t, const char *) +_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +_talloc_reference_loc: void *(const void *, const void *, const char *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +_talloc_set_destructor: void (const void *, int (*)(void *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +_talloc_steal_loc: void *(const void *, const void *, const char *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, va_list) +talloc_vasprintf_append: char *(char *, const char *, va_list) +talloc_vasprintf_append_buffer: char *(char *, const char *, va_list) +talloc_version_major: int (void) +talloc_version_minor: int (void) +_talloc_zero: void *(const void *, size_t, const char *) +_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +tdb_transaction_cancel: int (struct tdb_context *) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.1.2.abi b/libatalk/libatalk-3.1.2.abi new file mode 100644 index 0000000..4535bbc --- /dev/null +++ b/libatalk/libatalk-3.1.2.abi @@ -0,0 +1,639 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_osx: int (struct adouble *, char *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +apply_ip_mask: void (struct sockaddr *, int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, va_list) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(struct vol *, char *, int) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t) +dalloc_get: void *(const DALLOC_CTX *, ...) +dalloc_size: int (DALLOC_CTX *) +dalloc_strdup: char *(const void *, const char *) +dalloc_strndup: char *(const void *, const char *, size_t) +dalloc_value_for_key: void *(const DALLOC_CTX *, ...) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, lv_flags_t) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +_talloc: void *(const void *, size_t) +_talloc_array: void *(const void *, size_t, unsigned int, const char *) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +_talloc_free: int (void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +_talloc_get_type_abort: void *(const void *, const char *, const char *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +_talloc_memdup: void *(const void *, const void *, size_t, const char *) +_talloc_move: void *(const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +_talloc_realloc: void *(const void *, void *, size_t, const char *) +_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +_talloc_reference_loc: void *(const void *, const void *, const char *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +_talloc_set_destructor: void (const void *, int (*)(void *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +_talloc_steal_loc: void *(const void *, const void *, const char *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, va_list) +talloc_vasprintf_append: char *(char *, const char *, va_list) +talloc_vasprintf_append_buffer: char *(char *, const char *, va_list) +talloc_version_major: int (void) +talloc_version_minor: int (void) +_talloc_zero: void *(const void *, size_t, const char *) +_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +tdb_transaction_cancel: int (struct tdb_context *) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.1.3.abi b/libatalk/libatalk-3.1.3.abi new file mode 100644 index 0000000..9cc45db --- /dev/null +++ b/libatalk/libatalk-3.1.3.abi @@ -0,0 +1,634 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const unsigned long) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const unsigned long) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_osx: int (struct adouble *, char *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +apply_ip_mask: void (struct sockaddr *, int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_mysql_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_close: void (struct _cnid_db *) +cnid_mysql_delete: int (struct _cnid_db *, const cnid_t) +cnid_mysql_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_mysql_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_mysql_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_mysql_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_module: {name = "mysql", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_mysql_open: struct _cnid_db *(struct cnid_open_args *) +cnid_mysql_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_mysql_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_wipe: int (struct _cnid_db *) +cnid_open: struct _cnid_db *(struct vol *, char *, int) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t) +dalloc_get: void *(const DALLOC_CTX *, ...) +dalloc_size: int (DALLOC_CTX *) +dalloc_strdup: char *(const void *, const char *) +dalloc_strndup: char *(const void *, const char *, size_t) +dalloc_value_for_key: void *(const DALLOC_CTX *, ...) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +dequeue: void *(q_t *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, lv_flags_t) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, struct __va_list_tag *) +talloc_vasprintf_append: char *(char *, const char *, struct __va_list_tag *) +talloc_vasprintf_append_buffer: char *(char *, const char *, struct __va_list_tag *) +talloc_version_major: int (void) +talloc_version_minor: int (void) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.1.4.abi b/libatalk/libatalk-3.1.4.abi new file mode 100644 index 0000000..e69a944 --- /dev/null +++ b/libatalk/libatalk-3.1.4.abi @@ -0,0 +1,635 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const unsigned long) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const unsigned long) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_osx: int (struct adouble *, char *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +apply_ip_mask: void (struct sockaddr *, int) +asev_add_fd: _Bool (struct asev *, int, enum asev_fdtype, void *) +asev_del_fd: _Bool (struct asev *, int) +asev_init: struct asev *(int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_mysql_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_close: void (struct _cnid_db *) +cnid_mysql_delete: int (struct _cnid_db *, const cnid_t) +cnid_mysql_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_mysql_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_mysql_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_mysql_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_module: {name = "mysql", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_mysql_open: struct _cnid_db *(struct cnid_open_args *) +cnid_mysql_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_mysql_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_wipe: int (struct _cnid_db *) +cnid_open: struct _cnid_db *(struct vol *, char *, int) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t) +dalloc_get: void *(const DALLOC_CTX *, ...) +dalloc_size: int (DALLOC_CTX *) +dalloc_strdup: char *(const void *, const char *) +dalloc_strndup: char *(const void *, const char *, size_t) +dalloc_value_for_key: void *(const DALLOC_CTX *, ...) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +dequeue: void *(q_t *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +find_charset_functions: struct charset_functions *(const char *) +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, lv_flags_t) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, struct __va_list_tag *) +talloc_vasprintf_append: char *(char *, const char *, struct __va_list_tag *) +talloc_vasprintf_append_buffer: char *(char *, const char *, struct __va_list_tag *) +talloc_version_major: int (void) +talloc_version_minor: int (void) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.1.5.abi b/libatalk/libatalk-3.1.5.abi new file mode 100644 index 0000000..e69a944 --- /dev/null +++ b/libatalk/libatalk-3.1.5.abi @@ -0,0 +1,635 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const unsigned long) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const unsigned long) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_osx: int (struct adouble *, char *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +apply_ip_mask: void (struct sockaddr *, int) +asev_add_fd: _Bool (struct asev *, int, enum asev_fdtype, void *) +asev_del_fd: _Bool (struct asev *, int) +asev_init: struct asev *(int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_mysql_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_close: void (struct _cnid_db *) +cnid_mysql_delete: int (struct _cnid_db *, const cnid_t) +cnid_mysql_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_mysql_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_mysql_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_mysql_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_module: {name = "mysql", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_mysql_open: struct _cnid_db *(struct cnid_open_args *) +cnid_mysql_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_mysql_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_wipe: int (struct _cnid_db *) +cnid_open: struct _cnid_db *(struct vol *, char *, int) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t) +dalloc_get: void *(const DALLOC_CTX *, ...) +dalloc_size: int (DALLOC_CTX *) +dalloc_strdup: char *(const void *, const char *) +dalloc_strndup: char *(const void *, const char *, size_t) +dalloc_value_for_key: void *(const DALLOC_CTX *, ...) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +dequeue: void *(q_t *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +find_charset_functions: struct charset_functions *(const char *) +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, lv_flags_t) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, struct __va_list_tag *) +talloc_vasprintf_append: char *(char *, const char *, struct __va_list_tag *) +talloc_vasprintf_append_buffer: char *(char *, const char *, struct __va_list_tag *) +talloc_version_major: int (void) +talloc_version_minor: int (void) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/libatalk-3.1.6.abi b/libatalk/libatalk-3.1.6.abi new file mode 100644 index 0000000..e69a944 --- /dev/null +++ b/libatalk/libatalk-3.1.6.abi @@ -0,0 +1,635 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const unsigned long) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const unsigned long) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_osx: int (struct adouble *, char *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +apply_ip_mask: void (struct sockaddr *, int) +asev_add_fd: _Bool (struct asev *, int, enum asev_fdtype, void *) +asev_del_fd: _Bool (struct asev *, int) +asev_init: struct asev *(int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_mysql_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_close: void (struct _cnid_db *) +cnid_mysql_delete: int (struct _cnid_db *, const cnid_t) +cnid_mysql_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_mysql_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_mysql_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_mysql_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_module: {name = "mysql", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0} +cnid_mysql_open: struct _cnid_db *(struct cnid_open_args *) +cnid_mysql_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_mysql_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_mysql_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_mysql_wipe: int (struct _cnid_db *) +cnid_open: struct _cnid_db *(struct vol *, char *, int) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t) +dalloc_get: void *(const DALLOC_CTX *, ...) +dalloc_size: int (DALLOC_CTX *) +dalloc_strdup: char *(const void *, const char *) +dalloc_strndup: char *(const void *, const char *, size_t) +dalloc_value_for_key: void *(const DALLOC_CTX *, ...) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +dequeue: void *(q_t *) +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +find_charset_functions: struct charset_functions *(const char *) +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupfilter: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userfilter: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *, lv_flags_t) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, struct __va_list_tag *) +talloc_vasprintf_append: char *(char *, const char *, struct __va_list_tag *) +talloc_vasprintf_append_buffer: char *(char *, const char *, struct __va_list_tag *) +talloc_version_major: int (void) +talloc_version_minor: int (void) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/talloc/Makefile.am b/libatalk/talloc/Makefile.am new file mode 100644 index 0000000..8616eac --- /dev/null +++ b/libatalk/talloc/Makefile.am @@ -0,0 +1,4 @@ +# Makefile.am for libatalk/talloc/ + +noinst_LTLIBRARIES = libtalloc.la +libtalloc_la_SOURCES = talloc.c dalloc.c diff --git a/libatalk/talloc/Makefile.in b/libatalk/talloc/Makefile.in new file mode 100644 index 0000000..d8b52c2 --- /dev/null +++ b/libatalk/talloc/Makefile.in @@ -0,0 +1,662 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/talloc/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/talloc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libtalloc_la_LIBADD = +am_libtalloc_la_OBJECTS = talloc.lo dalloc.lo +libtalloc_la_OBJECTS = $(am_libtalloc_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libtalloc_la_SOURCES) +DIST_SOURCES = $(libtalloc_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libtalloc.la +libtalloc_la_SOURCES = talloc.c dalloc.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/talloc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/talloc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libtalloc.la: $(libtalloc_la_OBJECTS) $(libtalloc_la_DEPENDENCIES) $(EXTRA_libtalloc_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libtalloc_la_OBJECTS) $(libtalloc_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dalloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/talloc.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/talloc/dalloc.c b/libatalk/talloc/dalloc.c new file mode 100644 index 0000000..99dd7ec --- /dev/null +++ b/libatalk/talloc/dalloc.c @@ -0,0 +1,280 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ + +/*! + @file + Typesafe, dynamic object store based on talloc + + Usage: + + // + // Define some terminal types: + // + + // A key/value store aka dictionary that supports retrieving elements by key + typedef dict_t DALLOC_CTX; + + // An ordered set that can store different objects which can be retrieved by number + typedef set_t DALLOC_CTX; + + // + // Create an dalloc object and add elementes of different type + // + + // Allocate a new talloc context + TALLOC_CTX *mem_ctx = talloc_new(NULL); + // Create a new dalloc object + DALLOC_CTX *d = talloc_zero(mem_ctx, DALLOC_CTX); + + // Store an int value in the object + uint64_t i = 1; + dalloc_add_copy(d, &i, uint64_t); + + // Store a string + char *str = dalloc_strdup(d, "hello world"); + dalloc_add(d, str, char *); + + // Add a nested object, you later can't fetch this directly + DALLOC_CTX *nested = talloc_zero(d, DALLOC_CTX); + dalloc_add(d, nested, DALLOC_CTX); + + // Add an int value to the nested object, this can be fetched + i = 2; + dalloc_add_copy(nested, &i, uint64_t); + + // Add a nested set + set_t *set = talloc_zero(nested, set_t); + dalloc_add(nested, set, set_t); + + // Add an int value to the set + i = 3; + dalloc_add_copy(set, &i, uint64_t); + + // Add a dictionary (key/value store) + dict_t *dict = talloc_zero(nested, dict_t); + dalloc_add(nested, dict, dict_t); + + // Store a string as key in the dict + str = dalloc_strdup(d, "key"); + dalloc_add(dict, str, char *); + + // Add a value for the key + i = 4; + dalloc_add_copy(dict, &i, uint64_t); + + // + // Fetching value references + // You can fetch anything that is not a DALLOC_CTXs, because passing + // "DALLOC_CTXs" as type to the functions dalloc_get() and dalloc_value_for_key() + // tells the function to step into that object and expect more arguments that specify + // which element to fetch. + // + + // Get reference to an objects element by position + uint64_t *p = dalloc_get(d, "uint64_t", 0); + // p now points to the first int with a value of 1 + + // Get reference to the "hello world" string + str = dalloc_get(d, "char *", 1); + + // You can't fetch a pure DALLOC_CTX + nested = dalloc_get(d, "DALLOC_CTX", 2); + // But you can do this + p = dalloc_get(d, "DALLOC_CTX", 2, "uint64_t", 0); + // p now points to the value 2 + + // You can fetch types that are typedefd DALLOC_CTXs + set = dalloc_get(d, "DALLOC_CTX", 2, "set_t", 1); + + // Fetch int from set, note that you must use DALLOC_CTX as type for the set + p = dalloc_get(d, "DALLOC_CTX", 2, "DALLOC_CTX", 1, "uint64_t", 0); + // p points to 3 + + // Fetch value by key from dictionary + p = dalloc_value_for_key(d, "DALLOC_CTX", 2, "DALLOC_CTX", 2, "key"); + // p now point to 4 +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Use dalloc_add_copy() macro, not this function */ +int dalloc_add_talloc_chunk(DALLOC_CTX *dd, void *talloc_chunk, void *obj, size_t size) +{ + if (talloc_chunk) { + /* Called from dalloc_add_copy() macro */ + dd->dd_talloc_array = talloc_realloc(dd, + dd->dd_talloc_array, + void *, + talloc_array_length(dd->dd_talloc_array) + 1); + memcpy(talloc_chunk, obj, size); + dd->dd_talloc_array[talloc_array_length(dd->dd_talloc_array) - 1] = talloc_chunk; + } else { + /* Called from dalloc_add() macro */ + dd->dd_talloc_array = talloc_realloc(dd, + dd->dd_talloc_array, + void *, + talloc_array_length(dd->dd_talloc_array) + 1); + dd->dd_talloc_array[talloc_array_length(dd->dd_talloc_array) - 1] = obj; + + } + return 0; +} + +/* Get number of elements, returns 0 if the structure is empty or not initialized */ +int dalloc_size(DALLOC_CTX *d) +{ + if (!d || !d->dd_talloc_array) + return 0; + return talloc_array_length(d->dd_talloc_array); +} + +/* + * Get pointer to value from a DALLOC object + * + * Returns pointer to object from a DALLOC object. Nested object interation + * is supported by using the type string "DALLOC_CTX". Any other type string + * designates the requested objects type. + */ +void *dalloc_get(const DALLOC_CTX *d, ...) +{ + EC_INIT; + void *p = NULL; + va_list args; + const char *type; + int elem; + const char *elemtype; + + va_start(args, d); + type = va_arg(args, const char *); + + while (STRCMP(type, ==, "DALLOC_CTX")) { + elem = va_arg(args, int); + if (elem >= talloc_array_length(d->dd_talloc_array)) { + LOG(log_error, logtype_sl, "dalloc_get(%s): bound check error: %d >= %d", + type, elem >= talloc_array_length(d->dd_talloc_array)); + EC_FAIL; + } + d = d->dd_talloc_array[elem]; + type = va_arg(args, const char *); + } + + elem = va_arg(args, int); + if (elem >= talloc_array_length(d->dd_talloc_array)) { + LOG(log_error, logtype_sl, "dalloc_get(%s): bound check error: %d >= %d", + type, elem, talloc_array_length(d->dd_talloc_array)); + EC_FAIL; + } + + if (!(p = talloc_check_name(d->dd_talloc_array[elem], type))) { + LOG(log_error, logtype_sl, "dalloc_get(%d/%s): type mismatch: %s", + type, elem, talloc_get_name(d->dd_talloc_array[elem])); + } + + va_end(args); + +EC_CLEANUP: + if (ret != 0) + p = NULL; + return p; +} + +void *dalloc_value_for_key(const DALLOC_CTX *d, ...) +{ + EC_INIT; + void *p = NULL; + va_list args; + const char *type; + int elem; + const char *elemtype; + char *s; + + va_start(args, d); + type = va_arg(args, const char *); + + while (STRCMP(type, ==, "DALLOC_CTX")) { + elem = va_arg(args, int); + AFP_ASSERT(elem < talloc_array_length(d->dd_talloc_array)); + d = d->dd_talloc_array[elem]; + type = va_arg(args, const char *); + } + + for (elem = 0; elem + 1 < talloc_array_length(d->dd_talloc_array); elem += 2) { + if (STRCMP(talloc_get_name(d->dd_talloc_array[elem]), !=, "char *")) { + LOG(log_error, logtype_default, "dalloc_value_for_key: key not a string: %s", + talloc_get_name(d->dd_talloc_array[elem])); + EC_FAIL; + } + if (STRCMP((char *)d->dd_talloc_array[elem], ==, type)) { + p = d->dd_talloc_array[elem + 1]; + break; + } + } + va_end(args); + +EC_CLEANUP: + if (ret != 0) + p = NULL; + return p; +} + +char *dalloc_strdup(const void *ctx, const char *string) +{ + EC_INIT; + char *p; + + EC_NULL( p = talloc_strdup(ctx, string) ); + talloc_set_name(p, "char *"); + +EC_CLEANUP: + if (ret != 0) { + if (p) + talloc_free(p); + p = NULL; + } + return p; +} + +char *dalloc_strndup(const void *ctx, const char *string, size_t n) +{ + EC_INIT; + char *p; + + EC_NULL( p = talloc_strndup(ctx, string, n) ); + talloc_set_name(p, "char *"); + +EC_CLEANUP: + if (ret != 0) { + if (p) + talloc_free(p); + p = NULL; + } + return p; +} diff --git a/libatalk/talloc/talloc.c b/libatalk/talloc/talloc.c new file mode 100644 index 0000000..78dffa8 --- /dev/null +++ b/libatalk/talloc/talloc.c @@ -0,0 +1,2379 @@ +/* + Samba Unix SMB/CIFS implementation. + + Samba trivial allocation library - new interface + + NOTE: Please read talloc_guide.txt for full documentation + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +/* + inspired by http://swapped.cc/halloc/ +*/ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include + +#define _PUBLIC_ extern + +/** + * pointer difference macro + */ +#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) + + +#ifdef TALLOC_BUILD_VERSION_MAJOR +#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR) +#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR" +#endif +#endif + +#ifdef TALLOC_BUILD_VERSION_MINOR +#if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR) +#error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR" +#endif +#endif + +/* Special macros that are no-ops except when run under Valgrind on + * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */ +#ifdef HAVE_VALGRIND_MEMCHECK_H + /* memcheck.h includes valgrind.h */ +#include +#elif defined(HAVE_VALGRIND_H) +#include +#endif + +/* use this to force every realloc to change the pointer, to stress test + code that might not cope */ +#define ALWAYS_REALLOC 0 + + +#define MAX_TALLOC_SIZE 0x10000000 +#define TALLOC_MAGIC_BASE 0xe814ec70 +#define TALLOC_MAGIC ( \ + TALLOC_MAGIC_BASE + \ + (TALLOC_VERSION_MAJOR << 12) + \ + (TALLOC_VERSION_MINOR << 4) \ +) + +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 +#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */ +#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */ +#define TALLOC_MAGIC_REFERENCE ((const char *)1) + +/* by default we abort when given a bad pointer (such as when talloc_free() is called + on a pointer that came from malloc() */ +#ifndef TALLOC_ABORT +#define TALLOC_ABORT(reason) abort() +#endif + +#ifndef discard_const_p +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) +#else +# define discard_const_p(type, ptr) ((type *)(ptr)) +#endif +#endif + +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#else +#ifndef likely +#define likely(x) (x) +#endif +#ifndef unlikely +#define unlikely(x) (x) +#endif +#endif + +/* this null_context is only used if talloc_enable_leak_report() or + talloc_enable_leak_report_full() is called, otherwise it remains + NULL +*/ +static void *null_context; +static void *autofree_context; + +/* used to enable fill of memory on free, which can be useful for + * catching use after free errors when valgrind is too slow + */ +static struct { + bool initialised; + bool enabled; + uint8_t fill_value; +} talloc_fill; + +#define TALLOC_FILL_ENV "TALLOC_FREE_FILL" + +/* + * do not wipe the header, to allow the + * double-free logic to still work + */ +#define TC_INVALIDATE_FULL_FILL_CHUNK(_tc) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = (_tc)->size; \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) +/* Mark the whole chunk as not accessable */ +#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { \ + size_t _flen = TC_HDR_SIZE + (_tc)->size; \ + char *_fptr = (char *)(_tc); \ + VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ +} while(0) +#else +#define TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc) do { } while (0) +#endif + +#define TC_INVALIDATE_FULL_CHUNK(_tc) do { \ + TC_INVALIDATE_FULL_FILL_CHUNK(_tc); \ + TC_INVALIDATE_FULL_VALGRIND_CHUNK(_tc); \ +} while (0) + +#define TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) +/* Mark the unused bytes not accessable */ +#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ +} while (0) +#else +#define TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) +#endif + +#define TC_INVALIDATE_SHRINK_CHUNK(_tc, _new_size) do { \ + TC_INVALIDATE_SHRINK_FILL_CHUNK(_tc, _new_size); \ + TC_INVALIDATE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \ +} while (0) + +#define TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) +/* Mark the unused bytes as undefined */ +#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { \ + size_t _flen = (_tc)->size - (_new_size); \ + char *_fptr = (char *)TC_PTR_FROM_CHUNK(_tc); \ + _fptr += (_new_size); \ + VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \ +} while (0) +#else +#define TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) +#endif + +#define TC_UNDEFINE_SHRINK_CHUNK(_tc, _new_size) do { \ + TC_UNDEFINE_SHRINK_FILL_CHUNK(_tc, _new_size); \ + TC_UNDEFINE_SHRINK_VALGRIND_CHUNK(_tc, _new_size); \ +} while (0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) +/* Mark the new bytes as undefined */ +#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { \ + size_t _old_used = TC_HDR_SIZE + (_tc)->size; \ + size_t _new_used = TC_HDR_SIZE + (_new_size); \ + size_t _flen = _new_used - _old_used; \ + char *_fptr = _old_used + (char *)(_tc); \ + VALGRIND_MAKE_MEM_UNDEFINED(_fptr, _flen); \ +} while (0) +#else +#define TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size) do { } while (0) +#endif + +#define TC_UNDEFINE_GROW_CHUNK(_tc, _new_size) do { \ + TC_UNDEFINE_GROW_VALGRIND_CHUNK(_tc, _new_size); \ +} while (0) + +struct talloc_reference_handle { + struct talloc_reference_handle *next, *prev; + void *ptr; + const char *location; +}; + +typedef int (*talloc_destructor_t)(void *); + +struct talloc_chunk { + struct talloc_chunk *next, *prev; + struct talloc_chunk *parent, *child; + struct talloc_reference_handle *refs; + talloc_destructor_t destructor; + const char *name; + size_t size; + unsigned flags; + + /* + * "pool" has dual use: + * + * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool" + * marks the end of the currently allocated area. + * + * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool" + * is a pointer to the struct talloc_chunk of the pool that it was + * allocated from. This way children can quickly find the pool to chew + * from. + */ + void *pool; +}; + +/* 16 byte alignment seems to keep everyone happy */ +#define TC_ALIGN16(s) (((s)+15)&~15) +#define TC_HDR_SIZE TC_ALIGN16(sizeof(struct talloc_chunk)) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) + +_PUBLIC_ int talloc_version_major(void) +{ + return TALLOC_VERSION_MAJOR; +} + +_PUBLIC_ int talloc_version_minor(void) +{ + return TALLOC_VERSION_MINOR; +} + +static void (*talloc_log_fn)(const char *message); + +_PUBLIC_ void talloc_set_log_fn(void (*log_fn)(const char *message)) +{ + talloc_log_fn = log_fn; +} + +static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +static void talloc_log(const char *fmt, ...) +{ + va_list ap; + char *message; + + if (!talloc_log_fn) { + return; + } + + va_start(ap, fmt); + message = talloc_vasprintf(NULL, fmt, ap); + va_end(ap); + + talloc_log_fn(message); + talloc_free(message); +} + +static void talloc_log_stderr(const char *message) +{ + fprintf(stderr, "%s", message); +} + +_PUBLIC_ void talloc_set_log_stderr(void) +{ + talloc_set_log_fn(talloc_log_stderr); +} + +static void (*talloc_abort_fn)(const char *reason); + +_PUBLIC_ void talloc_set_abort_fn(void (*abort_fn)(const char *reason)) +{ + talloc_abort_fn = abort_fn; +} + +static void talloc_abort(const char *reason) +{ + talloc_log("%s\n", reason); + + if (!talloc_abort_fn) { + TALLOC_ABORT(reason); + } + + talloc_abort_fn(reason); +} + +static void talloc_abort_magic(unsigned magic) +{ + unsigned striped = magic - TALLOC_MAGIC_BASE; + unsigned major = (striped & 0xFFFFF000) >> 12; + unsigned minor = (striped & 0x00000FF0) >> 4; + talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n", + magic, major, minor, + TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR); + talloc_abort("Bad talloc magic value - wrong talloc version used/mixed"); +} + +static void talloc_abort_access_after_free(void) +{ + talloc_abort("Bad talloc magic value - access after free"); +} + +static void talloc_abort_unknown_value(void) +{ + talloc_abort("Bad talloc magic value - unknown value"); +} + +/* panic if we get a bad magic value */ +static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +{ + const char *pp = (const char *)ptr; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); + if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { + if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) { + talloc_abort_magic(tc->flags & (~0xF)); + return NULL; + } + + if (tc->flags & TALLOC_FLAG_FREE) { + talloc_log("talloc: access after free error - first free may be at %s\n", tc->name); + talloc_abort_access_after_free(); + return NULL; + } else { + talloc_abort_unknown_value(); + return NULL; + } + } + return tc; +} + +/* hook into the front of the list */ +#define _TLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define _TLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + + +/* + return the parent chunk of a pointer +*/ +static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); + while (tc->prev) tc=tc->prev; + + return tc->parent; +} + +_PUBLIC_ void *talloc_parent(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; +} + +/* + find parents name +*/ +_PUBLIC_ const char *talloc_parent_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? tc->name : NULL; +} + +/* + A pool carries an in-pool object count count in the first 16 bytes. + bytes. This is done to support talloc_steal() to a parent outside of the + pool. The count includes the pool itself, so a talloc_free() on a pool will + only destroy the pool if the count has dropped to zero. A talloc_free() of a + pool member will reduce the count, and eventually also call free(3) on the + pool memory. + + The object count is not put into "struct talloc_chunk" because it is only + relevant for talloc pools and the alignment to 16 bytes would increase the + memory footprint of each talloc chunk by those 16 bytes. +*/ + +#define TALLOC_POOL_HDR_SIZE 16 + +#define TC_POOL_SPACE_LEFT(_pool_tc) \ + PTR_DIFF(TC_HDR_SIZE + (_pool_tc)->size + (char *)(_pool_tc), \ + (_pool_tc)->pool) + +#define TC_POOL_FIRST_CHUNK(_pool_tc) \ + ((void *)(TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE + (char *)(_pool_tc))) + +#define TC_POOLMEM_CHUNK_SIZE(_tc) \ + TC_ALIGN16(TC_HDR_SIZE + (_tc)->size) + +#define TC_POOLMEM_NEXT_CHUNK(_tc) \ + ((void *)(TC_POOLMEM_CHUNK_SIZE(tc) + (char*)(_tc))) + +/* Mark the whole remaining pool as not accessable */ +#define TC_INVALIDATE_FILL_POOL(_pool_tc) do { \ + if (unlikely(talloc_fill.enabled)) { \ + size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \ + char *_fptr = (char *)(_pool_tc)->pool; \ + memset(_fptr, talloc_fill.fill_value, _flen); \ + } \ +} while(0) + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) +/* Mark the whole remaining pool as not accessable */ +#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { \ + size_t _flen = TC_POOL_SPACE_LEFT(_pool_tc); \ + char *_fptr = (char *)(_pool_tc)->pool; \ + VALGRIND_MAKE_MEM_NOACCESS(_fptr, _flen); \ +} while(0) +#else +#define TC_INVALIDATE_VALGRIND_POOL(_pool_tc) do { } while (0) +#endif + +#define TC_INVALIDATE_POOL(_pool_tc) do { \ + TC_INVALIDATE_FILL_POOL(_pool_tc); \ + TC_INVALIDATE_VALGRIND_POOL(_pool_tc); \ +} while (0) + +static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) +{ + return (unsigned int *)((char *)tc + TC_HDR_SIZE); +} + +/* + Allocate from a pool +*/ + +static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, + size_t size) +{ + struct talloc_chunk *pool_ctx = NULL; + size_t space_left; + struct talloc_chunk *result; + size_t chunk_size; + + if (parent == NULL) { + return NULL; + } + + if (parent->flags & TALLOC_FLAG_POOL) { + pool_ctx = parent; + } + else if (parent->flags & TALLOC_FLAG_POOLMEM) { + pool_ctx = (struct talloc_chunk *)parent->pool; + } + + if (pool_ctx == NULL) { + return NULL; + } + + space_left = TC_POOL_SPACE_LEFT(pool_ctx); + + /* + * Align size to 16 bytes + */ + chunk_size = TC_ALIGN16(size); + + if (space_left < chunk_size) { + return NULL; + } + + result = (struct talloc_chunk *)pool_ctx->pool; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_MAKE_MEM_UNDEFINED(result, size); +#endif + + pool_ctx->pool = (void *)((char *)result + chunk_size); + + result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM; + result->pool = pool_ctx; + + *talloc_pool_objectcount(pool_ctx) += 1; + + return result; +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +static inline void *__talloc(const void *context, size_t size) +{ + struct talloc_chunk *tc = NULL; + + if (unlikely(context == NULL)) { + context = null_context; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + if (context != NULL) { + tc = talloc_alloc_pool(talloc_chunk_from_ptr(context), + TC_HDR_SIZE+size); + } + + if (tc == NULL) { + tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); + if (unlikely(tc == NULL)) return NULL; + tc->flags = TALLOC_MAGIC; + tc->pool = NULL; + } + + tc->size = size; + tc->destructor = NULL; + tc->child = NULL; + tc->name = NULL; + tc->refs = NULL; + + if (likely(context)) { + struct talloc_chunk *parent = talloc_chunk_from_ptr(context); + + if (parent->child) { + parent->child->parent = NULL; + tc->next = parent->child; + tc->next->prev = tc; + } else { + tc->next = NULL; + } + tc->parent = parent; + tc->prev = NULL; + parent->child = tc; + } else { + tc->next = tc->prev = tc->parent = NULL; + } + + return TC_PTR_FROM_CHUNK(tc); +} + +/* + * Create a talloc pool + */ + +_PUBLIC_ void *talloc_pool(const void *context, size_t size) +{ + void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); + struct talloc_chunk *tc; + + if (unlikely(result == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(result); + + tc->flags |= TALLOC_FLAG_POOL; + tc->pool = TC_POOL_FIRST_CHUNK(tc); + + *talloc_pool_objectcount(tc) = 1; + + TC_INVALIDATE_POOL(tc); + + return result; +} + +/* + setup a destructor to be called on free of a pointer + the destructor should return 0 on success, or -1 on failure. + if the destructor fails then the free is failed, and the memory can + be continued to be used +*/ +_PUBLIC_ void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->destructor = destructor; +} + +/* + increase the reference count on a piece of memory. +*/ +_PUBLIC_ int talloc_increase_ref_count(const void *ptr) +{ + if (unlikely(!talloc_reference(null_context, ptr))) { + return -1; + } + return 0; +} + +/* + helper for talloc_reference() + + this is referenced by a function pointer and should not be inline +*/ +static int talloc_reference_destructor(struct talloc_reference_handle *handle) +{ + struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr); + _TLIST_REMOVE(ptr_tc->refs, handle); + return 0; +} + +/* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +static inline void _talloc_set_name_const(const void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + +/* + internal talloc_named_const() +*/ +static inline void *_talloc_named_const(const void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) { + return NULL; + } + + _talloc_set_name_const(ptr, name); + + return ptr; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +_PUBLIC_ void *_talloc_reference_loc(const void *context, const void *ptr, const char *location) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *handle; + if (unlikely(ptr == NULL)) return NULL; + + tc = talloc_chunk_from_ptr(ptr); + handle = (struct talloc_reference_handle *)_talloc_named_const(context, + sizeof(struct talloc_reference_handle), + TALLOC_MAGIC_REFERENCE); + if (unlikely(handle == NULL)) return NULL; + + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + handle->ptr = discard_const_p(void, ptr); + handle->location = location; + _TLIST_ADD(tc->refs, handle); + return handle->ptr; +} + +static void *_talloc_steal_internal(const void *new_ctx, const void *ptr); + +static inline void _talloc_free_poolmem(struct talloc_chunk *tc, + const char *location) +{ + struct talloc_chunk *pool; + void *next_tc; + unsigned int *pool_object_count; + + pool = (struct talloc_chunk *)tc->pool; + next_tc = TC_POOLMEM_NEXT_CHUNK(tc); + + tc->flags |= TALLOC_FLAG_FREE; + + /* we mark the freed memory with where we called the free + * from. This means on a double free error we can report where + * the first free came from + */ + tc->name = location; + + TC_INVALIDATE_FULL_CHUNK(tc); + + pool_object_count = talloc_pool_objectcount(pool); + + if (unlikely(*pool_object_count == 0)) { + talloc_abort("Pool object count zero!"); + return; + } + + *pool_object_count -= 1; + + if (unlikely(*pool_object_count == 1 && !(pool->flags & TALLOC_FLAG_FREE))) { + /* + * if there is just one object left in the pool + * and pool->flags does not have TALLOC_FLAG_FREE, + * it means this is the pool itself and + * the rest is available for new objects + * again. + */ + pool->pool = TC_POOL_FIRST_CHUNK(pool); + TC_INVALIDATE_POOL(pool); + } else if (unlikely(*pool_object_count == 0)) { + /* + * we mark the freed memory with where we called the free + * from. This means on a double free error we can report where + * the first free came from + */ + pool->name = location; + + TC_INVALIDATE_FULL_CHUNK(pool); + free(pool); + } else if (pool->pool == next_tc) { + /* + * if pool->pool still points to end of + * 'tc' (which is stored in the 'next_tc' variable), + * we can reclaim the memory of 'tc'. + */ + pool->pool = tc; + } +} + +static inline void _talloc_free_children_internal(struct talloc_chunk *tc, + void *ptr, + const char *location); + +/* + internal talloc_free call +*/ +static inline int _talloc_free_internal(void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + /* possibly initialised the talloc fill value */ + if (unlikely(!talloc_fill.initialised)) { + const char *fill = getenv(TALLOC_FILL_ENV); + if (fill != NULL) { + talloc_fill.enabled = true; + talloc_fill.fill_value = strtoul(fill, NULL, 0); + } + talloc_fill.initialised = true; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs)) { + int is_child; + /* check if this is a reference from a child or + * grandchild back to it's parent or grandparent + * + * in that case we need to remove the reference and + * call another instance of talloc_free() on the current + * pointer. + */ + is_child = talloc_is_parent(tc->refs, ptr); + _talloc_free_internal(tc->refs, location); + if (is_child) { + return _talloc_free_internal(ptr, location); + } + return -1; + } + + if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) { + /* we have a free loop - stop looping */ + return 0; + } + + if (unlikely(tc->destructor)) { + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; + return -1; + } + tc->destructor = NULL; + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + tc->prev = tc->next = NULL; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + _talloc_free_children_internal(tc, ptr, location); + + tc->flags |= TALLOC_FLAG_FREE; + + /* we mark the freed memory with where we called the free + * from. This means on a double free error we can report where + * the first free came from + */ + tc->name = location; + + if (tc->flags & TALLOC_FLAG_POOL) { + unsigned int *pool_object_count; + + pool_object_count = talloc_pool_objectcount(tc); + + if (unlikely(*pool_object_count == 0)) { + talloc_abort("Pool object count zero!"); + return 0; + } + + *pool_object_count -= 1; + + if (unlikely(*pool_object_count == 0)) { + TC_INVALIDATE_FULL_CHUNK(tc); + free(tc); + } + } else if (tc->flags & TALLOC_FLAG_POOLMEM) { + _talloc_free_poolmem(tc, location); + } else { + TC_INVALIDATE_FULL_CHUNK(tc); + free(tc); + } + return 0; +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +static void *_talloc_steal_internal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + + if (unlikely(!ptr)) { + return NULL; + } + + if (unlikely(new_ctx == NULL)) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(new_ctx == NULL)) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (unlikely(tc == new_tc || tc->parent == new_tc)) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + tc->prev = tc->next = NULL; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + return discard_const_p(void, ptr); +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +_PUBLIC_ void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) { + struct talloc_reference_handle *h; + + talloc_log("WARNING: talloc_steal with references at %s\n", + location); + + for (h=tc->refs; h; h=h->next) { + talloc_log("\treference at %s\n", + h->location); + } + } + +#if 0 + /* this test is probably too expensive to have on in the + normal build, but it useful for debugging */ + if (talloc_is_parent(new_ctx, ptr)) { + talloc_log("WARNING: stealing into talloc child at %s\n", location); + } +#endif + + return _talloc_steal_internal(new_ctx, ptr); +} + +/* + this is like a talloc_steal(), but you must supply the old + parent. This resolves the ambiguity in a talloc_steal() which is + called on a context that has more than one parent (via references) + + The old parent can be either a reference or a parent +*/ +_PUBLIC_ void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *h; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + if (old_parent == talloc_parent(ptr)) { + return _talloc_steal_internal(new_parent, ptr); + } + + tc = talloc_chunk_from_ptr(ptr); + for (h=tc->refs;h;h=h->next) { + if (talloc_parent(h) == old_parent) { + if (_talloc_steal_internal(new_parent, h) != h) { + return NULL; + } + return discard_const_p(void, ptr); + } + } + + /* it wasn't a parent */ + return NULL; +} + +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +static inline int talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (unlikely(context == NULL)) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *p = talloc_parent_chunk(h); + if (p == NULL) { + if (context == NULL) break; + } else if (TC_PTR_FROM_CHUNK(p) == context) { + break; + } + } + if (h == NULL) { + return -1; + } + + return _talloc_free_internal(h, __location__); +} + +/* + remove a specific parent context from a pointer. This is a more + controlled varient of talloc_free() +*/ +_PUBLIC_ int talloc_unlink(const void *context, void *ptr) +{ + struct talloc_chunk *tc_p, *new_p; + void *new_parent; + + if (ptr == NULL) { + return -1; + } + + if (context == NULL) { + context = null_context; + } + + if (talloc_unreference(context, ptr) == 0) { + return 0; + } + + if (context == NULL) { + if (talloc_parent_chunk(ptr) != NULL) { + return -1; + } + } else { + if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { + return -1; + } + } + + tc_p = talloc_chunk_from_ptr(ptr); + + if (tc_p->refs == NULL) { + return _talloc_free_internal(ptr, __location__); + } + + new_p = talloc_parent_chunk(tc_p->refs); + if (new_p) { + new_parent = TC_PTR_FROM_CHUNK(new_p); + } else { + new_parent = NULL; + } + + if (talloc_unreference(new_parent, ptr) != 0) { + return -1; + } + + _talloc_steal_internal(new_parent, ptr); + + return 0; +} + +/* + add a name to an existing pointer - va_list version +*/ +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = talloc_vasprintf(ptr, fmt, ap); + if (likely(tc->name)) { + _talloc_set_name_const(tc->name, ".name"); + } + return tc->name; +} + +/* + add a name to an existing pointer +*/ +_PUBLIC_ const char *talloc_set_name(const void *ptr, const char *fmt, ...) +{ + const char *name; + va_list ap; + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + return name; +} + + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +_PUBLIC_ void *talloc_named(const void *context, size_t size, const char *fmt, ...) +{ + va_list ap; + void *ptr; + const char *name; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free_internal(ptr, __location__); + return NULL; + } + + return ptr; +} + +/* + return the name of a talloc ptr, or "UNNAMED" +*/ +_PUBLIC_ const char *talloc_get_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) { + return ".reference"; + } + if (likely(tc->name)) { + return tc->name; + } + return "UNNAMED"; +} + + +/* + check if a pointer has the given name. If it does, return the pointer, + otherwise return NULL +*/ +_PUBLIC_ void *talloc_check_name(const void *ptr, const char *name) +{ + const char *pname; + if (unlikely(ptr == NULL)) return NULL; + pname = talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + return NULL; +} + +static void talloc_abort_type_missmatch(const char *location, + const char *name, + const char *expected) +{ + const char *reason; + + reason = talloc_asprintf(NULL, + "%s: Type mismatch: name[%s] expected[%s]", + location, + name?name:"NULL", + expected); + if (!reason) { + reason = "Type mismatch"; + } + + talloc_abort(reason); +} + +_PUBLIC_ void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) +{ + const char *pname; + + if (unlikely(ptr == NULL)) { + talloc_abort_type_missmatch(location, NULL, name); + return NULL; + } + + pname = talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + + talloc_abort_type_missmatch(location, pname, name); + return NULL; +} + +/* + this is for compatibility with older versions of talloc +*/ +_PUBLIC_ void *talloc_init(const char *fmt, ...) +{ + va_list ap; + void *ptr; + const char *name; + + ptr = __talloc(NULL, 0); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free_internal(ptr, __location__); + return NULL; + } + + return ptr; +} + +static inline void _talloc_free_children_internal(struct talloc_chunk *tc, + void *ptr, + const char *location) +{ + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(_talloc_free_internal(child, location) == -1)) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + _talloc_steal_internal(new_parent, child); + } + } +} + +/* + this is a replacement for the Samba3 talloc_destroy_pool functionality. It + should probably not be used in new code. It's in here to keep the talloc + code consistent across Samba 3 and 4. +*/ +_PUBLIC_ void talloc_free_children(void *ptr) +{ + struct talloc_chunk *tc_name = NULL; + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return; + } + + tc = talloc_chunk_from_ptr(ptr); + + /* we do not want to free the context name if it is a child .. */ + if (likely(tc->child)) { + for (tc_name = tc->child; tc_name; tc_name = tc_name->next) { + if (tc->name == TC_PTR_FROM_CHUNK(tc_name)) break; + } + if (tc_name) { + _TLIST_REMOVE(tc->child, tc_name); + if (tc->child) { + tc->child->parent = tc; + } + } + } + + _talloc_free_children_internal(tc, ptr, __location__); + + /* .. so we put it back after all other children have been freed */ + if (tc_name) { + if (tc->child) { + tc->child->parent = NULL; + } + tc_name->parent = tc; + _TLIST_ADD(tc->child, tc_name); + } +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +_PUBLIC_ void *_talloc(const void *context, size_t size) +{ + return __talloc(context, size); +} + +/* + externally callable talloc_set_name_const() +*/ +_PUBLIC_ void talloc_set_name_const(const void *ptr, const char *name) +{ + _talloc_set_name_const(ptr, name); +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +_PUBLIC_ void *talloc_named_const(const void *context, size_t size, const char *name) +{ + return _talloc_named_const(context, size, name); +} + +/* + free a talloc pointer. This also frees all child pointers of this + pointer recursively + + return 0 if the memory is actually freed, otherwise -1. The memory + will not be freed if the ref_count is > 1 or the destructor (if + any) returns non-zero +*/ +_PUBLIC_ int _talloc_free(void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs != NULL)) { + struct talloc_reference_handle *h; + + if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) { + /* in this case we do know which parent should + get this pointer, as there is really only + one parent */ + return talloc_unlink(null_context, ptr); + } + + talloc_log("ERROR: talloc_free with references at %s\n", + location); + + for (h=tc->refs; h; h=h->next) { + talloc_log("\treference at %s\n", + h->location); + } + return -1; + } + + return _talloc_free_internal(ptr, location); +} + + + +/* + A talloc version of realloc. The context argument is only used if + ptr is NULL +*/ +_PUBLIC_ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) +{ + struct talloc_chunk *tc; + void *new_ptr; + bool malloced = false; + struct talloc_chunk *pool_tc = NULL; + + /* size zero is equivalent to free() */ + if (unlikely(size == 0)) { + talloc_unlink(context, ptr); + return NULL; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + /* realloc(NULL) is equivalent to malloc() */ + if (ptr == NULL) { + return _talloc_named_const(context, size, name); + } + + tc = talloc_chunk_from_ptr(ptr); + + /* don't allow realloc on referenced pointers */ + if (unlikely(tc->refs)) { + return NULL; + } + + /* don't let anybody try to realloc a talloc_pool */ + if (unlikely(tc->flags & TALLOC_FLAG_POOL)) { + return NULL; + } + + /* don't let anybody try to realloc a talloc_pool */ + if (unlikely(tc->flags & TALLOC_FLAG_POOLMEM)) { + pool_tc = (struct talloc_chunk *)tc->pool; + } + +#if (ALWAYS_REALLOC == 0) + /* don't shrink if we have less than 1k to gain */ + if (size < tc->size) { + if (pool_tc) { + void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); + TC_INVALIDATE_SHRINK_CHUNK(tc, size); + tc->size = size; + if (next_tc == pool_tc->pool) { + pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); + } + return ptr; + } else if ((tc->size - size) < 1024) { + /* + * if we call TC_INVALIDATE_SHRINK_CHUNK() here + * we would need to call TC_UNDEFINE_GROW_CHUNK() + * after each realloc call, which slows down + * testing a lot :-(. + * + * That is why we only mark memory as undefined here. + */ + TC_UNDEFINE_SHRINK_CHUNK(tc, size); + + /* do not shrink if we have less than 1k to gain */ + tc->size = size; + return ptr; + } + } else if (tc->size == size) { + /* + * do not change the pointer if it is exactly + * the same size. + */ + return ptr; + } +#endif + + /* by resetting magic we catch users of the old memory */ + tc->flags |= TALLOC_FLAG_FREE; + +#if ALWAYS_REALLOC + if (pool_tc) { + new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); + *talloc_pool_objectcount(pool_tc) -= 1; + + if (new_ptr == NULL) { + new_ptr = malloc(TC_HDR_SIZE+size); + malloced = true; + } + + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + TC_INVALIDATE_FULL_CHUNK(tc); + } + } else { + new_ptr = malloc(size + TC_HDR_SIZE); + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE); + free(tc); + } + } +#else + if (pool_tc) { + void *next_tc = TC_POOLMEM_NEXT_CHUNK(tc); + size_t old_chunk_size = TC_POOLMEM_CHUNK_SIZE(tc); + size_t new_chunk_size = TC_ALIGN16(TC_HDR_SIZE + size); + size_t space_needed; + size_t space_left; + unsigned int chunk_count = *talloc_pool_objectcount(pool_tc); + + if (!(pool_tc->flags & TALLOC_FLAG_FREE)) { + chunk_count -= 1; + } + + if (chunk_count == 1) { + /* + * optimize for the case where 'tc' is the only + * chunk in the pool. + */ + space_needed = new_chunk_size; + space_left = pool_tc->size - TALLOC_POOL_HDR_SIZE; + + if (space_left >= space_needed) { + size_t old_used = TC_HDR_SIZE + tc->size; + size_t new_used = TC_HDR_SIZE + size; + pool_tc->pool = TC_POOL_FIRST_CHUNK(pool_tc); +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + /* + * we need to prepare the memmove into + * the unaccessable area. + */ + { + size_t diff = PTR_DIFF(tc, pool_tc->pool); + size_t flen = MIN(diff, old_used); + char *fptr = (char *)pool_tc->pool; + VALGRIND_MAKE_MEM_UNDEFINED(fptr, flen); + } +#endif + memmove(pool_tc->pool, tc, old_used); + new_ptr = pool_tc->pool; + + tc = (struct talloc_chunk *)new_ptr; + TC_UNDEFINE_GROW_CHUNK(tc, size); + + /* + * first we do not align the pool pointer + * because we want to invalidate the padding + * too. + */ + pool_tc->pool = new_used + (char *)new_ptr; + TC_INVALIDATE_POOL(pool_tc); + + /* now the aligned pointer */ + pool_tc->pool = new_chunk_size + (char *)new_ptr; + goto got_new_ptr; + } + + next_tc = NULL; + } + + if (new_chunk_size == old_chunk_size) { + TC_UNDEFINE_GROW_CHUNK(tc, size); + tc->flags &= ~TALLOC_FLAG_FREE; + tc->size = size; + return ptr; + } + + if (next_tc == pool_tc->pool) { + /* + * optimize for the case where 'tc' is the last + * chunk in the pool. + */ + space_needed = new_chunk_size - old_chunk_size; + space_left = TC_POOL_SPACE_LEFT(pool_tc); + + if (space_left >= space_needed) { + TC_UNDEFINE_GROW_CHUNK(tc, size); + tc->flags &= ~TALLOC_FLAG_FREE; + tc->size = size; + pool_tc->pool = TC_POOLMEM_NEXT_CHUNK(tc); + return ptr; + } + } + + new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); + + if (new_ptr == NULL) { + new_ptr = malloc(TC_HDR_SIZE+size); + malloced = true; + } + + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + + _talloc_free_poolmem(tc, __location__ "_talloc_realloc"); + } + } + else { + new_ptr = realloc(tc, size + TC_HDR_SIZE); + } +got_new_ptr: +#endif + if (unlikely(!new_ptr)) { + tc->flags &= ~TALLOC_FLAG_FREE; + return NULL; + } + + tc = (struct talloc_chunk *)new_ptr; + tc->flags &= ~TALLOC_FLAG_FREE; + if (malloced) { + tc->flags &= ~TALLOC_FLAG_POOLMEM; + } + if (tc->parent) { + tc->parent->child = tc; + } + if (tc->child) { + tc->child->parent = tc; + } + + if (tc->prev) { + tc->prev->next = tc; + } + if (tc->next) { + tc->next->prev = tc; + } + + tc->size = size; + _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); + + return TC_PTR_FROM_CHUNK(tc); +} + +/* + a wrapper around talloc_steal() for situations where you are moving a pointer + between two structures, and want the old pointer to be set to NULL +*/ +_PUBLIC_ void *_talloc_move(const void *new_ctx, const void *_pptr) +{ + const void **pptr = discard_const_p(const void *,_pptr); + void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr)); + (*pptr) = NULL; + return ret; +} + +/* + return the total size of a talloc pool (subtree) +*/ +_PUBLIC_ size_t talloc_total_size(const void *ptr) +{ + size_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) { + total = tc->size; + } + for (c=tc->child;c;c=c->next) { + total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + + return total; +} + +/* + return the total number of blocks in a talloc pool (subtree) +*/ +_PUBLIC_ size_t talloc_total_blocks(const void *ptr) +{ + size_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + total++; + for (c=tc->child;c;c=c->next) { + total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + + return total; +} + +/* + return the number of external references to a pointer +*/ +_PUBLIC_ size_t talloc_reference_count(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + size_t ret = 0; + + for (h=tc->refs;h;h=h->next) { + ret++; + } + return ret; +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +_PUBLIC_ void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data) +{ + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + callback(ptr, depth, max_depth, 0, private_data); + + if (max_depth >= 0 && depth >= max_depth) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); + callback(h->ptr, depth + 1, max_depth, 1, private_data); + } else { + talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; +} + +static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f) +{ + const char *name = talloc_get_name(ptr); + FILE *f = (FILE *)_f; + + if (is_ref) { + fprintf(f, "%*sreference to: %s\n", depth*4, "", name); + return; + } + + if (depth == 0) { + fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + (int)talloc_reference_count(ptr), ptr); + +#if 0 + fprintf(f, "content: "); + if (talloc_total_size(ptr)) { + int tot = talloc_total_size(ptr); + int i; + + for (i = 0; i < tot; i++) { + if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) { + fprintf(f, "%c", ((char *)ptr)[i]); + } else { + fprintf(f, "~%02x", ((char *)ptr)[i]); + } + } + } + fprintf(f, "\n"); +#endif +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +_PUBLIC_ void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) +{ + if (f) { + talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f); + fflush(f); + } +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +_PUBLIC_ void talloc_report_full(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, -1, f); +} + +/* + report on memory usage by all children of a pointer +*/ +_PUBLIC_ void talloc_report(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, 1, f); +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report(null_context, stderr); + } +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null_full(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report_full(null_context, stderr); + } +} + +/* + enable tracking of the NULL context +*/ +_PUBLIC_ void talloc_enable_null_tracking(void) +{ + if (null_context == NULL) { + null_context = _talloc_named_const(NULL, 0, "null_context"); + if (autofree_context != NULL) { + talloc_reparent(NULL, null_context, autofree_context); + } + } +} + +/* + enable tracking of the NULL context, not moving the autofree context + into the NULL context. This is needed for the talloc testsuite +*/ +_PUBLIC_ void talloc_enable_null_tracking_no_autofree(void) +{ + if (null_context == NULL) { + null_context = _talloc_named_const(NULL, 0, "null_context"); + } +} + +/* + disable tracking of the NULL context +*/ +_PUBLIC_ void talloc_disable_null_tracking(void) +{ + if (null_context != NULL) { + /* we have to move any children onto the real NULL + context */ + struct talloc_chunk *tc, *tc2; + tc = talloc_chunk_from_ptr(null_context); + for (tc2 = tc->child; tc2; tc2=tc2->next) { + if (tc2->parent == tc) tc2->parent = NULL; + if (tc2->prev == tc) tc2->prev = NULL; + } + for (tc2 = tc->next; tc2; tc2=tc2->next) { + if (tc2->parent == tc) tc2->parent = NULL; + if (tc2->prev == tc) tc2->prev = NULL; + } + tc->child = NULL; + tc->next = NULL; + } + talloc_free(null_context); + null_context = NULL; +} + +/* + enable leak reporting on exit +*/ +_PUBLIC_ void talloc_enable_leak_report(void) +{ + talloc_enable_null_tracking(); + atexit(talloc_report_null); +} + +/* + enable full leak reporting on exit +*/ +_PUBLIC_ void talloc_enable_leak_report_full(void) +{ + talloc_enable_null_tracking(); + atexit(talloc_report_null_full); +} + +/* + talloc and zero memory. +*/ +_PUBLIC_ void *_talloc_zero(const void *ctx, size_t size, const char *name) +{ + void *p = _talloc_named_const(ctx, size, name); + + if (p) { + memset(p, '\0', size); + } + + return p; +} + +/* + memdup with a talloc. +*/ +_PUBLIC_ void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) +{ + void *newp = _talloc_named_const(t, size, name); + + if (likely(newp)) { + memcpy(newp, p, size); + } + + return newp; +} + +static inline char *__talloc_strlendup(const void *t, const char *p, size_t len) +{ + char *ret; + + ret = (char *)__talloc(t, len + 1); + if (unlikely(!ret)) return NULL; + + memcpy(ret, p, len); + ret[len] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + +/* + strdup with a talloc +*/ +_PUBLIC_ char *talloc_strdup(const void *t, const char *p) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strlen(p)); +} + +/* + strndup with a talloc +*/ +_PUBLIC_ char *talloc_strndup(const void *t, const char *p, size_t n) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strnlen(p, n)); +} + +static inline char *__talloc_strlendup_append(char *s, size_t slen, + const char *a, size_t alen) +{ + char *ret; + + ret = talloc_realloc(NULL, s, char, slen + alen + 1); + if (unlikely(!ret)) return NULL; + + /* append the string and the trailing \0 */ + memcpy(&ret[slen], a, alen); + ret[slen+alen] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + +/* + * Appends at the end of the string. + */ +_PUBLIC_ char *talloc_strdup_append(char *s, const char *a) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strlen(a)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +_PUBLIC_ char *talloc_strdup_append_buffer(char *s, const char *a) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strlen(a)); +} + +/* + * Appends at the end of the string. + */ +_PUBLIC_ char *talloc_strndup_append(char *s, const char *a, size_t n) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +_PUBLIC_ char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strnlen(a, n)); +} + +_PUBLIC_ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) +{ + int len; + char *ret; + va_list ap2; + char c; + + /* this call looks strange, but it makes it work on older solaris boxes */ + va_copy(ap2, ap); + len = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + if (unlikely(len < 0)) { + return NULL; + } + + ret = (char *)__talloc(t, len+1); + if (unlikely(!ret)) return NULL; + + va_copy(ap2, ap); + vsnprintf(ret, len+1, fmt, ap2); + va_end(ap2); + + _talloc_set_name_const(ret, ret); + return ret; +} + + +/* + Perform string formatting, and return a pointer to newly allocated + memory holding the result, inside a memory pool. + */ +_PUBLIC_ char *talloc_asprintf(const void *t, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = talloc_vasprintf(t, fmt, ap); + va_end(ap); + return ret; +} + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) + PRINTF_ATTRIBUTE(3,0); + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) +{ + ssize_t alen; + va_list ap2; + char c; + + va_copy(ap2, ap); + alen = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + + if (alen <= 0) { + /* Either the vsnprintf failed or the format resulted in + * no characters being formatted. In the former case, we + * ought to return NULL, in the latter we ought to return + * the original string. Most current callers of this + * function expect it to never return NULL. + */ + return s; + } + + s = talloc_realloc(NULL, s, char, slen + alen + 1); + if (!s) return NULL; + + va_copy(ap2, ap); + vsnprintf(s + slen, alen + 1, fmt, ap2); + va_end(ap2); + + _talloc_set_name_const(s, s); + return s; +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Good for gradually + * accumulating output into a string buffer. Appends at the end + * of the string. + **/ +_PUBLIC_ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +{ + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap); +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Always appends at the + * end of the talloc'ed buffer, not the end of the string. + **/ +_PUBLIC_ char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_vaslenprintf_append(s, slen, fmt, ap); +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a string buffer. + */ +_PUBLIC_ char *talloc_asprintf_append(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append(s, fmt, ap); + va_end(ap); + return s; +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a buffer. + */ +_PUBLIC_ char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append_buffer(s, fmt, ap); + va_end(ap); + return s; +} + +/* + alloc an array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_named_const(ctx, el_size * count, name); +} + +/* + alloc an zero array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_zero(ctx, el_size * count, name); +} + +/* + realloc an array, checking for integer overflow in the array size +*/ +_PUBLIC_ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_realloc(ctx, ptr, el_size * count, name); +} + +/* + a function version of talloc_realloc(), so it can be passed as a function pointer + to libraries that want a realloc function (a realloc function encapsulates + all the basic capabilities of an allocation library, which is why this is useful) +*/ +_PUBLIC_ void *talloc_realloc_fn(const void *context, void *ptr, size_t size) +{ + return _talloc_realloc(context, ptr, size, NULL); +} + + +static int talloc_autofree_destructor(void *ptr) +{ + autofree_context = NULL; + return 0; +} + +static void talloc_autofree(void) +{ + talloc_free(autofree_context); +} + +/* + return a context which will be auto-freed on exit + this is useful for reducing the noise in leak reports +*/ +_PUBLIC_ void *talloc_autofree_context(void) +{ + if (autofree_context == NULL) { + autofree_context = _talloc_named_const(NULL, 0, "autofree_context"); + talloc_set_destructor(autofree_context, talloc_autofree_destructor); + atexit(talloc_autofree); + } + return autofree_context; +} + +_PUBLIC_ size_t talloc_get_size(const void *context) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + context = null_context; + } + if (context == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(context); + + return tc->size; +} + +/* + find a parent of this context that has the given name, if any +*/ +_PUBLIC_ void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return TC_PTR_FROM_CHUNK(tc); + } + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + return NULL; +} + +/* + show the parentage of a context +*/ +_PUBLIC_ void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + fflush(file); +} + +/* + return 1 if ptr is a parent of context +*/ +static int _talloc_is_parent(const void *context, const void *ptr, int depth) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(context); + while (tc && depth > 0) { + if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1; + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + depth--; + } + } + return 0; +} + +/* + return 1 if ptr is a parent of context +*/ +_PUBLIC_ int talloc_is_parent(const void *context, const void *ptr) +{ + return _talloc_is_parent(context, ptr, TALLOC_MAX_DEPTH); +} diff --git a/libatalk/tdb/Makefile.am b/libatalk/tdb/Makefile.am new file mode 100644 index 0000000..874baef --- /dev/null +++ b/libatalk/tdb/Makefile.am @@ -0,0 +1,16 @@ +# Makefile.am for libatalk/tdb/ + +noinst_LTLIBRARIES = libtdb.la +noinst_HEADERS = tdb_private.h +libtdb_la_SOURCES = check.c \ + dump.c \ + error.c \ + freelist.c \ + freelistcheck.c \ + io.c \ + lock.c \ + open.c \ + tdb.c \ + transaction.c \ + traverse.c + diff --git a/libatalk/tdb/Makefile.in b/libatalk/tdb/Makefile.in new file mode 100644 index 0000000..e16dc2e --- /dev/null +++ b/libatalk/tdb/Makefile.in @@ -0,0 +1,687 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/tdb/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/tdb +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libtdb_la_LIBADD = +am_libtdb_la_OBJECTS = check.lo dump.lo error.lo freelist.lo \ + freelistcheck.lo io.lo lock.lo open.lo tdb.lo transaction.lo \ + traverse.lo +libtdb_la_OBJECTS = $(am_libtdb_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libtdb_la_SOURCES) +DIST_SOURCES = $(libtdb_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libtdb.la +noinst_HEADERS = tdb_private.h +libtdb_la_SOURCES = check.c \ + dump.c \ + error.c \ + freelist.c \ + freelistcheck.c \ + io.c \ + lock.c \ + open.c \ + tdb.c \ + transaction.c \ + traverse.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/tdb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/tdb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libtdb.la: $(libtdb_la_OBJECTS) $(libtdb_la_DEPENDENCIES) $(EXTRA_libtdb_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libtdb_la_OBJECTS) $(libtdb_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freelist.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freelistcheck.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/open.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tdb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transaction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traverse.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/tdb/check.c b/libatalk/tdb/check.c new file mode 100644 index 0000000..f0a15f8 --- /dev/null +++ b/libatalk/tdb/check.c @@ -0,0 +1,423 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Rusty Russell 2009 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ +#include "tdb_private.h" + +/* Since we opened it, these shouldn't fail unless it's recent corruption. */ +static bool tdb_check_header(struct tdb_context *tdb, tdb_off_t *recovery) +{ + struct tdb_header hdr; + + if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), DOCONV()) == -1) + return false; + if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) + goto corrupt; + + CONVERT(hdr); + if (hdr.version != TDB_VERSION) + goto corrupt; + + if (hdr.rwlocks != 0) + goto corrupt; + + if (hdr.hash_size == 0) + goto corrupt; + + if (hdr.hash_size != tdb->header.hash_size) + goto corrupt; + + if (hdr.recovery_start != 0 && + hdr.recovery_start < TDB_DATA_START(tdb->header.hash_size)) + goto corrupt; + + *recovery = hdr.recovery_start; + return true; + +corrupt: + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "Header is corrupt\n")); + return false; +} + +/* Generic record header check. */ +static bool tdb_check_record(struct tdb_context *tdb, + tdb_off_t off, + const struct tdb_record *rec) +{ + tdb_off_t tailer; + + /* Check rec->next: 0 or points to record offset, aligned. */ + if (rec->next > 0 && rec->next < TDB_DATA_START(tdb->header.hash_size)){ + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d too small next %d\n", + off, rec->next)); + goto corrupt; + } + if (rec->next + sizeof(*rec) < rec->next) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d too large next %d\n", + off, rec->next)); + goto corrupt; + } + if ((rec->next % TDB_ALIGNMENT) != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d misaligned next %d\n", + off, rec->next)); + goto corrupt; + } + if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0)) + goto corrupt; + + /* Check rec_len: similar to rec->next, implies next record. */ + if ((rec->rec_len % TDB_ALIGNMENT) != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d misaligned length %d\n", + off, rec->rec_len)); + goto corrupt; + } + /* Must fit tailer. */ + if (rec->rec_len < sizeof(tailer)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d too short length %d\n", + off, rec->rec_len)); + goto corrupt; + } + /* OOB allows "right at the end" access, so this works for last rec. */ + if (tdb->methods->tdb_oob(tdb, off+sizeof(*rec)+rec->rec_len, 0)) + goto corrupt; + + /* Check tailer. */ + if (tdb_ofs_read(tdb, off+sizeof(*rec)+rec->rec_len-sizeof(tailer), + &tailer) == -1) + goto corrupt; + if (tailer != sizeof(*rec) + rec->rec_len) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d invalid tailer\n", off)); + goto corrupt; + } + + return true; + +corrupt: + tdb->ecode = TDB_ERR_CORRUPT; + return false; +} + +/* Grab some bytes: may copy if can't use mmap. + Caller has already done bounds check. */ +static TDB_DATA get_bytes(struct tdb_context *tdb, + tdb_off_t off, tdb_len_t len) +{ + TDB_DATA d; + + d.dsize = len; + + if (tdb->transaction == NULL && tdb->map_ptr != NULL) + d.dptr = (unsigned char *)tdb->map_ptr + off; + else + d.dptr = tdb_alloc_read(tdb, off, d.dsize); + return d; +} + +/* Frees data if we're not able to simply use mmap. */ +static void put_bytes(struct tdb_context *tdb, TDB_DATA d) +{ + if (tdb->transaction == NULL && tdb->map_ptr != NULL) + return; + free(d.dptr); +} + +/* We use the excellent Jenkins lookup3 hash; this is based on hash_word2. + * See: http://burtleburtle.net/bob/c/lookup3.c + */ +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) +static void hash(uint32_t key, uint32_t *pc, uint32_t *pb) +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + *pc; + c += *pb; + a += key; + c ^= b; c -= rot(b,14); + a ^= c; a -= rot(c,11); + b ^= a; b -= rot(a,25); + c ^= b; c -= rot(b,16); + a ^= c; a -= rot(c,4); + b ^= a; b -= rot(a,14); + c ^= b; c -= rot(b,24); + *pc=c; *pb=b; +} + +/* + We want to check that all free records are in the free list + (only once), and all free list entries are free records. Similarly + for each hash chain of used records. + + Doing that naively (without walking hash chains, since we want to be + linear) means keeping a list of records which have been seen in each + hash chain, and another of records pointed to (ie. next pointers + from records and the initial hash chain heads). These two lists + should be equal. This will take 8 bytes per record, and require + sorting at the end. + + So instead, we record each offset in a bitmap such a way that + recording it twice will cancel out. Since each offset should appear + exactly twice, the bitmap should be zero at the end. + + The approach was inspired by Bloom Filters (see Wikipedia). For + each value, we flip K bits in a bitmap of size N. The number of + distinct arrangements is: + + N! / (K! * (N-K)!) + + Of course, not all arrangements are actually distinct, but testing + shows this formula to be close enough. + + So, if K == 8 and N == 256, the probability of two things flipping the same + bits is 1 in 409,663,695,276,000. + + Given that ldb uses a hash size of 10000, using 32 bytes per hash chain + (320k) seems reasonable. +*/ +#define NUM_HASHES 8 +#define BITMAP_BITS 256 + +static void bit_flip(unsigned char bits[], unsigned int idx) +{ + bits[idx / CHAR_BIT] ^= (1 << (idx % CHAR_BIT)); +} + +/* We record offsets in a bitmap for the particular chain it should be in. */ +static void record_offset(unsigned char bits[], tdb_off_t off) +{ + uint32_t h1 = off, h2 = 0; + unsigned int i; + + /* We get two good hash values out of jhash2, so we use both. Then + * we keep going to produce further hash values. */ + for (i = 0; i < NUM_HASHES / 2; i++) { + hash(off, &h1, &h2); + bit_flip(bits, h1 % BITMAP_BITS); + bit_flip(bits, h2 % BITMAP_BITS); + h2++; + } +} + +/* Check that an in-use record is valid. */ +static bool tdb_check_used_record(struct tdb_context *tdb, + tdb_off_t off, + const struct tdb_record *rec, + unsigned char **hashes, + int (*check)(TDB_DATA, TDB_DATA, void *), + void *private_data) +{ + TDB_DATA key, data; + + if (!tdb_check_record(tdb, off, rec)) + return false; + + /* key + data + tailer must fit in record */ + if (rec->key_len + rec->data_len + sizeof(tdb_off_t) > rec->rec_len) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d too short for contents\n", off)); + return false; + } + + key = get_bytes(tdb, off + sizeof(*rec), rec->key_len); + if (!key.dptr) + return false; + + if (tdb->hash_fn(&key) != rec->full_hash) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Record offset %d has incorrect hash\n", off)); + goto fail_put_key; + } + + /* Mark this offset as a known value for this hash bucket. */ + record_offset(hashes[BUCKET(rec->full_hash)+1], off); + /* And similarly if the next pointer is valid. */ + if (rec->next) + record_offset(hashes[BUCKET(rec->full_hash)+1], rec->next); + + /* If they supply a check function and this record isn't dead, + get data and feed it. */ + if (check && rec->magic != TDB_DEAD_MAGIC) { + data = get_bytes(tdb, off + sizeof(*rec) + rec->key_len, + rec->data_len); + if (!data.dptr) + goto fail_put_key; + + if (check(key, data, private_data) == -1) + goto fail_put_data; + put_bytes(tdb, data); + } + + put_bytes(tdb, key); + return true; + +fail_put_data: + put_bytes(tdb, data); +fail_put_key: + put_bytes(tdb, key); + return false; +} + +/* Check that an unused record is valid. */ +static bool tdb_check_free_record(struct tdb_context *tdb, + tdb_off_t off, + const struct tdb_record *rec, + unsigned char **hashes) +{ + if (!tdb_check_record(tdb, off, rec)) + return false; + + /* Mark this offset as a known value for the free list. */ + record_offset(hashes[0], off); + /* And similarly if the next pointer is valid. */ + if (rec->next) + record_offset(hashes[0], rec->next); + return true; +} + +int tdb_check(struct tdb_context *tdb, + int (*check)(TDB_DATA key, TDB_DATA data, void *private_data), + void *private_data) +{ + unsigned int h; + unsigned char **hashes; + tdb_off_t off, recovery_start; + struct tdb_record rec; + bool found_recovery = false; + + if (tdb_lockall(tdb) == -1) + return -1; + + /* Make sure we know true size of the underlying file. */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* Header must be OK: also gets us the recovery ptr, if any. */ + if (!tdb_check_header(tdb, &recovery_start)) + goto unlock; + + /* We should have the whole header, too. */ + if (tdb->map_size < TDB_DATA_START(tdb->header.hash_size)) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "File too short for hashes\n")); + goto unlock; + } + + /* One big malloc: pointers then bit arrays. */ + hashes = (unsigned char **)calloc( + 1, sizeof(hashes[0]) * (1+tdb->header.hash_size) + + BITMAP_BITS / CHAR_BIT * (1+tdb->header.hash_size)); + if (!hashes) { + tdb->ecode = TDB_ERR_OOM; + goto unlock; + } + + /* Initialize pointers */ + hashes[0] = (unsigned char *)(&hashes[1+tdb->header.hash_size]); + for (h = 1; h < 1+tdb->header.hash_size; h++) + hashes[h] = hashes[h-1] + BITMAP_BITS / CHAR_BIT; + + /* Freelist and hash headers are all in a row: read them. */ + for (h = 0; h < 1+tdb->header.hash_size; h++) { + if (tdb_ofs_read(tdb, FREELIST_TOP + h*sizeof(tdb_off_t), + &off) == -1) + goto free; + if (off) + record_offset(hashes[h], off); + } + + /* For each record, read it in and check it's ok. */ + for (off = TDB_DATA_START(tdb->header.hash_size); + off < tdb->map_size; + off += sizeof(rec) + rec.rec_len) { + if (tdb->methods->tdb_read(tdb, off, &rec, sizeof(rec), + DOCONV()) == -1) + goto free; + switch (rec.magic) { + case TDB_MAGIC: + case TDB_DEAD_MAGIC: + if (!tdb_check_used_record(tdb, off, &rec, hashes, + check, private_data)) + goto free; + break; + case TDB_FREE_MAGIC: + if (!tdb_check_free_record(tdb, off, &rec, hashes)) + goto free; + break; + case TDB_RECOVERY_MAGIC: + case 0: /* Used for invalid (or in-progress) recovery area. */ + if (recovery_start != off) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Unexpected recovery record at offset %d\n", + off)); + goto free; + } + found_recovery = true; + break; + default: + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Bad magic 0x%x at offset %d\n", + rec.magic, off)); + goto free; + } + } + + /* Now, hashes should all be empty: each record exists and is referred + * to by one other. */ + for (h = 0; h < 1+tdb->header.hash_size; h++) { + unsigned int i; + for (i = 0; i < BITMAP_BITS / CHAR_BIT; i++) { + if (hashes[h][i] != 0) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Hashes do not match records\n")); + goto free; + } + } + } + + /* We must have found recovery area if there was one. */ + if (recovery_start != 0 && !found_recovery) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, + "Expected %s recovery area, got %s\n", + recovery_start ? "a" : "no", + found_recovery ? "one" : "none")); + goto free; + } + + free(hashes); + tdb_unlockall(tdb); + return 0; + +free: + free(hashes); +unlock: + tdb_unlockall(tdb); + return -1; +} diff --git a/libatalk/tdb/dump.c b/libatalk/tdb/dump.c new file mode 100644 index 0000000..bdcbfab --- /dev/null +++ b/libatalk/tdb/dump.c @@ -0,0 +1,137 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash, + tdb_off_t offset) +{ + struct tdb_record rec; + tdb_off_t tailer_ofs, tailer; + + if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + printf("ERROR: failed to read record at %u\n", offset); + return 0; + } + + printf(" rec: hash=%d offset=0x%08x next=0x%08x rec_len=%d " + "key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", + hash, offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, + rec.full_hash, rec.magic); + + tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t); + + if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) { + printf("ERROR: failed to read tailer at %u\n", tailer_ofs); + return rec.next; + } + + if (tailer != rec.rec_len + sizeof(rec)) { + printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", + (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); + } + return rec.next; +} + +static int tdb_dump_chain(struct tdb_context *tdb, int i) +{ + tdb_off_t rec_ptr, top; + + top = TDB_HASH_TOP(i); + + if (tdb_lock(tdb, i, F_WRLCK) != 0) + return -1; + + if (tdb_ofs_read(tdb, top, &rec_ptr) == -1) + return tdb_unlock(tdb, i, F_WRLCK); + + if (rec_ptr) + printf("hash=%d\n", i); + + while (rec_ptr) { + rec_ptr = tdb_dump_record(tdb, i, rec_ptr); + } + + return tdb_unlock(tdb, i, F_WRLCK); +} + +void tdb_dump_all(struct tdb_context *tdb) +{ + int i; + for (i=0;iheader.hash_size;i++) { + tdb_dump_chain(tdb, i); + } + printf("freelist:\n"); + tdb_dump_chain(tdb, -1); +} + +int tdb_printfreelist(struct tdb_context *tdb) +{ + int ret; + long total_free = 0; + tdb_off_t offset, rec_ptr; + struct tdb_record rec; + + if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) + return ret; + + offset = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + + printf("freelist top=[0x%08x]\n", rec_ptr ); + while (rec_ptr) { + if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, + sizeof(rec), DOCONV()) == -1) { + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + if (rec.magic != TDB_FREE_MAGIC) { + printf("bad magic 0x%08x in free list\n", rec.magic); + tdb_unlock(tdb, -1, F_WRLCK); + return -1; + } + + printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", + rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); + total_free += rec.rec_len; + + /* move to the next record */ + rec_ptr = rec.next; + } + printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, + (int)total_free); + + return tdb_unlock(tdb, -1, F_WRLCK); +} + diff --git a/libatalk/tdb/error.c b/libatalk/tdb/error.c new file mode 100644 index 0000000..195ab23 --- /dev/null +++ b/libatalk/tdb/error.c @@ -0,0 +1,57 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +enum TDB_ERROR tdb_error(struct tdb_context *tdb) +{ + return tdb->ecode; +} + +static struct tdb_errname { + enum TDB_ERROR ecode; const char *estring; +} emap[] = { {TDB_SUCCESS, "Success"}, + {TDB_ERR_CORRUPT, "Corrupt database"}, + {TDB_ERR_IO, "IO Error"}, + {TDB_ERR_LOCK, "Locking error"}, + {TDB_ERR_OOM, "Out of memory"}, + {TDB_ERR_EXISTS, "Record exists"}, + {TDB_ERR_NOLOCK, "Lock exists on other keys"}, + {TDB_ERR_EINVAL, "Invalid parameter"}, + {TDB_ERR_NOEXIST, "Record does not exist"}, + {TDB_ERR_RDONLY, "write not permitted"} }; + +/* Error string for the last tdb error */ +const char *tdb_errorstr(struct tdb_context *tdb) +{ + uint32_t i; + for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) + if (tdb->ecode == emap[i].ecode) + return emap[i].estring; + return "Invalid error code"; +} + diff --git a/libatalk/tdb/freelist.c b/libatalk/tdb/freelist.c new file mode 100644 index 0000000..8113b54 --- /dev/null +++ b/libatalk/tdb/freelist.c @@ -0,0 +1,386 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +/* 'right' merges can involve O(n^2) cost when combined with a + traverse, so they are disabled until we find a way to do them in + O(1) time +*/ +#define USE_RIGHT_MERGES 0 + +/* read a freelist record and check for simple errors */ +int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct tdb_record *rec) +{ + if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + + if (rec->magic == TDB_MAGIC) { + /* this happens when a app is showdown while deleting a record - we should + not completely fail when this happens */ + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n", + rec->magic, off)); + rec->magic = TDB_FREE_MAGIC; + if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1) + return -1; + } + + if (rec->magic != TDB_FREE_MAGIC) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", + rec->magic, off)); + return -1; + } + if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) + return -1; + return 0; +} + + +#if USE_RIGHT_MERGES +/* Remove an element from the freelist. Must have alloc lock. */ +static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next) +{ + tdb_off_t last_ptr, i; + + /* read in the freelist top */ + last_ptr = FREELIST_TOP; + while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { + if (i == off) { + /* We've found it! */ + return tdb_ofs_write(tdb, last_ptr, &next); + } + /* Follow chain (next offset is at start of record) */ + last_ptr = i; + } + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off)); + return -1; +} +#endif + + +/* update a record tailer (must hold allocation lock) */ +static int update_tailer(struct tdb_context *tdb, tdb_off_t offset, + const struct tdb_record *rec) +{ + tdb_off_t totalsize; + + /* Offset of tailer from record header */ + totalsize = sizeof(*rec) + rec->rec_len; + return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t), + &totalsize); +} + +/* Add an element into the freelist. Merge adjacent records if + neccessary. */ +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) +{ + /* Allocation and tailer lock */ + if (tdb_lock(tdb, -1, F_WRLCK) != 0) + return -1; + + /* set an initial tailer, so if we fail we don't leave a bogus record */ + if (update_tailer(tdb, offset, rec) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n")); + goto fail; + } + +#if USE_RIGHT_MERGES + /* Look right first (I'm an Australian, dammit) */ + if (offset + sizeof(*rec) + rec->rec_len + sizeof(*rec) <= tdb->map_size) { + tdb_off_t right = offset + sizeof(*rec) + rec->rec_len; + struct tdb_record r; + + if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right)); + goto left; + } + + /* If it's free, expand to include it. */ + if (r.magic == TDB_FREE_MAGIC) { + if (remove_from_freelist(tdb, right, r.next) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right)); + goto left; + } + rec->rec_len += sizeof(r) + r.rec_len; + if (update_tailer(tdb, offset, rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); + goto fail; + } + } + } +left: +#endif + + /* Look left */ + if (offset - sizeof(tdb_off_t) > TDB_DATA_START(tdb->header.hash_size)) { + tdb_off_t left = offset - sizeof(tdb_off_t); + struct tdb_record l; + tdb_off_t leftsize; + + /* Read in tailer and jump back to header */ + if (tdb_ofs_read(tdb, left, &leftsize) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left)); + goto update; + } + + /* it could be uninitialised data */ + if (leftsize == 0 || leftsize == TDB_PAD_U32) { + goto update; + } + + left = offset - leftsize; + + if (leftsize > offset || + left < TDB_DATA_START(tdb->header.hash_size)) { + goto update; + } + + /* Now read in the left record */ + if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); + goto update; + } + + /* If it's free, expand to include it. */ + if (l.magic == TDB_FREE_MAGIC) { + /* we now merge the new record into the left record, rather than the other + way around. This makes the operation O(1) instead of O(n). This change + prevents traverse from being O(n^2) after a lot of deletes */ + l.rec_len += sizeof(*rec) + rec->rec_len; + if (tdb_rec_write(tdb, left, &l) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_left failed at %u\n", left)); + goto fail; + } + if (update_tailer(tdb, left, &l) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); + goto fail; + } + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + } + } + +update: + + /* Now, prepend to free list */ + rec->magic = TDB_FREE_MAGIC; + + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || + tdb_rec_write(tdb, offset, rec) == -1 || + tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset)); + goto fail; + } + + /* And we're done. */ + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + + + +/* + the core of tdb_allocate - called when we have decided which + free list entry to use + + Note that we try to allocate by grabbing data from the end of an existing record, + not the beginning. This is so the left merge in a free is more likely to be + able to free up the record without fragmentation + */ +static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, + tdb_len_t length, tdb_off_t rec_ptr, + struct tdb_record *rec, tdb_off_t last_ptr) +{ +#define MIN_REC_SIZE (sizeof(struct tdb_record) + sizeof(tdb_off_t) + 8) + + if (rec->rec_len < length + MIN_REC_SIZE) { + /* we have to grab the whole record */ + + /* unlink it from the previous record */ + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { + return 0; + } + + /* mark it not free */ + rec->magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + return rec_ptr; + } + + /* we're going to just shorten the existing record */ + rec->rec_len -= (length + sizeof(*rec)); + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + /* and setup the new record */ + rec_ptr += sizeof(*rec) + rec->rec_len; + + memset(rec, '\0', sizeof(*rec)); + rec->rec_len = length; + rec->magic = TDB_MAGIC; + + if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { + return 0; + } + + if (update_tailer(tdb, rec_ptr, rec) == -1) { + return 0; + } + + return rec_ptr; +} + +/* allocate some space from the free list. The offset returned points + to a unconnected tdb_record within the database with room for at + least length bytes of total data + + 0 is returned if the space could not be allocated + */ +tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec) +{ + tdb_off_t rec_ptr, last_ptr, newrec_ptr; + struct { + tdb_off_t rec_ptr, last_ptr; + tdb_len_t rec_len; + } bestfit; + float multiplier = 1.0; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) + return 0; + + /* over-allocate to reduce fragmentation */ + length *= 1.25; + + /* Extra bytes required for tailer */ + length += sizeof(tdb_off_t); + length = TDB_ALIGN(length, TDB_ALIGNMENT); + + again: + last_ptr = FREELIST_TOP; + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) + goto fail; + + bestfit.rec_ptr = 0; + bestfit.last_ptr = 0; + bestfit.rec_len = 0; + + /* + this is a best fit allocation strategy. Originally we used + a first fit strategy, but it suffered from massive fragmentation + issues when faced with a slowly increasing record size. + */ + while (rec_ptr) { + if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) { + goto fail; + } + + if (rec->rec_len >= length) { + if (bestfit.rec_ptr == 0 || + rec->rec_len < bestfit.rec_len) { + bestfit.rec_len = rec->rec_len; + bestfit.rec_ptr = rec_ptr; + bestfit.last_ptr = last_ptr; + } + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec->next; + + /* if we've found a record that is big enough, then + stop searching if its also not too big. The + definition of 'too big' changes as we scan + through */ + if (bestfit.rec_len > 0 && + bestfit.rec_len < length * multiplier) { + break; + } + + /* this multiplier means we only extremely rarely + search more than 50 or so records. At 50 records we + accept records up to 11 times larger than what we + want */ + multiplier *= 1.05; + } + + if (bestfit.rec_ptr != 0) { + if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { + goto fail; + } + + newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, + rec, bestfit.last_ptr); + tdb_unlock(tdb, -1, F_WRLCK); + return newrec_ptr; + } + + /* we didn't find enough space. See if we can expand the + database and if we can then try again */ + if (tdb_expand(tdb, length + sizeof(*rec)) == 0) + goto again; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return 0; +} + + + +/* + return the size of the freelist - used to decide if we should repack +*/ +int tdb_freelist_size(struct tdb_context *tdb) +{ + tdb_off_t ptr; + int count=0; + + if (tdb_lock(tdb, -1, F_RDLCK) == -1) { + return -1; + } + + ptr = FREELIST_TOP; + while (tdb_ofs_read(tdb, ptr, &ptr) == 0 && ptr != 0) { + count++; + } + + tdb_unlock(tdb, -1, F_RDLCK); + return count; +} diff --git a/libatalk/tdb/freelistcheck.c b/libatalk/tdb/freelistcheck.c new file mode 100644 index 0000000..8d1ebab --- /dev/null +++ b/libatalk/tdb/freelistcheck.c @@ -0,0 +1,109 @@ +/* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Jeremy Allison 2006 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +/* Check the freelist is good and contains no loops. + Very memory intensive - only do this as a consistency + checker. Heh heh - uses an in memory tdb as the storage + for the "seen" record list. For some reason this strikes + me as extremely clever as I don't have to write another tree + data structure implementation :-). + */ + +static int seen_insert(struct tdb_context *mem_tdb, tdb_off_t rec_ptr) +{ + TDB_DATA key, data; + + memset(&data, '\0', sizeof(data)); + key.dptr = (unsigned char *)&rec_ptr; + key.dsize = sizeof(rec_ptr); + return tdb_store(mem_tdb, key, data, TDB_INSERT); +} + +int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries) +{ + struct tdb_context *mem_tdb = NULL; + struct tdb_record rec; + tdb_off_t rec_ptr, last_ptr; + int ret = -1; + + *pnum_entries = 0; + + mem_tdb = tdb_open("flval", tdb->header.hash_size, + TDB_INTERNAL, O_RDWR, 0600); + if (!mem_tdb) { + return -1; + } + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + tdb_close(mem_tdb); + return 0; + } + + last_ptr = FREELIST_TOP; + + /* Store the FREELIST_TOP record. */ + if (seen_insert(mem_tdb, last_ptr) == -1) { + tdb->ecode = TDB_ERR_CORRUPT; + ret = -1; + goto fail; + } + + /* read in the freelist top */ + if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) { + goto fail; + } + + while (rec_ptr) { + + /* If we can't store this record (we've seen it + before) then the free list has a loop and must + be corrupt. */ + + if (seen_insert(mem_tdb, rec_ptr)) { + tdb->ecode = TDB_ERR_CORRUPT; + ret = -1; + goto fail; + } + + if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) { + goto fail; + } + + /* move to the next record */ + last_ptr = rec_ptr; + rec_ptr = rec.next; + *pnum_entries += 1; + } + + ret = 0; + + fail: + + tdb_close(mem_tdb); + tdb_unlock(tdb, -1, F_WRLCK); + return ret; +} diff --git a/libatalk/tdb/io.c b/libatalk/tdb/io.c new file mode 100644 index 0000000..88ff7ac --- /dev/null +++ b/libatalk/tdb/io.c @@ -0,0 +1,472 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +/* check for an out of bounds access - if it is out of bounds then + see if the database has been expanded by someone else and expand + if necessary + note that "len" is the minimum length needed for the db +*/ +static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +{ + struct stat st; + if (len <= tdb->map_size) + return 0; + if (tdb->flags & TDB_INTERNAL) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n", + (int)len, (int)tdb->map_size)); + } + return -1; + } + + if (fstat(tdb->fd, &st) == -1) { + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (st.st_size < (size_t)len) { + if (!probe) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n", + (int)len, (int)st.st_size)); + } + return -1; + } + + /* Unmap, update size, remap */ + if (tdb_munmap(tdb) == -1) { + tdb->ecode = TDB_ERR_IO; + return -1; + } + tdb->map_size = st.st_size; + tdb_mmap(tdb); + return 0; +} + +/* write a lump of data at a specified offset */ +static int tdb_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + if (len == 0) { + return 0; + } + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) + return -1; + + if (tdb->map_ptr) { + memcpy(off + (char *)tdb->map_ptr, buf, len); + } else { + ssize_t written = pwrite(tdb->fd, buf, len, off); + if ((written != (ssize_t)len) && (written != -1)) { + /* try once more */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_write: wrote only " + "%d of %d bytes at %d, trying once more\n", + (int)written, len, off)); + written = pwrite(tdb->fd, (const char *)buf+written, + len-written, + off+written); + } + if (written == -1) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d " + "len=%d (%s)\n", off, len, strerror(errno))); + return -1; + } else if (written != (ssize_t)len) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_write: failed to " + "write %d bytes at %d in two attempts\n", + len, off)); + return -1; + } + } + return 0; +} + +/* Endian conversion: we only ever deal with 4 byte quantities */ +void *tdb_convert(void *buf, uint32_t size) +{ + uint32_t i, *p = (uint32_t *)buf; + for (i = 0; i < size / 4; i++) + p[i] = TDB_BYTEREV(p[i]); + return buf; +} + + +/* read a lump of data at a specified offset, maybe convert */ +static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) { + return -1; + } + + if (tdb->map_ptr) { + memcpy(buf, off + (char *)tdb->map_ptr, len); + } else { + ssize_t ret = pread(tdb->fd, buf, len, off); + if (ret != (ssize_t)len) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d " + "len=%d ret=%d (%s) map_size=%d\n", + (int)off, (int)len, (int)ret, strerror(errno), + (int)tdb->map_size)); + return -1; + } + } + if (cv) { + tdb_convert(buf, len); + } + return 0; +} + + + +/* + do an unlocked scan of the hash table heads to find the next non-zero head. The value + will then be confirmed with the lock held +*/ +static void tdb_next_hash_chain(struct tdb_context *tdb, uint32_t *chain) +{ + uint32_t h = *chain; + if (tdb->map_ptr) { + for (;h < tdb->header.hash_size;h++) { + if (0 != *(uint32_t *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { + break; + } + } + } else { + uint32_t off=0; + for (;h < tdb->header.hash_size;h++) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) { + break; + } + } + } + (*chain) = h; +} + + +int tdb_munmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return 0; + +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + int ret; + + ret = munmap(tdb->map_ptr, tdb->map_size); + if (ret != 0) + return ret; + } +#endif + tdb->map_ptr = NULL; + return 0; +} + +void tdb_mmap(struct tdb_context *tdb) +{ + if (tdb->flags & TDB_INTERNAL) + return; + +#ifdef HAVE_MMAP + if (!(tdb->flags & TDB_NOMMAP)) { + tdb->map_ptr = mmap(NULL, tdb->map_size, + PROT_READ|(tdb->read_only? 0:PROT_WRITE), + MAP_SHARED, tdb->fd, 0); + + /* + * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! + */ + + if (tdb->map_ptr == MAP_FAILED) { + tdb->map_ptr = NULL; + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n", + tdb->map_size, strerror(errno))); + } + } else { + tdb->map_ptr = NULL; + } +#else + tdb->map_ptr = NULL; +#endif +} + +/* expand a file. we prefer to use ftruncate, as that is what posix + says to use for mmap expansion */ +static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) +{ + char buf[8192]; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + if (ftruncate(tdb->fd, size+addition) == -1) { + char b = 0; + ssize_t written = pwrite(tdb->fd, &b, 1, (size+addition) - 1); + if (written == 0) { + /* try once more, potentially revealing errno */ + written = pwrite(tdb->fd, &b, 1, (size+addition) - 1); + } + if (written == 0) { + /* again - give up, guessing errno */ + errno = ENOSPC; + } + if (written != 1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", + size+addition, strerror(errno))); + return -1; + } + } + + /* now fill the file with something. This ensures that the + file isn't sparse, which would be very bad if we ran out of + disk. This must be done with write, not via mmap */ + memset(buf, TDB_PAD_BYTE, sizeof(buf)); + while (addition) { + size_t n = addition>sizeof(buf)?sizeof(buf):addition; + ssize_t written = pwrite(tdb->fd, buf, n, size); + if (written == 0) { + /* prevent infinite loops: try _once_ more */ + written = pwrite(tdb->fd, buf, n, size); + } + if (written == 0) { + /* give up, trying to provide a useful errno */ + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write " + "returned 0 twice: giving up!\n")); + errno = ENOSPC; + return -1; + } else if (written == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of " + "%d bytes failed (%s)\n", (int)n, + strerror(errno))); + return -1; + } else if (written != n) { + TDB_LOG((tdb, TDB_DEBUG_WARNING, "expand_file: wrote " + "only %d of %d bytes - retrying\n", (int)written, + (int)n)); + } + addition -= written; + size += written; + } + return 0; +} + + +/* expand the database at least size bytes by expanding the underlying + file and doing the mmap again if necessary */ +int tdb_expand(struct tdb_context *tdb, tdb_off_t size) +{ + struct tdb_record rec; + tdb_off_t offset, new_size; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n")); + return -1; + } + + /* must know about any previous expansions by another process */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* always make room for at least 100 more records, and at + least 25% more space. Round the database up to a multiple + of the page size */ + new_size = MAX(tdb->map_size + size*100, tdb->map_size * 1.25); + size = TDB_ALIGN(new_size, tdb->page_size) - tdb->map_size; + + if (!(tdb->flags & TDB_INTERNAL)) + tdb_munmap(tdb); + + /* + * We must ensure the file is unmapped before doing this + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* expand the file itself */ + if (!(tdb->flags & TDB_INTERNAL)) { + if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0) + goto fail; + } + + tdb->map_size += size; + + if (tdb->flags & TDB_INTERNAL) { + char *new_map_ptr = (char *)realloc(tdb->map_ptr, + tdb->map_size); + if (!new_map_ptr) { + tdb->map_size -= size; + goto fail; + } + tdb->map_ptr = new_map_ptr; + } else { + /* + * We must ensure the file is remapped before adding the space + * to ensure consistency with systems like OpenBSD where + * writes and mmaps are not consistent. + */ + + /* We're ok if the mmap fails as we'll fallback to read/write */ + tdb_mmap(tdb); + } + + /* form a new freelist record */ + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = size - sizeof(rec); + + /* link it into the free list */ + offset = tdb->map_size - size; + if (tdb_free(tdb, offset, &rec) == -1) + goto fail; + + tdb_unlock(tdb, -1, F_WRLCK); + return 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return -1; +} + +/* read/write a tdb_off_t */ +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); +} + +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) +{ + tdb_off_t off = *d; + return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); +} + + +/* read a lump of data, allocating the space for it */ +unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) +{ + unsigned char *buf; + + /* some systems don't like zero length malloc */ + + if (!(buf = (unsigned char *)malloc(len ? len : 1))) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_OOM; + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n", + len, strerror(errno))); + return NULL; + } + if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) { + SAFE_FREE(buf); + return NULL; + } + return buf; +} + +/* Give a piece of tdb data to a parser */ + +int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, + tdb_off_t offset, tdb_len_t len, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + TDB_DATA data; + int result; + + data.dsize = len; + + if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) { + /* + * Optimize by avoiding the malloc/memcpy/free, point the + * parser directly at the mmap area. + */ + if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) { + return -1; + } + data.dptr = offset + (unsigned char *)tdb->map_ptr; + return parser(key, data, private_data); + } + + if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) { + return -1; + } + + result = parser(key, data, private_data); + free(data.dptr); + return result; +} + +/* read/write a record */ +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) +{ + if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) + return -1; + if (TDB_BAD_MAGIC(rec)) { + /* Ensure ecode is set for log fn. */ + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); + return -1; + } + return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0); +} + +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) +{ + struct tdb_record r = *rec; + return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r)); +} + +static const struct tdb_methods io_methods = { + tdb_read, + tdb_write, + tdb_next_hash_chain, + tdb_oob, + tdb_expand_file, + tdb_brlock +}; + +/* + initialise the default methods table +*/ +void tdb_io_init(struct tdb_context *tdb) +{ + tdb->methods = &io_methods; +} diff --git a/libatalk/tdb/lock.c b/libatalk/tdb/lock.c new file mode 100644 index 0000000..0984e51 --- /dev/null +++ b/libatalk/tdb/lock.c @@ -0,0 +1,592 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +#define TDB_MARK_LOCK 0x80000000 + +void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr) +{ + tdb->interrupt_sig_ptr = ptr; +} + +/* a byte range locking function - return 0 on success + this functions locks/unlocks 1 byte at the specified offset. + + On error, errno is also set so that errors are passed back properly + through tdb_open(). + + note that a len of zero means lock to end of file +*/ +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe, size_t len) +{ + struct flock fl; + int ret; + + if (tdb->flags & TDB_NOLOCK) { + return 0; + } + + if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { + tdb->ecode = TDB_ERR_RDONLY; + return -1; + } + + fl.l_type = rw_type; + fl.l_whence = SEEK_SET; + fl.l_start = offset; + fl.l_len = len; + fl.l_pid = 0; + + do { + ret = fcntl(tdb->fd,lck_type,&fl); + + /* Check for a sigalarm break. */ + if (ret == -1 && errno == EINTR && + tdb->interrupt_sig_ptr && + *tdb->interrupt_sig_ptr) { + break; + } + } while (ret == -1 && errno == EINTR); + + if (ret == -1) { + tdb->ecode = TDB_ERR_LOCK; + /* Generic lock error. errno set by fcntl. + * EAGAIN is an expected return from non-blocking + * locks. */ + if (!probe && lck_type != F_SETLK) { + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", + tdb->fd, offset, rw_type, lck_type, (int)len)); + } + return -1; + } + return 0; +} + + +/* + upgrade a read lock to a write lock. This needs to be handled in a + special way as some OSes (such as solaris) have too conservative + deadlock detection and claim a deadlock when progress can be + made. For those OSes we may loop for a while. +*/ +int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) +{ + int count = 1000; + while (count--) { + struct timeval tv; + if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) { + return 0; + } + if (errno != EDEADLK) { + break; + } + /* sleep for as short a time as we can - more portable than usleep() */ + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); + } + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset)); + return -1; +} + + +/* lock a list in the database. list -1 is the alloc list */ +static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) +{ + struct tdb_lock_type *new_lck; + int i; + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* a global lock allows us to avoid per chain locks */ + if (tdb->global_lock.count && + (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { + return 0; + } + + if (tdb->global_lock.count) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (list < -1 || list >= (int)tdb->header.hash_size) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", + list, ltype)); + return -1; + } + if (tdb->flags & TDB_NOLOCK) + return 0; + + for (i=0; inum_lockrecs; i++) { + if (tdb->lockrecs[i].list == list) { + if (tdb->lockrecs[i].count == 0) { + /* + * Can't happen, see tdb_unlock(). It should + * be an assert. + */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: " + "lck->count == 0 for list %d", list)); + } + /* + * Just increment the in-memory struct, posix locks + * don't stack. + */ + tdb->lockrecs[i].count++; + return 0; + } + } + + new_lck = (struct tdb_lock_type *)realloc( + tdb->lockrecs, + sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1)); + if (new_lck == NULL) { + errno = ENOMEM; + return -1; + } + tdb->lockrecs = new_lck; + + /* Since fcntl locks don't nest, we do a lock for the first one, + and simply bump the count for future ones */ + if (!mark_lock && + tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op, + 0, 1)) { + return -1; + } + + tdb->num_locks++; + + tdb->lockrecs[tdb->num_lockrecs].list = list; + tdb->lockrecs[tdb->num_lockrecs].count = 1; + tdb->lockrecs[tdb->num_lockrecs].ltype = ltype; + tdb->num_lockrecs += 1; + + return 0; +} + +/* lock a list in the database. list -1 is the alloc list */ +int tdb_lock(struct tdb_context *tdb, int list, int ltype) +{ + int ret; + ret = _tdb_lock(tdb, list, ltype, F_SETLKW); + if (ret) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d " + "ltype=%d (%s)\n", list, ltype, strerror(errno))); + } + return ret; +} + +/* lock a list in the database. list -1 is the alloc list. non-blocking lock */ +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype) +{ + return _tdb_lock(tdb, list, ltype, F_SETLK); +} + + +/* unlock the database: returns void because it's too late for errors. */ + /* changed to return int it may be interesting to know there + has been an error --simo */ +int tdb_unlock(struct tdb_context *tdb, int list, int ltype) +{ + int ret = -1; + int i; + struct tdb_lock_type *lck = NULL; + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* a global lock allows us to avoid per chain locks */ + if (tdb->global_lock.count && + (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { + return 0; + } + + if (tdb->global_lock.count) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->flags & TDB_NOLOCK) + return 0; + + /* Sanity checks */ + if (list < -1 || list >= (int)tdb->header.hash_size) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); + return ret; + } + + for (i=0; inum_lockrecs; i++) { + if (tdb->lockrecs[i].list == list) { + lck = &tdb->lockrecs[i]; + break; + } + } + + if ((lck == NULL) || (lck->count == 0)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); + return -1; + } + + if (lck->count > 1) { + lck->count--; + return 0; + } + + /* + * This lock has count==1 left, so we need to unlock it in the + * kernel. We don't bother with decrementing the in-memory array + * element, we're about to overwrite it with the last array element + * anyway. + */ + + if (mark_lock) { + ret = 0; + } else { + ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, + F_SETLKW, 0, 1); + } + tdb->num_locks--; + + /* + * Shrink the array by overwriting the element just unlocked with the + * last array element. + */ + + if (tdb->num_lockrecs > 1) { + *lck = tdb->lockrecs[tdb->num_lockrecs-1]; + } + tdb->num_lockrecs -= 1; + + /* + * We don't bother with realloc when the array shrinks, but if we have + * a completely idle tdb we should get rid of the locked array. + */ + + if (tdb->num_lockrecs == 0) { + SAFE_FREE(tdb->lockrecs); + } + + if (ret) + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n")); + return ret; +} + +/* + get the transaction lock + */ +int tdb_transaction_lock(struct tdb_context *tdb, int ltype) +{ + if (tdb->global_lock.count) { + return 0; + } + if (tdb->transaction_lock_count > 0) { + tdb->transaction_lock_count++; + return 0; + } + + if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, + F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + tdb->transaction_lock_count++; + return 0; +} + +/* + release the transaction lock + */ +int tdb_transaction_unlock(struct tdb_context *tdb) +{ + int ret; + if (tdb->global_lock.count) { + return 0; + } + if (tdb->transaction_lock_count > 1) { + tdb->transaction_lock_count--; + return 0; + } + ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); + if (ret == 0) { + tdb->transaction_lock_count = 0; + } + return ret; +} + + + + +/* lock/unlock entire database */ +static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op) +{ + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* There are no locks on read-only dbs */ + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) { + tdb->global_lock.count++; + return 0; + } + + if (tdb->global_lock.count) { + /* a global lock of a different type exists */ + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->num_locks != 0) { + /* can't combine global and chain locks */ + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (!mark_lock && + tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op, + 0, 4*tdb->header.hash_size)) { + if (op == F_SETLKW) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno))); + } + return -1; + } + + tdb->global_lock.count = 1; + tdb->global_lock.ltype = ltype; + + return 0; +} + + + +/* unlock entire db */ +static int _tdb_unlockall(struct tdb_context *tdb, int ltype) +{ + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; + + /* There are no locks on read-only dbs */ + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) { + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->global_lock.count > 1) { + tdb->global_lock.count--; + return 0; + } + + if (!mark_lock && + tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, + 0, 4*tdb->header.hash_size)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno))); + return -1; + } + + tdb->global_lock.count = 0; + tdb->global_lock.ltype = 0; + + return 0; +} + +/* lock entire database with write lock */ +int tdb_lockall(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall"); + return _tdb_lockall(tdb, F_WRLCK, F_SETLKW); +} + +/* lock entire database with write lock - mark only */ +int tdb_lockall_mark(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall_mark"); + return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW); +} + +/* unlock entire database with write lock - unmark only */ +int tdb_lockall_unmark(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall_unmark"); + return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK); +} + +/* lock entire database with write lock - nonblocking varient */ +int tdb_lockall_nonblock(struct tdb_context *tdb) +{ + int ret = _tdb_lockall(tdb, F_WRLCK, F_SETLK); + tdb_trace_ret(tdb, "tdb_lockall_nonblock", ret); + return ret; +} + +/* unlock entire database with write lock */ +int tdb_unlockall(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_unlockall"); + return _tdb_unlockall(tdb, F_WRLCK); +} + +/* lock entire database with read lock */ +int tdb_lockall_read(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_lockall_read"); + return _tdb_lockall(tdb, F_RDLCK, F_SETLKW); +} + +/* lock entire database with read lock - nonblock varient */ +int tdb_lockall_read_nonblock(struct tdb_context *tdb) +{ + int ret = _tdb_lockall(tdb, F_RDLCK, F_SETLK); + tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret); + return ret; +} + +/* unlock entire database with read lock */ +int tdb_unlockall_read(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_unlockall_read"); + return _tdb_unlockall(tdb, F_RDLCK); +} + +/* lock/unlock one hash chain. This is meant to be used to reduce + contention - it cannot guarantee how many records will be locked */ +int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) +{ + int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); + tdb_trace_1rec(tdb, "tdb_chainlock", key); + return ret; +} + +/* lock/unlock one hash chain, non-blocking. This is meant to be used + to reduce contention - it cannot guarantee how many records will be + locked */ +int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key) +{ + int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); + tdb_trace_1rec_ret(tdb, "tdb_chainlock_nonblock", key, ret); + return ret; +} + +/* mark a chain as locked without actually locking it. Warning! use with great caution! */ +int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) +{ + int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); + tdb_trace_1rec(tdb, "tdb_chainlock_mark", key); + return ret; +} + +/* unmark a chain as locked without actually locking it. Warning! use with great caution! */ +int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_trace_1rec(tdb, "tdb_chainlock_unmark", key); + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); +} + +int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_trace_1rec(tdb, "tdb_chainunlock", key); + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); +} + +int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + int ret; + ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); + tdb_trace_1rec(tdb, "tdb_chainlock_read", key); + return ret; +} + +int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_trace_1rec(tdb, "tdb_chainunlock_read", key); + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); +} + + + +/* record lock stops delete underneath */ +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + if (tdb->global_lock.count) { + return 0; + } + return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0; +} + +/* + Write locks override our own fcntl readlocks, so check it here. + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + return -1; + return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1); +} + +/* + Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not + an error to fail to get the lock here. +*/ +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1); +} + +/* fcntl locks don't stack: avoid unlocking someone else's */ +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) +{ + struct tdb_traverse_lock *i; + uint32_t count = 0; + + if (tdb->global_lock.count) { + return 0; + } + + if (off == 0) + return 0; + for (i = &tdb->travlocks; i; i = i->next) + if (i->off == off) + count++; + return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0); +} diff --git a/libatalk/tdb/open.c b/libatalk/tdb/open.c new file mode 100644 index 0000000..4d4f95a --- /dev/null +++ b/libatalk/tdb/open.c @@ -0,0 +1,552 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ +static struct tdb_context *tdbs = NULL; + + +/* This is based on the hash algorithm from gdbm */ +static unsigned int default_tdb_hash(TDB_DATA *key) +{ + uint32_t value; /* Used to compute the hash value. */ + uint32_t i; /* Used to cycle through random values. */ + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++) + value = (value + (key->dptr[i] << (i*5 % 24))); + + return (1103515243 * value + 12345); +} + + +/* initialise a new database with a specified hash size */ +static int tdb_new_database(struct tdb_context *tdb, int hash_size) +{ + struct tdb_header *newdb; + size_t size; + int ret = -1; + ssize_t written; + + /* We make it up in memory, then write it out if not internal */ + size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t); + if (!(newdb = (struct tdb_header *)calloc(size, 1))) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* Fill in the header */ + newdb->version = TDB_VERSION; + newdb->hash_size = hash_size; + if (tdb->flags & TDB_INTERNAL) { + tdb->map_size = size; + tdb->map_ptr = (char *)newdb; + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Convert the `ondisk' version if asked. */ + CONVERT(*newdb); + return 0; + } + if (lseek(tdb->fd, 0, SEEK_SET) == -1) + goto fail; + + if (ftruncate(tdb->fd, 0) == -1) + goto fail; + + /* This creates an endian-converted header, as if read from disk */ + CONVERT(*newdb); + memcpy(&tdb->header, newdb, sizeof(tdb->header)); + /* Don't endian-convert the magic food! */ + memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); + /* we still have "ret == -1" here */ + written = write(tdb->fd, newdb, size); + if (written == size) { + ret = 0; + } else if (written != -1) { + /* call write once again, this usually should return -1 and + * set errno appropriately */ + size -= written; + written = write(tdb->fd, newdb+written, size); + if (written == size) { + ret = 0; + } else if (written >= 0) { + /* a second incomplete write - we give up. + * guessing the errno... */ + errno = ENOSPC; + } + } + + fail: + SAFE_FREE(newdb); + return ret; +} + + + +static int tdb_already_open(dev_t device, + ino_t ino) +{ + struct tdb_context *i; + + for (i = tdbs; i; i = i->next) { + if (i->device == device && i->inode == ino) { + return 1; + } + } + + return 0; +} + +/* open the database, creating it if necessary + + The open_flags and mode are passed straight to the open call on the + database file. A flags value of O_WRONLY is invalid. The hash size + is advisory, use zero for a default value. + + Return is NULL on error, in which case errno is also set. Don't + try to call tdb_error or tdb_errname, just do strerror(errno). + + @param name may be NULL for internal databases. */ +struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode) +{ + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); +} + +/* a default logging function */ +static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ +} + + +struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + int open_flags, mode_t mode, + const struct tdb_logging_context *log_ctx, + tdb_hash_func hash_fn) +{ + struct tdb_context *tdb; + struct stat st; + int rev = 0, locked = 0; + unsigned char *vp; + uint32_t vertest; + unsigned v; + + if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) { + /* Can't log this */ + errno = ENOMEM; + goto fail; + } + tdb_io_init(tdb); + tdb->fd = -1; +#ifdef TDB_TRACE + tdb->tracefd = -1; +#endif + tdb->name = NULL; + tdb->map_ptr = NULL; + tdb->flags = tdb_flags; + tdb->open_flags = open_flags; + if (log_ctx) { + tdb->log = *log_ctx; + } else { + tdb->log.log_fn = null_log_fn; + tdb->log.log_private = NULL; + } + tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; + + /* cache the page size */ + tdb->page_size = getpagesize(); + if (tdb->page_size <= 0) { + tdb->page_size = 0x2000; + } + + tdb->max_dead_records = (tdb_flags & TDB_VOLATILE) ? 5 : 0; + + if ((open_flags & O_ACCMODE) == O_WRONLY) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", + name)); + errno = EINVAL; + goto fail; + } + + if (hash_size == 0) + hash_size = DEFAULT_HASH_SIZE; + if ((open_flags & O_ACCMODE) == O_RDONLY) { + tdb->read_only = 1; + /* read only databases don't do locking or clear if first */ + tdb->flags |= TDB_NOLOCK; + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + } + + if ((tdb->flags & TDB_ALLOW_NESTING) && + (tdb->flags & TDB_DISALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "allow_nesting and disallow_nesting are not allowed together!")); + errno = EINVAL; + goto fail; + } + + /* + * TDB_ALLOW_NESTING is the default behavior. + * Note: this may change in future versions! + */ + if (!(tdb->flags & TDB_DISALLOW_NESTING)) { + tdb->flags |= TDB_ALLOW_NESTING; + } + + /* internal databases don't mmap or lock, and start off cleared */ + if (tdb->flags & TDB_INTERNAL) { + tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); + tdb->flags &= ~TDB_CLEAR_IF_FIRST; + if (tdb_new_database(tdb, hash_size) != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!")); + goto fail; + } + goto internal; + } + + if ((tdb->fd = open(name, open_flags, mode)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ + } + + /* on exec, don't inherit the fd */ + v = fcntl(tdb->fd, F_GETFD, 0); + fcntl(tdb->fd, F_SETFD, v | FD_CLOEXEC); + + /* ensure there is only one process initialising at once */ + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by tdb_brlock */ + } + + /* we need to zero database if we are the only one with it open */ + if ((tdb_flags & TDB_CLEAR_IF_FIRST) && + (!tdb->read_only) && + (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) { + open_flags |= O_CREAT; + if (ftruncate(tdb->fd, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " + "failed to truncate %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by ftruncate */ + } + } + + errno = 0; + if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) + || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0) { + if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { + if (errno == 0) { + errno = EIO; /* ie bad format or something */ + } + goto fail; + } + rev = (tdb->flags & TDB_CONVERT); + } else if (tdb->header.version != TDB_VERSION + && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION)))) { + /* wrong version */ + errno = EIO; + goto fail; + } + vp = (unsigned char *)&tdb->header.version; + vertest = (((uint32_t)vp[0]) << 24) | (((uint32_t)vp[1]) << 16) | + (((uint32_t)vp[2]) << 8) | (uint32_t)vp[3]; + tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; + if (!rev) + tdb->flags &= ~TDB_CONVERT; + else { + tdb->flags |= TDB_CONVERT; + tdb_convert(&tdb->header, sizeof(tdb->header)); + } + if (fstat(tdb->fd, &st) == -1) + goto fail; + + if (tdb->header.rwlocks != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); + goto fail; + } + + /* Is it already in the open list? If so, fail. */ + if (tdb_already_open(st.st_dev, st.st_ino)) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "%s (%d,%d) is already open in this process\n", + name, (int)st.st_dev, (int)st.st_ino)); + errno = EBUSY; + goto fail; + } + + if (!(tdb->name = (char *)strdup(name))) { + errno = ENOMEM; + goto fail; + } + + tdb->map_size = st.st_size; + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + tdb_mmap(tdb); + if (locked) { + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " + "failed to take ACTIVE_LOCK on %s: %s\n", + name, strerror(errno))); + goto fail; + } + + } + + /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if + we didn't get the initial exclusive lock as we need to let all other + users know we're using it. */ + + if (tdb_flags & TDB_CLEAR_IF_FIRST) { + /* leave this lock in place to indicate it's in use */ + if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1) + goto fail; + } + + /* if needed, run recovery */ + if (tdb_transaction_recover(tdb) == -1) { + goto fail; + } + +#ifdef TDB_TRACE + { + char tracefile[strlen(name) + 32]; + + snprintf(tracefile, sizeof(tracefile), + "%s.trace.%li", name, (long)getpid()); + tdb->tracefd = open(tracefile, O_WRONLY|O_CREAT|O_EXCL, 0600); + if (tdb->tracefd >= 0) { + tdb_enable_seqnum(tdb); + tdb_trace_open(tdb, "tdb_open", hash_size, tdb_flags, + open_flags); + } else + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to open trace file %s!\n", tracefile)); + } +#endif + + internal: + /* Internal (memory-only) databases skip all the code above to + * do with disk files, and resume here by releasing their + * global lock and hooking into the active list. */ + if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1) + goto fail; + tdb->next = tdbs; + tdbs = tdb; + return tdb; + + fail: + { int save_errno = errno; + + if (!tdb) + return NULL; + +#ifdef TDB_TRACE + close(tdb->tracefd); +#endif + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) + if (close(tdb->fd) != 0) + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n")); + SAFE_FREE(tdb); + errno = save_errno; + return NULL; + } +} + +/* + * Set the maximum number of dead records per hash chain + */ + +void tdb_set_max_dead(struct tdb_context *tdb, int max_dead) +{ + tdb->max_dead_records = max_dead; +} + +/** + * Close a database. + * + * @returns -1 for error; 0 for success. + **/ +int tdb_close(struct tdb_context *tdb) +{ + struct tdb_context **i; + int ret = 0; + + tdb_trace(tdb, "tdb_close"); + if (tdb->transaction) { + _tdb_transaction_cancel(tdb); + } + + if (tdb->map_ptr) { + if (tdb->flags & TDB_INTERNAL) + SAFE_FREE(tdb->map_ptr); + else + tdb_munmap(tdb); + } + SAFE_FREE(tdb->name); + if (tdb->fd != -1) { + ret = close(tdb->fd); + tdb->fd = -1; + } + SAFE_FREE(tdb->lockrecs); + + /* Remove from contexts list */ + for (i = &tdbs; *i; i = &(*i)->next) { + if (*i == tdb) { + *i = tdb->next; + break; + } + } + +#ifdef TDB_TRACE + close(tdb->tracefd); +#endif + memset(tdb, 0, sizeof(*tdb)); + SAFE_FREE(tdb); + + return ret; +} + +/* register a loging function */ +void tdb_set_logging_function(struct tdb_context *tdb, + const struct tdb_logging_context *log_ctx) +{ + tdb->log = *log_ctx; +} + +void *tdb_get_logging_private(struct tdb_context *tdb) +{ + return tdb->log.log_private; +} + +static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock) +{ +#if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \ + !defined(LIBREPLACE_PWRITE_NOT_REPLACED) + struct stat st; +#endif + + if (tdb->flags & TDB_INTERNAL) { + return 0; /* Nothing to do. */ + } + + if (tdb->num_locks != 0 || tdb->global_lock.count) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n")); + goto fail; + } + + if (tdb->transaction != 0) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n")); + goto fail; + } + +/* If we have real pread & pwrite, we can skip reopen. */ +#if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \ + !defined(LIBREPLACE_PWRITE_NOT_REPLACED) + if (tdb_munmap(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + goto fail; + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + if (fstat(tdb->fd, &st) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + goto fail; + } + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + tdb_mmap(tdb); +#endif /* fake pread or pwrite */ + + if (active_lock && + (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen a tdb - this can be used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +int tdb_reopen(struct tdb_context *tdb) +{ + return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST); +} + +/* reopen all tdb's */ +int tdb_reopen_all(int parent_longlived) +{ + struct tdb_context *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + bool active_lock = (tdb->flags & TDB_CLEAR_IF_FIRST); + + /* + * If the parent is longlived (ie. a + * parent daemon architecture), we know + * it will keep it's active lock on a + * tdb opened with CLEAR_IF_FIRST. Thus + * for child processes we don't have to + * add an active lock. This is essential + * to improve performance on systems that + * keep POSIX locks as a non-scalable data + * structure in the kernel. + */ + if (parent_longlived) { + /* Ensure no clear-if-first. */ + active_lock = false; + } + + if (tdb_reopen_internal(tdb, active_lock) != 0) + return -1; + } + + return 0; +} diff --git a/libatalk/tdb/tdb.c b/libatalk/tdb/tdb.c new file mode 100644 index 0000000..d2688de --- /dev/null +++ b/libatalk/tdb/tdb.c @@ -0,0 +1,1140 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +TDB_DATA tdb_null; + +/* + non-blocking increment of the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +void tdb_increment_seqnum_nonblock(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + + if (!(tdb->flags & TDB_SEQNUM)) { + return; + } + + /* we ignore errors from this, as we have no sane way of + dealing with them. + */ + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + seqnum++; + tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); +} + +/* + increment the tdb sequence number if the tdb has been opened using + the TDB_SEQNUM flag +*/ +static void tdb_increment_seqnum(struct tdb_context *tdb) +{ + if (!(tdb->flags & TDB_SEQNUM)) { + return; + } + + if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) { + return; + } + + tdb_increment_seqnum_nonblock(tdb); + + tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1); +} + +static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data) +{ + return memcmp(data.dptr, key.dptr, data.dsize); +} + +/* Returns 0 on fail. On success, return offset of record, and fills + in rec */ +static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, + struct tdb_record *r) +{ + tdb_off_t rec_ptr; + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + /* keep looking until we find the right record */ + while (rec_ptr) { + if (tdb_rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (!TDB_DEAD(r) && hash==r->full_hash + && key.dsize==r->key_len + && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r), + r->key_len, tdb_key_compare, + NULL) == 0) { + return rec_ptr; + } + /* detect tight infinite loop */ + if (rec_ptr == r->next) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_find: loop detected.\n")); + return 0; + } + rec_ptr = r->next; + } + tdb->ecode = TDB_ERR_NOEXIST; + return 0; +} + +/* As tdb_find, but if you succeed, keep the lock */ +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype, + struct tdb_record *rec) +{ + uint32_t rec_ptr; + + if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) + return 0; + if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) + tdb_unlock(tdb, BUCKET(hash), locktype); + return rec_ptr; +} + +static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key); + +/* update an entry in place - this only works if the new data size + is <= the old data size and the key exists. + on failure return -1. +*/ +static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, TDB_DATA dbuf) +{ + struct tdb_record rec; + tdb_off_t rec_ptr; + + /* find entry */ + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) + return -1; + + /* it could be an exact duplicate of what is there - this is + * surprisingly common (eg. with a ldb re-index). */ + if (rec.key_len == key.dsize && + rec.data_len == dbuf.dsize && + rec.full_hash == hash) { + TDB_DATA data = _tdb_fetch(tdb, key); + if (data.dsize == dbuf.dsize && + memcmp(data.dptr, dbuf.dptr, data.dsize) == 0) { + if (data.dptr) { + free(data.dptr); + } + return 0; + } + if (data.dptr) { + free(data.dptr); + } + } + + + /* must be long enough key, data and tailer */ + if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) { + tdb->ecode = TDB_SUCCESS; /* Not really an error */ + return -1; + } + + if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, + dbuf.dptr, dbuf.dsize) == -1) + return -1; + + if (dbuf.dsize != rec.data_len) { + /* update size */ + rec.data_len = dbuf.dsize; + return tdb_rec_write(tdb, rec_ptr, &rec); + } + + return 0; +} + +/* find an entry in the database given a key */ +/* If an entry doesn't exist tdb_err will be set to + * TDB_ERR_NOEXIST. If a key has no data attached + * then the TDB_DATA will have zero length but + * a non-zero pointer + */ +static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key) +{ + tdb_off_t rec_ptr; + struct tdb_record rec; + TDB_DATA ret; + uint32_t hash; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) + return tdb_null; + + ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len); + ret.dsize = rec.data_len; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return ret; +} + +TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) +{ + TDB_DATA ret = _tdb_fetch(tdb, key); + + tdb_trace_1rec_retrec(tdb, "tdb_fetch", key, ret); + return ret; +} + +/* + * Find an entry in the database and hand the record's data to a parsing + * function. The parsing function is executed under the chain read lock, so it + * should be fast and should not block on other syscalls. + * + * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS. + * + * For mmapped tdb's that do not have a transaction open it points the parsing + * function directly at the mmap area, it avoids the malloc/memcpy in this + * case. If a transaction is open or no mmap is available, it has to do + * malloc/read/parse/free. + * + * This is interesting for all readers of potentially large data structures in + * the tdb records, ldb indexes being one example. + */ + +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + tdb_off_t rec_ptr; + struct tdb_record rec; + int ret; + uint32_t hash; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { + tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1); + tdb->ecode = TDB_ERR_NOEXIST; + return 0; + } + tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, 0); + + ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len, parser, private_data); + + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + + return ret; +} + +/* check if an entry in the database exists + + note that 1 is returned if the key is found and 0 is returned if not found + this doesn't match the conventions in the rest of this module, but is + compatible with gdbm +*/ +static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash) +{ + struct tdb_record rec; + + if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) + return 0; + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + return 1; +} + +int tdb_exists(struct tdb_context *tdb, TDB_DATA key) +{ + uint32_t hash = tdb->hash_fn(&key); + int ret; + + ret = tdb_exists_hash(tdb, key, hash); + tdb_trace_1rec_ret(tdb, "tdb_exists", key, ret); + return ret; +} + +/* actually delete an entry in the database given the offset */ +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct tdb_record *rec) +{ + tdb_off_t last_ptr, i; + struct tdb_record lastrec; + + if (tdb->read_only || tdb->traverse_read) return -1; + + if (((tdb->traverse_write != 0) && (!TDB_DEAD(rec))) || + tdb_write_lock_record(tdb, rec_ptr) == -1) { + /* Someone traversing here: mark it as dead */ + rec->magic = TDB_DEAD_MAGIC; + return tdb_rec_write(tdb, rec_ptr, rec); + } + if (tdb_write_unlock_record(tdb, rec_ptr) != 0) + return -1; + + /* find previous record in hash chain */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) + return -1; + for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) + if (tdb_rec_read(tdb, i, &lastrec) == -1) + return -1; + + /* unlink it: next ptr is at start of record. */ + if (last_ptr == 0) + last_ptr = TDB_HASH_TOP(rec->full_hash); + if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) + return -1; + + /* recover the space */ + if (tdb_free(tdb, rec_ptr, rec) == -1) + return -1; + return 0; +} + +static int tdb_count_dead(struct tdb_context *tdb, uint32_t hash) +{ + int res = 0; + tdb_off_t rec_ptr; + struct tdb_record rec; + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + while (rec_ptr) { + if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) + return 0; + + if (rec.magic == TDB_DEAD_MAGIC) { + res += 1; + } + rec_ptr = rec.next; + } + return res; +} + +/* + * Purge all DEAD records from a hash chain + */ +static int tdb_purge_dead(struct tdb_context *tdb, uint32_t hash) +{ + int res = -1; + struct tdb_record rec; + tdb_off_t rec_ptr; + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + return -1; + } + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + goto fail; + + while (rec_ptr) { + tdb_off_t next; + + if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) { + goto fail; + } + + next = rec.next; + + if (rec.magic == TDB_DEAD_MAGIC + && tdb_do_delete(tdb, rec_ptr, &rec) == -1) { + goto fail; + } + rec_ptr = next; + } + res = 0; + fail: + tdb_unlock(tdb, -1, F_WRLCK); + return res; +} + +/* delete an entry in the database given a key */ +static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash) +{ + tdb_off_t rec_ptr; + struct tdb_record rec; + int ret; + + if (tdb->max_dead_records != 0) { + + /* + * Allow for some dead records per hash chain, mainly for + * tdb's with a very high create/delete rate like locking.tdb. + */ + + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) { + /* + * Don't let the per-chain freelist grow too large, + * delete all existing dead records + */ + tdb_purge_dead(tdb, hash); + } + + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return -1; + } + + /* + * Just mark the record as dead. + */ + rec.magic = TDB_DEAD_MAGIC; + ret = tdb_rec_write(tdb, rec_ptr, &rec); + } + else { + if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, + &rec))) + return -1; + + ret = tdb_do_delete(tdb, rec_ptr, &rec); + } + + if (ret == 0) { + tdb_increment_seqnum(tdb); + } + + if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n")); + return ret; +} + +int tdb_delete(struct tdb_context *tdb, TDB_DATA key) +{ + uint32_t hash = tdb->hash_fn(&key); + int ret; + + ret = tdb_delete_hash(tdb, key, hash); + tdb_trace_1rec_ret(tdb, "tdb_delete", key, ret); + return ret; +} + +/* + * See if we have a dead record around with enough space + */ +static tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash, + struct tdb_record *r, tdb_len_t length) +{ + tdb_off_t rec_ptr; + + /* read in the hash top */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) + return 0; + + /* keep looking until we find the right record */ + while (rec_ptr) { + if (tdb_rec_read(tdb, rec_ptr, r) == -1) + return 0; + + if (TDB_DEAD(r) && r->rec_len >= length) { + /* + * First fit for simple coding, TODO: change to best + * fit + */ + return rec_ptr; + } + rec_ptr = r->next; + } + return 0; +} + +static int _tdb_store(struct tdb_context *tdb, TDB_DATA key, + TDB_DATA dbuf, int flag, uint32_t hash) +{ + struct tdb_record rec; + tdb_off_t rec_ptr; + char *p = NULL; + int ret = -1; + + /* check for it existing, on insert. */ + if (flag == TDB_INSERT) { + if (tdb_exists_hash(tdb, key, hash)) { + tdb->ecode = TDB_ERR_EXISTS; + goto fail; + } + } else { + /* first try in-place update, on modify or replace. */ + if (tdb_update_hash(tdb, key, hash, dbuf) == 0) { + goto done; + } + if (tdb->ecode == TDB_ERR_NOEXIST && + flag == TDB_MODIFY) { + /* if the record doesn't exist and we are in TDB_MODIFY mode then + we should fail the store */ + goto fail; + } + } + /* reset the error code potentially set by the tdb_update() */ + tdb->ecode = TDB_SUCCESS; + + /* delete any existing record - if it doesn't exist we don't + care. Doing this first reduces fragmentation, and avoids + coalescing with `allocated' block before it's updated. */ + if (flag != TDB_INSERT) + tdb_delete_hash(tdb, key, hash); + + /* Copy key+value *before* allocating free space in case malloc + fails and we are left with a dead spot in the tdb. */ + + if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + + memcpy(p, key.dptr, key.dsize); + if (dbuf.dsize) + memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); + + if (tdb->max_dead_records != 0) { + /* + * Allow for some dead records per hash chain, look if we can + * find one that can hold the new record. We need enough space + * for key, data and tailer. If we find one, we don't have to + * consult the central freelist. + */ + rec_ptr = tdb_find_dead( + tdb, hash, &rec, + key.dsize + dbuf.dsize + sizeof(tdb_off_t)); + + if (rec_ptr != 0) { + rec.key_len = key.dsize; + rec.data_len = dbuf.dsize; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 + || tdb->methods->tdb_write( + tdb, rec_ptr + sizeof(rec), + p, key.dsize + dbuf.dsize) == -1) { + goto fail; + } + goto done; + } + } + + /* + * We have to allocate some space from the freelist, so this means we + * have to lock it. Use the chance to purge all the DEAD records from + * the hash chain under the freelist lock. + */ + + if (tdb_lock(tdb, -1, F_WRLCK) == -1) { + goto fail; + } + + if ((tdb->max_dead_records != 0) + && (tdb_purge_dead(tdb, hash) == -1)) { + tdb_unlock(tdb, -1, F_WRLCK); + goto fail; + } + + /* we have to allocate some space */ + rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec); + + tdb_unlock(tdb, -1, F_WRLCK); + + if (rec_ptr == 0) { + goto fail; + } + + /* Read hash top into next ptr */ + if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) + goto fail; + + rec.key_len = key.dsize; + rec.data_len = dbuf.dsize; + rec.full_hash = hash; + rec.magic = TDB_MAGIC; + + /* write out and point the top of the hash chain at it */ + if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 + || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 + || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { + /* Need to tdb_unallocate() here */ + goto fail; + } + + done: + ret = 0; + fail: + if (ret == 0) { + tdb_increment_seqnum(tdb); + } + + SAFE_FREE(p); + return ret; +} + +/* store an element in the database, replacing any existing element + with the same key + + return 0 on success, -1 on failure +*/ +int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) +{ + uint32_t hash; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + tdb->ecode = TDB_ERR_RDONLY; + tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag, -1); + return -1; + } + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + ret = _tdb_store(tdb, key, dbuf, flag, hash); + tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag, ret); + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + return ret; +} + +/* Append to an entry. Create if not exist. */ +int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) +{ + uint32_t hash; + TDB_DATA dbuf; + int ret = -1; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) + return -1; + + dbuf = _tdb_fetch(tdb, key); + + if (dbuf.dptr == NULL) { + dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize); + } else { + unsigned int new_len = dbuf.dsize + new_dbuf.dsize; + unsigned char *new_dptr; + + /* realloc '0' is special: don't do that. */ + if (new_len == 0) + new_len = 1; + new_dptr = (unsigned char *)realloc(dbuf.dptr, new_len); + if (new_dptr == NULL) { + free(dbuf.dptr); + } + dbuf.dptr = new_dptr; + } + + if (dbuf.dptr == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto failed; + } + + memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); + dbuf.dsize += new_dbuf.dsize; + + ret = _tdb_store(tdb, key, dbuf, 0, hash); + tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf); + +failed: + tdb_unlock(tdb, BUCKET(hash), F_WRLCK); + SAFE_FREE(dbuf.dptr); + return ret; +} + + +/* + return the name of the current tdb file + useful for external logging functions +*/ +const char *tdb_name(struct tdb_context *tdb) +{ + return tdb->name; +} + +/* + return the underlying file descriptor being used by tdb, or -1 + useful for external routines that want to check the device/inode + of the fd +*/ +int tdb_fd(struct tdb_context *tdb) +{ + return tdb->fd; +} + +/* + return the current logging function + useful for external tdb routines that wish to log tdb errors +*/ +tdb_log_func tdb_log_fn(struct tdb_context *tdb) +{ + return tdb->log.log_fn; +} + + +/* + get the tdb sequence number. Only makes sense if the writers opened + with TDB_SEQNUM set. Note that this sequence number will wrap quite + quickly, so it should only be used for a 'has something changed' + test, not for code that relies on the count of the number of changes + made. If you want a counter then use a tdb record. + + The aim of this sequence number is to allow for a very lightweight + test of a possible tdb change. +*/ +int tdb_get_seqnum(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + return seqnum; +} + +int tdb_hash_size(struct tdb_context *tdb) +{ + return tdb->header.hash_size; +} + +size_t tdb_map_size(struct tdb_context *tdb) +{ + return tdb->map_size; +} + +int tdb_get_flags(struct tdb_context *tdb) +{ + return tdb->flags; +} + +void tdb_add_flags(struct tdb_context *tdb, unsigned flags) +{ + if ((flags & TDB_ALLOW_NESTING) && + (flags & TDB_DISALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_add_flags: " + "allow_nesting and disallow_nesting are not allowed together!")); + return; + } + + if (flags & TDB_ALLOW_NESTING) { + tdb->flags &= ~TDB_DISALLOW_NESTING; + } + if (flags & TDB_DISALLOW_NESTING) { + tdb->flags &= ~TDB_ALLOW_NESTING; + } + + tdb->flags |= flags; +} + +void tdb_remove_flags(struct tdb_context *tdb, unsigned flags) +{ + if ((flags & TDB_ALLOW_NESTING) && + (flags & TDB_DISALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_remove_flags: " + "allow_nesting and disallow_nesting are not allowed together!")); + return; + } + + if (flags & TDB_ALLOW_NESTING) { + tdb->flags |= TDB_DISALLOW_NESTING; + } + if (flags & TDB_DISALLOW_NESTING) { + tdb->flags |= TDB_ALLOW_NESTING; + } + + tdb->flags &= ~flags; +} + + +/* + enable sequence number handling on an open tdb +*/ +void tdb_enable_seqnum(struct tdb_context *tdb) +{ + tdb->flags |= TDB_SEQNUM; +} + + +/* + add a region of the file to the freelist. Length is the size of the region in bytes, + which includes the free list header that needs to be added + */ +static int tdb_free_region(struct tdb_context *tdb, tdb_off_t offset, ssize_t length) +{ + struct tdb_record rec; + if (length <= sizeof(rec)) { + /* the region is not worth adding */ + return 0; + } + if (length + offset > tdb->map_size) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: adding region beyond end of file\n")); + return -1; + } + memset(&rec,'\0',sizeof(rec)); + rec.rec_len = length - sizeof(rec); + if (tdb_free(tdb, offset, &rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_free_region: failed to add free record\n")); + return -1; + } + return 0; +} + +/* + wipe the entire database, deleting all records. This can be done + very fast by using a global lock. The entire data portion of the + file becomes a single entry in the freelist. + + This code carefully steps around the recovery area, leaving it alone + */ +int tdb_wipe_all(struct tdb_context *tdb) +{ + int i; + tdb_off_t offset = 0; + ssize_t data_len; + tdb_off_t recovery_head; + tdb_len_t recovery_size = 0; + + if (tdb_lockall(tdb) != 0) { + return -1; + } + + tdb_trace(tdb, "tdb_wipe_all"); + + /* see if the tdb has a recovery area, and remember its size + if so. We don't want to lose this as otherwise each + tdb_wipe_all() in a transaction will increase the size of + the tdb by the size of the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery head\n")); + goto failed; + } + + if (recovery_head != 0) { + struct tdb_record rec; + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_wipe_all: failed to read recovery record\n")); + return -1; + } + recovery_size = rec.rec_len + sizeof(rec); + } + + /* wipe the hashes */ + for (i=0;iheader.hash_size;i++) { + if (tdb_ofs_write(tdb, TDB_HASH_TOP(i), &offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to write hash %d\n", i)); + goto failed; + } + } + + /* wipe the freelist */ + if (tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to write freelist\n")); + goto failed; + } + + /* add all the rest of the file to the freelist, possibly leaving a gap + for the recovery area */ + if (recovery_size == 0) { + /* the simple case - the whole file can be used as a freelist */ + data_len = (tdb->map_size - TDB_DATA_START(tdb->header.hash_size)); + if (tdb_free_region(tdb, TDB_DATA_START(tdb->header.hash_size), data_len) != 0) { + goto failed; + } + } else { + /* we need to add two freelist entries - one on either + side of the recovery area + + Note that we cannot shift the recovery area during + this operation. Only the transaction.c code may + move the recovery area or we risk subtle data + corruption + */ + data_len = (recovery_head - TDB_DATA_START(tdb->header.hash_size)); + if (tdb_free_region(tdb, TDB_DATA_START(tdb->header.hash_size), data_len) != 0) { + goto failed; + } + /* and the 2nd free list entry after the recovery area - if any */ + data_len = tdb->map_size - (recovery_head+recovery_size); + if (tdb_free_region(tdb, recovery_head+recovery_size, data_len) != 0) { + goto failed; + } + } + + if (tdb_unlockall(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_wipe_all: failed to unlock\n")); + goto failed; + } + + return 0; + +failed: + tdb_unlockall(tdb); + return -1; +} + +struct traverse_state { + bool error; + struct tdb_context *dest_db; +}; + +/* + traverse function for repacking + */ +static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data) +{ + struct traverse_state *state = (struct traverse_state *)private_data; + if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) { + state->error = true; + return -1; + } + return 0; +} + +/* + repack a tdb + */ +int tdb_repack(struct tdb_context *tdb) +{ + struct tdb_context *tmp_db; + struct traverse_state state; + + tdb_trace(tdb, "tdb_repack"); + + if (tdb_transaction_start(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to start transaction\n")); + return -1; + } + + tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb), TDB_INTERNAL, O_RDWR|O_CREAT, 0); + if (tmp_db == NULL) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to create tmp_db\n")); + tdb_transaction_cancel(tdb); + return -1; + } + + state.error = false; + state.dest_db = tmp_db; + + if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying out\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (state.error) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during traversal\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (tdb_wipe_all(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to wipe database\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + state.error = false; + state.dest_db = tdb; + + if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying back\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (state.error) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during second traversal\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + tdb_close(tmp_db); + + if (tdb_transaction_commit(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to commit\n")); + return -1; + } + + return 0; +} + +#ifdef TDB_TRACE +static void tdb_trace_write(struct tdb_context *tdb, const char *str) +{ + if (write(tdb->tracefd, str, strlen(str)) != strlen(str)) { + close(tdb->tracefd); + tdb->tracefd = -1; + } +} + +static void tdb_trace_start(struct tdb_context *tdb) +{ + tdb_off_t seqnum=0; + char msg[sizeof(tdb_off_t) * 4 + 1]; + + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + snprintf(msg, sizeof(msg), "%u ", seqnum); + tdb_trace_write(tdb, msg); +} + +static void tdb_trace_end(struct tdb_context *tdb) +{ + tdb_trace_write(tdb, "\n"); +} + +static void tdb_trace_end_ret(struct tdb_context *tdb, int ret) +{ + char msg[sizeof(ret) * 4 + 4]; + snprintf(msg, sizeof(msg), " = %i\n", ret); + tdb_trace_write(tdb, msg); +} + +static void tdb_trace_record(struct tdb_context *tdb, TDB_DATA rec) +{ + char msg[20 + rec.dsize*2], *p; + unsigned int i; + + /* We differentiate zero-length records from non-existent ones. */ + if (rec.dptr == NULL) { + tdb_trace_write(tdb, " NULL"); + return; + } + + /* snprintf here is purely cargo-cult programming. */ + p = msg; + p += snprintf(p, sizeof(msg), " %zu:", rec.dsize); + for (i = 0; i < rec.dsize; i++) + p += snprintf(p, 2, "%02x", rec.dptr[i]); + + tdb_trace_write(tdb, msg); +} + +void tdb_trace(struct tdb_context *tdb, const char *op) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_end(tdb); +} + +void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op) +{ + char msg[sizeof(tdb_off_t) * 4 + 1]; + + snprintf(msg, sizeof(msg), "%u ", seqnum); + tdb_trace_write(tdb, msg); + tdb_trace_write(tdb, op); + tdb_trace_end(tdb); +} + +void tdb_trace_open(struct tdb_context *tdb, const char *op, + unsigned hash_size, unsigned tdb_flags, unsigned open_flags) +{ + char msg[128]; + + snprintf(msg, sizeof(msg), + "%s %u 0x%x 0x%x", op, hash_size, tdb_flags, open_flags); + tdb_trace_start(tdb); + tdb_trace_write(tdb, msg); + tdb_trace_end(tdb); +} + +void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_end_ret(tdb, ret); +} + +void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_write(tdb, " ="); + tdb_trace_record(tdb, ret); + tdb_trace_end(tdb); +} + +void tdb_trace_1rec(struct tdb_context *tdb, const char *op, + TDB_DATA rec) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec); + tdb_trace_end(tdb); +} + +void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op, + TDB_DATA rec, int ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec); + tdb_trace_end_ret(tdb, ret); +} + +void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op, + TDB_DATA rec, TDB_DATA ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec); + tdb_trace_write(tdb, " ="); + tdb_trace_record(tdb, ret); + tdb_trace_end(tdb); +} + +void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op, + TDB_DATA rec1, TDB_DATA rec2, unsigned flag, + int ret) +{ + char msg[1 + sizeof(ret) * 4]; + + snprintf(msg, sizeof(msg), " %#x", flag); + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec1); + tdb_trace_record(tdb, rec2); + tdb_trace_write(tdb, msg); + tdb_trace_end_ret(tdb, ret); +} + +void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op, + TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret) +{ + tdb_trace_start(tdb); + tdb_trace_write(tdb, op); + tdb_trace_record(tdb, rec1); + tdb_trace_record(tdb, rec2); + tdb_trace_write(tdb, " ="); + tdb_trace_record(tdb, ret); + tdb_trace_end(tdb); +} +#endif diff --git a/libatalk/tdb/tdb_private.h b/libatalk/tdb/tdb_private.h new file mode 100644 index 0000000..de5dd02 --- /dev/null +++ b/libatalk/tdb/tdb_private.h @@ -0,0 +1,279 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library - private includes + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#ifndef __STRINGSTRING +#define __STRINGSTRING(x) __STRING(x) +#endif + +#ifndef __LINESTR__ +#define __LINESTR__ __STRINGSTRING(__LINE__) +#endif + +#ifndef __location__ +#define __location__ __FILE__ ":" __LINESTR__ +#endif + +#include +#include "atalk/tdb.h" + +/* #define TDB_TRACE 1 */ +#ifndef HAVE_GETPAGESIZE +#define getpagesize() 0x2000 +#endif + +typedef uint32_t tdb_len_t; +typedef uint32_t tdb_off_t; + +#define TDB_MAGIC_FOOD "TDB file\n" +#define TDB_VERSION (0x26011967 + 6) +#define TDB_MAGIC (0x26011999U) +#define TDB_FREE_MAGIC (~TDB_MAGIC) +#define TDB_DEAD_MAGIC (0xFEE1DEAD) +#define TDB_RECOVERY_MAGIC (0xf53bc0e7U) +#define TDB_ALIGNMENT 4 +#define DEFAULT_HASH_SIZE 131 +#define FREELIST_TOP (sizeof(struct tdb_header)) +#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) +#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) +#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) +#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) +#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) +#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t)) +#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + sizeof(tdb_off_t)) +#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start) +#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number) +#define TDB_PAD_BYTE 0x42 +#define TDB_PAD_U32 0x42424242 + +/* NB assumes there is a local variable called "tdb" that is the + * current context, also takes doubly-parenthesized print-style + * argument. */ +#define TDB_LOG(x) tdb->log.log_fn x + +#ifdef TDB_TRACE +void tdb_trace(struct tdb_context *tdb, const char *op); +void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op); +void tdb_trace_open(struct tdb_context *tdb, const char *op, + unsigned hash_size, unsigned tdb_flags, unsigned open_flags); +void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret); +void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret); +void tdb_trace_1rec(struct tdb_context *tdb, const char *op, + TDB_DATA rec); +void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op, + TDB_DATA rec, int ret); +void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op, + TDB_DATA rec, TDB_DATA ret); +void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op, + TDB_DATA rec1, TDB_DATA rec2, unsigned flag, + int ret); +void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op, + TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret); +#else +#define tdb_trace(tdb, op) +#define tdb_trace_seqnum(tdb, seqnum, op) +#define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags) +#define tdb_trace_ret(tdb, op, ret) +#define tdb_trace_retrec(tdb, op, ret) +#define tdb_trace_1rec(tdb, op, rec) +#define tdb_trace_1rec_ret(tdb, op, rec, ret) +#define tdb_trace_1rec_retrec(tdb, op, rec, ret) +#define tdb_trace_2rec_flag_ret(tdb, op, rec1, rec2, flag, ret) +#define tdb_trace_2rec_retrec(tdb, op, rec1, rec2, ret) +#endif /* !TDB_TRACE */ + +/* lock offsets */ +#define GLOBAL_LOCK 0 +#define ACTIVE_LOCK 4 +#define TRANSACTION_LOCK 8 + +/* free memory if the pointer is valid and zero the pointer */ +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) +#endif + +#define BUCKET(hash) ((hash) % tdb->header.hash_size) + +#define DOCONV() (tdb->flags & TDB_CONVERT) +#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x) + + +/* the body of the database is made of one tdb_record for the free space + plus a separate data list for each hash value */ +struct tdb_record { + tdb_off_t next; /* offset of the next record in the list */ + tdb_len_t rec_len; /* total byte length of record */ + tdb_len_t key_len; /* byte length of key */ + tdb_len_t data_len; /* byte length of data */ + uint32_t full_hash; /* the full 32 bit hash of the key */ + uint32_t magic; /* try to catch errors */ + /* the following union is implied: + union { + char record[rec_len]; + struct { + char key[key_len]; + char data[data_len]; + } + uint32_t totalsize; (tailer) + } + */ +}; + + +/* this is stored at the front of every database */ +struct tdb_header { + char magic_food[32]; /* for /etc/magic */ + uint32_t version; /* version of the code */ + uint32_t hash_size; /* number of hash entries */ + tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ + tdb_off_t recovery_start; /* offset of transaction recovery region */ + tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ + tdb_off_t reserved[29]; +}; + +struct tdb_lock_type { + int list; + uint32_t count; + uint32_t ltype; +}; + +struct tdb_traverse_lock { + struct tdb_traverse_lock *next; + uint32_t off; + uint32_t hash; + int lock_rw; +}; + + +struct tdb_methods { + int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int ); + int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t); + void (*next_hash_chain)(struct tdb_context *, uint32_t *); + int (*tdb_oob)(struct tdb_context *, tdb_off_t , int ); + int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); + int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t); +}; + +struct tdb_context { + char *name; /* the name of the database */ + void *map_ptr; /* where it is currently mapped */ + int fd; /* open file descriptor for the database */ + tdb_len_t map_size; /* how much space has been mapped */ + int read_only; /* opened read-only */ + int traverse_read; /* read-only traversal */ + int traverse_write; /* read-write traversal */ + struct tdb_lock_type global_lock; + int num_lockrecs; + struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */ + enum TDB_ERROR ecode; /* error code for last tdb error */ + struct tdb_header header; /* a cached copy of the header */ + uint32_t flags; /* the flags passed to tdb_open */ + struct tdb_traverse_lock travlocks; /* current traversal locks */ + struct tdb_context *next; /* all tdbs to avoid multiple opens */ + dev_t device; /* uniquely identifies this tdb */ + ino_t inode; /* uniquely identifies this tdb */ + struct tdb_logging_context log; + unsigned int (*hash_fn)(TDB_DATA *key); + int open_flags; /* flags used in the open - needed by reopen */ + unsigned int num_locks; /* number of chain locks held */ + const struct tdb_methods *methods; + struct tdb_transaction *transaction; + int page_size; + int max_dead_records; + int transaction_lock_count; +#ifdef TDB_TRACE + int tracefd; +#endif + volatile sig_atomic_t *interrupt_sig_ptr; +}; + + +/* + internal prototypes +*/ +int tdb_munmap(struct tdb_context *tdb); +void tdb_mmap(struct tdb_context *tdb); +int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); +int tdb_unlock(struct tdb_context *tdb, int list, int ltype); +int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); +int tdb_transaction_lock(struct tdb_context *tdb, int ltype); +int tdb_transaction_unlock(struct tdb_context *tdb); +int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len); +int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +void *tdb_convert(void *buf, uint32_t size); +int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); +tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec); +int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); +int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); +int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); +int _tdb_transaction_cancel(struct tdb_context *tdb); +int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); +int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); +int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct tdb_record *rec); +unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); +int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, + tdb_off_t offset, tdb_len_t len, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data); +tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype, + struct tdb_record *rec); +void tdb_io_init(struct tdb_context *tdb); +int tdb_expand(struct tdb_context *tdb, tdb_off_t size); +int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, + struct tdb_record *rec); + + diff --git a/libatalk/tdb/transaction.c b/libatalk/tdb/transaction.c new file mode 100644 index 0000000..b8988ea --- /dev/null +++ b/libatalk/tdb/transaction.c @@ -0,0 +1,1236 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +/* + transaction design: + + - only allow a single transaction at a time per database. This makes + using the transaction API simpler, as otherwise the caller would + have to cope with temporary failures in transactions that conflict + with other current transactions + + - keep the transaction recovery information in the same file as the + database, using a special 'transaction recovery' record pointed at + by the header. This removes the need for extra journal files as + used by some other databases + + - dynamically allocated the transaction recover record, re-using it + for subsequent transactions. If a larger record is needed then + tdb_free() the old record to place it on the normal tdb freelist + before allocating the new record + + - during transactions, keep a linked list of writes all that have + been performed by intercepting all tdb_write() calls. The hooked + transaction versions of tdb_read() and tdb_write() check this + linked list and try to use the elements of the list in preference + to the real database. + + - don't allow any locks to be held when a transaction starts, + otherwise we can end up with deadlock (plus lack of lock nesting + in posix locks would mean the lock is lost) + + - if the caller gains a lock during the transaction but doesn't + release it then fail the commit + + - allow for nested calls to tdb_transaction_start(), re-using the + existing transaction record. If the inner transaction is cancelled + then a subsequent commit will fail + + - keep a mirrored copy of the tdb hash chain heads to allow for the + fast hash heads scan on traverse, updating the mirrored copy in + the transaction version of tdb_write + + - allow callers to mix transaction and non-transaction use of tdb, + although once a transaction is started then an exclusive lock is + gained until the transaction is committed or cancelled + + - the commit stategy involves first saving away all modified data + into a linearised buffer in the transaction recovery area, then + marking the transaction recovery area with a magic value to + indicate a valid recovery record. In total 4 fsync/msync calls are + needed per commit to prevent race conditions. It might be possible + to reduce this to 3 or even 2 with some more work. + + - check for a valid recovery record on open of the tdb, while the + global lock is held. Automatically recover from the transaction + recovery area if needed, then continue with the open as + usual. This allows for smooth crash recovery with no administrator + intervention. + + - if TDB_NOSYNC is passed to flags in tdb_open then transactions are + still available, but no transaction recovery area is used and no + fsync/msync calls are made. + + - if TDB_ALLOW_NESTING is passed to flags in tdb open, or added using + tdb_add_flags() transaction nesting is enabled. + It resets the TDB_DISALLOW_NESTING flag, as both cannot be used together. + The default is that transaction nesting is allowed. + Note: this default may change in future versions of tdb. + + Beware. when transactions are nested a transaction successfully + completed with tdb_transaction_commit() can be silently unrolled later. + + - if TDB_DISALLOW_NESTING is passed to flags in tdb open, or added using + tdb_add_flags() transaction nesting is disabled. + It resets the TDB_ALLOW_NESTING flag, as both cannot be used together. + An attempt create a nested transaction will fail with TDB_ERR_NESTING. + The default is that transaction nesting is allowed. + Note: this default may change in future versions of tdb. +*/ + + +/* + hold the context of any current transaction +*/ +struct tdb_transaction { + /* we keep a mirrored copy of the tdb hash heads here so + tdb_next_hash_chain() can operate efficiently */ + uint32_t *hash_heads; + + /* the original io methods - used to do IOs to the real db */ + const struct tdb_methods *io_methods; + + /* the list of transaction blocks. When a block is first + written to, it gets created in this list */ + uint8_t **blocks; + uint32_t num_blocks; + uint32_t block_size; /* bytes in each block */ + uint32_t last_block_size; /* number of valid bytes in the last block */ + + /* non-zero when an internal transaction error has + occurred. All write operations will then fail until the + transaction is ended */ + int transaction_error; + + /* when inside a transaction we need to keep track of any + nested tdb_transaction_start() calls, as these are allowed, + but don't create a new transaction */ + int nesting; + + /* set when a prepare has already occurred */ + bool prepared; + tdb_off_t magic_offset; + + /* set when the GLOBAL_LOCK has been taken */ + bool global_lock_taken; + + /* old file size before transaction */ + tdb_len_t old_map_size; + + /* we should re-pack on commit */ + bool need_repack; +}; + + +/* + read while in a transaction. We need to check first if the data is in our list + of transaction elements, then if not do a real read +*/ +static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, + tdb_len_t len, int cv) +{ + uint32_t blk; + + /* break it down into block sized ops */ + while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size); + if (transaction_read(tdb, off, buf, len2, cv) != 0) { + return -1; + } + len -= len2; + off += len2; + buf = (void *)(len2 + (char *)buf); + } + + if (len == 0) { + return 0; + } + + blk = off / tdb->transaction->block_size; + + /* see if we have it in the block list */ + if (tdb->transaction->num_blocks <= blk || + tdb->transaction->blocks[blk] == NULL) { + /* nope, do a real read */ + if (tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv) != 0) { + goto fail; + } + return 0; + } + + /* it is in the block list. Now check for the last block */ + if (blk == tdb->transaction->num_blocks-1) { + if (len > tdb->transaction->last_block_size) { + goto fail; + } + } + + /* now copy it out of this block */ + memcpy(buf, tdb->transaction->blocks[blk] + (off % tdb->transaction->block_size), len); + if (cv) { + tdb_convert(buf, len); + } + return 0; + +fail: + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len)); + tdb->ecode = TDB_ERR_IO; + tdb->transaction->transaction_error = 1; + return -1; +} + + +/* + write while in a transaction +*/ +static int transaction_write(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + uint32_t blk; + + /* Only a commit is allowed on a prepared transaction */ + if (tdb->transaction->prepared) { + tdb->ecode = TDB_ERR_EINVAL; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: transaction already prepared, write not allowed\n")); + tdb->transaction->transaction_error = 1; + return -1; + } + + /* if the write is to a hash head, then update the transaction + hash heads */ + if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP && + off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) { + uint32_t chain = (off-FREELIST_TOP) / sizeof(tdb_off_t); + memcpy(&tdb->transaction->hash_heads[chain], buf, len); + } + + /* break it up into block sized chunks */ + while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size); + if (transaction_write(tdb, off, buf, len2) != 0) { + return -1; + } + len -= len2; + off += len2; + if (buf != NULL) { + buf = (const void *)(len2 + (const char *)buf); + } + } + + if (len == 0) { + return 0; + } + + blk = off / tdb->transaction->block_size; + off = off % tdb->transaction->block_size; + + if (tdb->transaction->num_blocks <= blk) { + uint8_t **new_blocks; + /* expand the blocks array */ + if (tdb->transaction->blocks == NULL) { + new_blocks = (uint8_t **)malloc( + (blk+1)*sizeof(uint8_t *)); + } else { + new_blocks = (uint8_t **)realloc( + tdb->transaction->blocks, + (blk+1)*sizeof(uint8_t *)); + } + if (new_blocks == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + memset(&new_blocks[tdb->transaction->num_blocks], 0, + (1+(blk - tdb->transaction->num_blocks))*sizeof(uint8_t *)); + tdb->transaction->blocks = new_blocks; + tdb->transaction->num_blocks = blk+1; + tdb->transaction->last_block_size = 0; + } + + /* allocate and fill a block? */ + if (tdb->transaction->blocks[blk] == NULL) { + tdb->transaction->blocks[blk] = (uint8_t *)calloc(tdb->transaction->block_size, 1); + if (tdb->transaction->blocks[blk] == NULL) { + tdb->ecode = TDB_ERR_OOM; + tdb->transaction->transaction_error = 1; + return -1; + } + if (tdb->transaction->old_map_size > blk * tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size; + if (len2 + (blk * tdb->transaction->block_size) > tdb->transaction->old_map_size) { + len2 = tdb->transaction->old_map_size - (blk * tdb->transaction->block_size); + } + if (tdb->transaction->io_methods->tdb_read(tdb, blk * tdb->transaction->block_size, + tdb->transaction->blocks[blk], + len2, 0) != 0) { + SAFE_FREE(tdb->transaction->blocks[blk]); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + if (blk == tdb->transaction->num_blocks-1) { + tdb->transaction->last_block_size = len2; + } + } + } + + /* overwrite part of an existing block */ + if (buf == NULL) { + memset(tdb->transaction->blocks[blk] + off, 0, len); + } else { + memcpy(tdb->transaction->blocks[blk] + off, buf, len); + } + if (blk == tdb->transaction->num_blocks-1) { + if (len + off > tdb->transaction->last_block_size) { + tdb->transaction->last_block_size = len + off; + } + } + + return 0; + +fail: + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", + (blk*tdb->transaction->block_size) + off, len)); + tdb->transaction->transaction_error = 1; + return -1; +} + + +/* + write while in a transaction - this varient never expands the transaction blocks, it only + updates existing blocks. This means it cannot change the recovery size +*/ +static int transaction_write_existing(struct tdb_context *tdb, tdb_off_t off, + const void *buf, tdb_len_t len) +{ + uint32_t blk; + + /* break it up into block sized chunks */ + while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) { + tdb_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size); + if (transaction_write_existing(tdb, off, buf, len2) != 0) { + return -1; + } + len -= len2; + off += len2; + if (buf != NULL) { + buf = (const void *)(len2 + (const char *)buf); + } + } + + if (len == 0) { + return 0; + } + + blk = off / tdb->transaction->block_size; + off = off % tdb->transaction->block_size; + + if (tdb->transaction->num_blocks <= blk || + tdb->transaction->blocks[blk] == NULL) { + return 0; + } + + if (blk == tdb->transaction->num_blocks-1 && + off + len > tdb->transaction->last_block_size) { + if (off >= tdb->transaction->last_block_size) { + return 0; + } + len = tdb->transaction->last_block_size - off; + } + + /* overwrite part of an existing block */ + memcpy(tdb->transaction->blocks[blk] + off, buf, len); + + return 0; +} + + +/* + accelerated hash chain head search, using the cached hash heads +*/ +static void transaction_next_hash_chain(struct tdb_context *tdb, uint32_t *chain) +{ + uint32_t h = *chain; + for (;h < tdb->header.hash_size;h++) { + /* the +1 takes account of the freelist */ + if (0 != tdb->transaction->hash_heads[h+1]) { + break; + } + } + (*chain) = h; +} + +/* + out of bounds check during a transaction +*/ +static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +{ + if (len <= tdb->map_size) { + return 0; + } + tdb->ecode = TDB_ERR_IO; + return -1; +} + +/* + transaction version of tdb_expand(). +*/ +static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, + tdb_off_t addition) +{ + /* add a write to the transaction elements, so subsequent + reads see the zero data */ + if (transaction_write(tdb, size, NULL, addition) != 0) { + return -1; + } + + tdb->transaction->need_repack = true; + + return 0; +} + +/* + brlock during a transaction - ignore them +*/ +static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, + int rw_type, int lck_type, int probe, size_t len) +{ + return 0; +} + +static const struct tdb_methods transaction_methods = { + transaction_read, + transaction_write, + transaction_next_hash_chain, + transaction_oob, + transaction_expand_file, + transaction_brlock +}; + + +/* + start a tdb transaction. No token is returned, as only a single + transaction is allowed to be pending per tdb_context +*/ +int tdb_transaction_start(struct tdb_context *tdb) +{ + /* some sanity checks */ + if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); + tdb->ecode = TDB_ERR_EINVAL; + return -1; + } + + /* cope with nested tdb_transaction_start() calls */ + if (tdb->transaction != NULL) { + if (!(tdb->flags & TDB_ALLOW_NESTING)) { + tdb->ecode = TDB_ERR_NESTING; + return -1; + } + tdb->transaction->nesting++; + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", + tdb->transaction->nesting)); + return 0; + } + + if (tdb->num_locks != 0 || tdb->global_lock.count) { + /* the caller must not have any locks when starting a + transaction as otherwise we'll be screwed by lack + of nested locks in posix */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + if (tdb->travlocks.next != NULL) { + /* you cannot use transactions inside a traverse (although you can use + traverse inside a transaction) as otherwise you can end up with + deadlock */ + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n")); + tdb->ecode = TDB_ERR_LOCK; + return -1; + } + + tdb->transaction = (struct tdb_transaction *) + calloc(sizeof(struct tdb_transaction), 1); + if (tdb->transaction == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* a page at a time seems like a reasonable compromise between compactness and efficiency */ + tdb->transaction->block_size = tdb->page_size; + + /* get the transaction write lock. This is a blocking lock. As + discussed with Volker, there are a number of ways we could + make this async, which we will probably do in the future */ + if (tdb_transaction_lock(tdb, F_WRLCK) == -1) { + SAFE_FREE(tdb->transaction->blocks); + SAFE_FREE(tdb->transaction); + return -1; + } + + /* get a read lock from the freelist to the end of file. This + is upgraded to a write lock during the commit */ + if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + goto fail; + } + + /* setup a copy of the hash table heads so the hash scan in + traverse can be fast */ + tdb->transaction->hash_heads = (uint32_t *) + calloc(tdb->header.hash_size+1, sizeof(uint32_t)); + if (tdb->transaction->hash_heads == NULL) { + tdb->ecode = TDB_ERR_OOM; + goto fail; + } + if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, + TDB_HASHTABLE_SIZE(tdb), 0) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n")); + tdb->ecode = TDB_ERR_IO; + goto fail; + } + + /* make sure we know about any file expansions already done by + anyone else */ + tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); + tdb->transaction->old_map_size = tdb->map_size; + + /* finally hook the io methods, replacing them with + transaction specific methods */ + tdb->transaction->io_methods = tdb->methods; + tdb->methods = &transaction_methods; + + /* Trace at the end, so we get sequence number correct. */ + tdb_trace(tdb, "tdb_transaction_start"); + return 0; + +fail: + tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_transaction_unlock(tdb); + SAFE_FREE(tdb->transaction->blocks); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + return -1; +} + + +/* + sync to disk +*/ +static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length) +{ + if (tdb->flags & TDB_NOSYNC) { + return 0; + } + + if (fsync(tdb->fd) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n")); + return -1; + } +#ifdef HAVE_MMAP + if (tdb->map_ptr) { + tdb_off_t moffset = offset & ~(tdb->page_size-1); + if (msync(moffset + (char *)tdb->map_ptr, + length + (offset - moffset), MS_SYNC) != 0) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n", + strerror(errno))); + return -1; + } + } +#endif + return 0; +} + + +int _tdb_transaction_cancel(struct tdb_context *tdb) +{ + int i, ret = 0; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n")); + return -1; + } + + if (tdb->transaction->nesting != 0) { + tdb->transaction->transaction_error = 1; + tdb->transaction->nesting--; + return 0; + } + + tdb->map_size = tdb->transaction->old_map_size; + + /* free all the transaction blocks */ + for (i=0;itransaction->num_blocks;i++) { + if (tdb->transaction->blocks[i] != NULL) { + free(tdb->transaction->blocks[i]); + } + } + SAFE_FREE(tdb->transaction->blocks); + + if (tdb->transaction->magic_offset) { + const struct tdb_methods *methods = tdb->transaction->io_methods; + uint32_t zero = 0; + + /* remove the recovery marker */ + if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &zero, 4) == -1 || + transaction_sync(tdb, tdb->transaction->magic_offset, 4) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_cancel: failed to remove recovery magic\n")); + ret = -1; + } + } + + if (tdb->transaction->global_lock_taken) { + tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); + tdb->transaction->global_lock_taken = false; + } + + /* remove any global lock created during the transaction */ + if (tdb->global_lock.count != 0) { + tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size); + tdb->global_lock.count = 0; + } + + /* remove any locks created during the transaction */ + if (tdb->num_locks != 0) { + for (i=0;inum_lockrecs;i++) { + tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list, + F_UNLCK,F_SETLKW, 0, 1); + } + tdb->num_locks = 0; + tdb->num_lockrecs = 0; + SAFE_FREE(tdb->lockrecs); + } + + /* restore the normal io methods */ + tdb->methods = tdb->transaction->io_methods; + + tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); + tdb_transaction_unlock(tdb); + SAFE_FREE(tdb->transaction->hash_heads); + SAFE_FREE(tdb->transaction); + + return ret; +} + +/* + cancel the current transaction +*/ +int tdb_transaction_cancel(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_transaction_cancel"); + return _tdb_transaction_cancel(tdb); +} + +/* + work out how much space the linearised recovery data will consume +*/ +static tdb_len_t tdb_recovery_size(struct tdb_context *tdb) +{ + tdb_len_t recovery_size = 0; + int i; + + recovery_size = sizeof(uint32_t); + for (i=0;itransaction->num_blocks;i++) { + if (i * tdb->transaction->block_size >= tdb->transaction->old_map_size) { + break; + } + if (tdb->transaction->blocks[i] == NULL) { + continue; + } + recovery_size += 2*sizeof(tdb_off_t); + if (i == tdb->transaction->num_blocks-1) { + recovery_size += tdb->transaction->last_block_size; + } else { + recovery_size += tdb->transaction->block_size; + } + } + + return recovery_size; +} + +/* + allocate the recovery area, or use an existing recovery area if it is + large enough +*/ +static int tdb_recovery_allocate(struct tdb_context *tdb, + tdb_len_t *recovery_size, + tdb_off_t *recovery_offset, + tdb_len_t *recovery_max_size) +{ + struct tdb_record rec; + const struct tdb_methods *methods = tdb->transaction->io_methods; + tdb_off_t recovery_head; + + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n")); + return -1; + } + + rec.rec_len = 0; + + if (recovery_head != 0 && + methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n")); + return -1; + } + + *recovery_size = tdb_recovery_size(tdb); + + if (recovery_head != 0 && *recovery_size <= rec.rec_len) { + /* it fits in the existing area */ + *recovery_max_size = rec.rec_len; + *recovery_offset = recovery_head; + return 0; + } + + /* we need to free up the old recovery area, then allocate a + new one at the end of the file. Note that we cannot use + tdb_allocate() to allocate the new one as that might return + us an area that is being currently used (as of the start of + the transaction) */ + if (recovery_head != 0) { + if (tdb_free(tdb, recovery_head, &rec) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n")); + return -1; + } + } + + /* the tdb_free() call might have increased the recovery size */ + *recovery_size = tdb_recovery_size(tdb); + + /* round up to a multiple of page size */ + *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec); + *recovery_offset = tdb->map_size; + recovery_head = *recovery_offset; + + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + (tdb->map_size - tdb->transaction->old_map_size) + + sizeof(rec) + *recovery_max_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n")); + return -1; + } + + /* remap the file (if using mmap) */ + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + + /* we have to reset the old map size so that we don't try to expand the file + again in the transaction commit, which would destroy the recovery area */ + tdb->transaction->old_map_size = tdb->map_size; + + /* write the recovery header offset and sync - we can sync without a race here + as the magic ptr in the recovery record has not been set */ + CONVERT(recovery_head); + if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, + &recovery_head, sizeof(tdb_off_t)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); + return -1; + } + if (transaction_write_existing(tdb, TDB_RECOVERY_HEAD, &recovery_head, sizeof(tdb_off_t)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); + return -1; + } + + return 0; +} + + +/* + setup the recovery data that will be used on a crash during commit +*/ +static int transaction_setup_recovery(struct tdb_context *tdb, + tdb_off_t *magic_offset) +{ + tdb_len_t recovery_size; + unsigned char *data, *p; + const struct tdb_methods *methods = tdb->transaction->io_methods; + struct tdb_record *rec; + tdb_off_t recovery_offset, recovery_max_size; + tdb_off_t old_map_size = tdb->transaction->old_map_size; + uint32_t magic, tailer; + int i; + + /* + check that the recovery area has enough space + */ + if (tdb_recovery_allocate(tdb, &recovery_size, + &recovery_offset, &recovery_max_size) == -1) { + return -1; + } + + data = (unsigned char *)malloc(recovery_size + sizeof(*rec)); + if (data == NULL) { + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + rec = (struct tdb_record *)data; + memset(rec, 0, sizeof(*rec)); + + rec->magic = 0; + rec->data_len = recovery_size; + rec->rec_len = recovery_max_size; + rec->key_len = old_map_size; + CONVERT(rec); + + /* build the recovery data into a single blob to allow us to do a single + large write, which should be more efficient */ + p = data + sizeof(*rec); + for (i=0;itransaction->num_blocks;i++) { + tdb_off_t offset; + tdb_len_t length; + + if (tdb->transaction->blocks[i] == NULL) { + continue; + } + + offset = i * tdb->transaction->block_size; + length = tdb->transaction->block_size; + if (i == tdb->transaction->num_blocks-1) { + length = tdb->transaction->last_block_size; + } + + if (offset >= old_map_size) { + continue; + } + if (offset + length > tdb->transaction->old_map_size) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n")); + free(data); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + memcpy(p, &offset, 4); + memcpy(p+4, &length, 4); + if (DOCONV()) { + tdb_convert(p, 8); + } + /* the recovery area contains the old data, not the + new data, so we have to call the original tdb_read + method to get it */ + if (methods->tdb_read(tdb, offset, p + 8, length, 0) != 0) { + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + length; + } + + /* and the tailer */ + tailer = sizeof(*rec) + recovery_max_size; + memcpy(p, &tailer, 4); + CONVERT(p); + + /* write the recovery data to the recovery area */ + if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n")); + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + if (transaction_write_existing(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write secondary recovery data\n")); + free(data); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* as we don't have ordered writes, we have to sync the recovery + data before we update the magic to indicate that the recovery + data is present */ + if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) { + free(data); + return -1; + } + + free(data); + + magic = TDB_RECOVERY_MAGIC; + CONVERT(magic); + + *magic_offset = recovery_offset + offsetof(struct tdb_record, magic); + + if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + if (transaction_write_existing(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write secondary recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* ensure the recovery magic marker is on disk */ + if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) { + return -1; + } + + return 0; +} + +static int _tdb_transaction_prepare_commit(struct tdb_context *tdb) +{ + const struct tdb_methods *methods; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: no transaction\n")); + return -1; + } + + if (tdb->transaction->prepared) { + tdb->ecode = TDB_ERR_EINVAL; + _tdb_transaction_cancel(tdb); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: transaction already prepared\n")); + return -1; + } + + if (tdb->transaction->transaction_error) { + tdb->ecode = TDB_ERR_IO; + _tdb_transaction_cancel(tdb); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: transaction error pending\n")); + return -1; + } + + + if (tdb->transaction->nesting != 0) { + return 0; + } + + /* check for a null transaction */ + if (tdb->transaction->blocks == NULL) { + return 0; + } + + methods = tdb->transaction->io_methods; + + /* if there are any locks pending then the caller has not + nested their locks properly, so fail the transaction */ + if (tdb->num_locks || tdb->global_lock.count) { + tdb->ecode = TDB_ERR_LOCK; + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: locks pending on commit\n")); + _tdb_transaction_cancel(tdb); + return -1; + } + + /* upgrade the main transaction lock region to a write lock */ + if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to upgrade hash locks\n")); + tdb->ecode = TDB_ERR_LOCK; + _tdb_transaction_cancel(tdb); + return -1; + } + + /* get the global lock - this prevents new users attaching to the database + during the commit */ + if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get global lock\n")); + tdb->ecode = TDB_ERR_LOCK; + _tdb_transaction_cancel(tdb); + return -1; + } + + tdb->transaction->global_lock_taken = true; + + if (!(tdb->flags & TDB_NOSYNC)) { + /* write the recovery data to the end of the file */ + if (transaction_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: failed to setup recovery data\n")); + _tdb_transaction_cancel(tdb); + return -1; + } + } + + tdb->transaction->prepared = true; + + /* expand the file to the new size if needed */ + if (tdb->map_size != tdb->transaction->old_map_size) { + if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, + tdb->map_size - + tdb->transaction->old_map_size) == -1) { + tdb->ecode = TDB_ERR_IO; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: expansion failed\n")); + _tdb_transaction_cancel(tdb); + return -1; + } + tdb->map_size = tdb->transaction->old_map_size; + methods->tdb_oob(tdb, tdb->map_size + 1, 1); + } + + /* Keep the global lock until the actual commit */ + + return 0; +} + +/* + prepare to commit the current transaction +*/ +int tdb_transaction_prepare_commit(struct tdb_context *tdb) +{ + tdb_trace(tdb, "tdb_transaction_prepare_commit"); + return _tdb_transaction_prepare_commit(tdb); +} + +/* + commit the current transaction +*/ +int tdb_transaction_commit(struct tdb_context *tdb) +{ + const struct tdb_methods *methods; + int i; + bool need_repack; + + if (tdb->transaction == NULL) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n")); + return -1; + } + + tdb_trace(tdb, "tdb_transaction_commit"); + + if (tdb->transaction->transaction_error) { + tdb->ecode = TDB_ERR_IO; + _tdb_transaction_cancel(tdb); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n")); + return -1; + } + + + if (tdb->transaction->nesting != 0) { + tdb->transaction->nesting--; + return 0; + } + + /* check for a null transaction */ + if (tdb->transaction->blocks == NULL) { + _tdb_transaction_cancel(tdb); + return 0; + } + + if (!tdb->transaction->prepared) { + int ret = _tdb_transaction_prepare_commit(tdb); + if (ret) + return ret; + } + + methods = tdb->transaction->io_methods; + + /* perform all the writes */ + for (i=0;itransaction->num_blocks;i++) { + tdb_off_t offset; + tdb_len_t length; + + if (tdb->transaction->blocks[i] == NULL) { + continue; + } + + offset = i * tdb->transaction->block_size; + length = tdb->transaction->block_size; + if (i == tdb->transaction->num_blocks-1) { + length = tdb->transaction->last_block_size; + } + + if (methods->tdb_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); + + /* we've overwritten part of the data and + possibly expanded the file, so we need to + run the crash recovery code */ + tdb->methods = methods; + tdb_transaction_recover(tdb); + + _tdb_transaction_cancel(tdb); + + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n")); + return -1; + } + SAFE_FREE(tdb->transaction->blocks[i]); + } + + SAFE_FREE(tdb->transaction->blocks); + tdb->transaction->num_blocks = 0; + + /* ensure the new data is on disk */ + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + return -1; + } + + /* + TODO: maybe write to some dummy hdr field, or write to magic + offset without mmap, before the last sync, instead of the + utime() call + */ + + /* on some systems (like Linux 2.6.x) changes via mmap/msync + don't change the mtime of the file, this means the file may + not be backed up (as tdb rounding to block sizes means that + file size changes are quite rare too). The following forces + mtime changes when a transaction completes */ +#ifdef HAVE_UTIME + utime(tdb->name, NULL); +#endif + + need_repack = tdb->transaction->need_repack; + + /* use a transaction cancel to free memory and remove the + transaction locks */ + _tdb_transaction_cancel(tdb); + + if (need_repack) { + return tdb_repack(tdb); + } + + return 0; +} + + +/* + recover from an aborted transaction. Must be called with exclusive + database write access already established (including the global + lock to prevent new processes attaching) +*/ +int tdb_transaction_recover(struct tdb_context *tdb) +{ + tdb_off_t recovery_head, recovery_eof; + unsigned char *data, *p; + uint32_t zero = 0; + struct tdb_record rec; + + /* find the recovery area */ + if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (recovery_head == 0) { + /* we have never allocated a recovery record */ + return 0; + } + + /* read the recovery record */ + if (tdb->methods->tdb_read(tdb, recovery_head, &rec, + sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + if (rec.magic != TDB_RECOVERY_MAGIC) { + /* there is no valid recovery data */ + return 0; + } + + if (tdb->read_only) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n")); + tdb->ecode = TDB_ERR_CORRUPT; + return -1; + } + + recovery_eof = rec.key_len; + + data = (unsigned char *)malloc(rec.data_len); + if (data == NULL) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n")); + tdb->ecode = TDB_ERR_OOM; + return -1; + } + + /* read the full recovery data */ + if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, + rec.data_len, 0) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* recover the file data */ + p = data; + while (p+8 < data + rec.data_len) { + uint32_t ofs, len; + if (DOCONV()) { + tdb_convert(p, 8); + } + memcpy(&ofs, p, 4); + memcpy(&len, p+4, 4); + + if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { + free(data); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); + tdb->ecode = TDB_ERR_IO; + return -1; + } + p += 8 + len; + } + + free(data); + + if (transaction_sync(tdb, 0, tdb->map_size) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* if the recovery area is after the recovered eof then remove it */ + if (recovery_eof <= recovery_head) { + if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + } + + /* remove the recovery magic */ + if (tdb_ofs_write(tdb, recovery_head + offsetof(struct tdb_record, magic), + &zero) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + /* reduce the file size to the old size */ + tdb_munmap(tdb); + if (ftruncate(tdb->fd, recovery_eof) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + tdb->map_size = recovery_eof; + tdb_mmap(tdb); + + if (transaction_sync(tdb, 0, recovery_eof) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n")); + tdb->ecode = TDB_ERR_IO; + return -1; + } + + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n", + recovery_eof)); + + /* all done */ + return 0; +} diff --git a/libatalk/tdb/traverse.c b/libatalk/tdb/traverse.c new file mode 100644 index 0000000..c340dd3 --- /dev/null +++ b/libatalk/tdb/traverse.c @@ -0,0 +1,366 @@ + /* + Unix SMB/CIFS implementation. + + trivial database library + + Copyright (C) Andrew Tridgell 1999-2005 + Copyright (C) Paul `Rusty' Russell 2000 + Copyright (C) Jeremy Allison 2000-2003 + + ** NOTE! The following LGPL license applies to the tdb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + 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 3 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, see . +*/ + +#include "tdb_private.h" + +#define TDB_NEXT_LOCK_ERR ((tdb_off_t)-1) + +/* Uses traverse lock: 0 = finish, TDB_NEXT_LOCK_ERR = error, + other = record offset */ +static tdb_off_t tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock, + struct tdb_record *rec) +{ + int want_next = (tlock->off != 0); + + /* Lock each chain from the start one. */ + for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { + if (!tlock->off && tlock->hash != 0) { + /* this is an optimisation for the common case where + the hash chain is empty, which is particularly + common for the use of tdb with ldb, where large + hashes are used. In that case we spend most of our + time in tdb_brlock(), locking empty hash chains. + + To avoid this, we do an unlocked pre-check to see + if the hash chain is empty before starting to look + inside it. If it is empty then we can avoid that + hash chain. If it isn't empty then we can't believe + the value we get back, as we read it without a + lock, so instead we get the lock and re-fetch the + value below. + + Notice that not doing this optimisation on the + first hash chain is critical. We must guarantee + that we have done at least one fcntl lock at the + start of a search to guarantee that memory is + coherent on SMP systems. If records are added by + others during the search then thats OK, and we + could possibly miss those with this trick, but we + could miss them anyway without this trick, so the + semantics don't change. + + With a non-indexed ldb search this trick gains us a + factor of around 80 in speed on a linux 2.6.x + system (testing using ldbtest). + */ + tdb->methods->next_hash_chain(tdb, &tlock->hash); + if (tlock->hash == tdb->header.hash_size) { + continue; + } + } + + if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1) + return TDB_NEXT_LOCK_ERR; + + /* No previous record? Start at top of chain. */ + if (!tlock->off) { + if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash), + &tlock->off) == -1) + goto fail; + } else { + /* Otherwise unlock the previous record. */ + if (tdb_unlock_record(tdb, tlock->off) != 0) + goto fail; + } + + if (want_next) { + /* We have offset of old record: grab next */ + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + tlock->off = rec->next; + } + + /* Iterate through chain */ + while( tlock->off) { + tdb_off_t current; + if (tdb_rec_read(tdb, tlock->off, rec) == -1) + goto fail; + + /* Detect infinite loops. From "Shlomi Yaakobovich" . */ + if (tlock->off == rec->next) { + tdb->ecode = TDB_ERR_CORRUPT; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n")); + goto fail; + } + + if (!TDB_DEAD(rec)) { + /* Woohoo: we found one! */ + if (tdb_lock_record(tdb, tlock->off) != 0) + goto fail; + return tlock->off; + } + + /* Try to clean dead ones from old traverses */ + current = tlock->off; + tlock->off = rec->next; + if (!(tdb->read_only || tdb->traverse_read) && + tdb_do_delete(tdb, current, rec) != 0) + goto fail; + } + tdb_unlock(tdb, tlock->hash, tlock->lock_rw); + want_next = 0; + } + /* We finished iteration without finding anything */ + tdb->ecode = TDB_SUCCESS; + return 0; + + fail: + tlock->off = 0; + if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n")); + return TDB_NEXT_LOCK_ERR; +} + +/* traverse the entire database - calling fn(tdb, key, data) on each element. + return -1 on error or the record count traversed + if fn is NULL then it is not called + a non-zero return value from fn() indicates that the traversal should stop + */ +static int tdb_traverse_internal(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data, + struct tdb_traverse_lock *tl) +{ + TDB_DATA key, dbuf; + struct tdb_record rec; + int ret = 0, count = 0; + tdb_off_t off; + + /* This was in the initializaton, above, but the IRIX compiler + * did not like it. crh + */ + tl->next = tdb->travlocks.next; + + /* fcntl locks don't stack: beware traverse inside traverse */ + tdb->travlocks.next = tl; + + /* tdb_next_lock places locks on the record returned, and its chain */ + while ((off = tdb_next_lock(tdb, tl, &rec)) != 0) { + if (off == TDB_NEXT_LOCK_ERR) { + ret = -1; + goto out; + } + count++; + /* now read the full record */ + key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), + rec.key_len + rec.data_len); + if (!key.dptr) { + ret = -1; + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) + goto out; + if (tdb_unlock_record(tdb, tl->off) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + goto out; + } + key.dsize = rec.key_len; + dbuf.dptr = key.dptr + rec.key_len; + dbuf.dsize = rec.data_len; + + tdb_trace_1rec_retrec(tdb, "traverse", key, dbuf); + + /* Drop chain lock, call out */ + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { + ret = -1; + SAFE_FREE(key.dptr); + goto out; + } + if (fn && fn(tdb, key, dbuf, private_data)) { + /* They want us to terminate traversal */ + tdb_trace_ret(tdb, "tdb_traverse_end", count); + if (tdb_unlock_record(tdb, tl->off) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; + ret = -1; + } + SAFE_FREE(key.dptr); + goto out; + } + SAFE_FREE(key.dptr); + } + tdb_trace(tdb, "tdb_traverse_end"); +out: + tdb->travlocks.next = tl->next; + if (ret < 0) + return -1; + else + return count; +} + + +/* + a write style traverse - temporarily marks the db read only +*/ +int tdb_traverse_read(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; + int ret; + + /* we need to get a read lock on the transaction lock here to + cope with the lock ordering semantics of solaris10 */ + if (tdb_transaction_lock(tdb, F_RDLCK)) { + return -1; + } + + tdb->traverse_read++; + tdb_trace(tdb, "tdb_traverse_read_start"); + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + tdb->traverse_read--; + + tdb_transaction_unlock(tdb); + + return ret; +} + +/* + a write style traverse - needs to get the transaction lock to + prevent deadlocks + + WARNING: The data buffer given to the callback fn does NOT meet the + alignment restrictions malloc gives you. +*/ +int tdb_traverse(struct tdb_context *tdb, + tdb_traverse_func fn, void *private_data) +{ + struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; + int ret; + + if (tdb->read_only || tdb->traverse_read) { + return tdb_traverse_read(tdb, fn, private_data); + } + + if (tdb_transaction_lock(tdb, F_WRLCK)) { + return -1; + } + + tdb->traverse_write++; + tdb_trace(tdb, "tdb_traverse_start"); + ret = tdb_traverse_internal(tdb, fn, private_data, &tl); + tdb->traverse_write--; + + tdb_transaction_unlock(tdb); + + return ret; +} + + +/* find the first entry in the database and return its key */ +TDB_DATA tdb_firstkey(struct tdb_context *tdb) +{ + TDB_DATA key; + struct tdb_record rec; + tdb_off_t off; + + /* release any old lock */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) + return tdb_null; + tdb->travlocks.off = tdb->travlocks.hash = 0; + tdb->travlocks.lock_rw = F_RDLCK; + + /* Grab first record: locks chain and returned record. */ + off = tdb_next_lock(tdb, &tdb->travlocks, &rec); + if (off == 0 || off == TDB_NEXT_LOCK_ERR) { + tdb_trace_retrec(tdb, "tdb_firstkey", tdb_null); + return tdb_null; + } + /* now read the key */ + key.dsize = rec.key_len; + key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); + + tdb_trace_retrec(tdb, "tdb_firstkey", key); + + /* Unlock the hash chain of the record we just read. */ + if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + return key; +} + +/* find the next entry in the database, returning its key */ +TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) +{ + uint32_t oldhash; + TDB_DATA key = tdb_null; + struct tdb_record rec; + unsigned char *k = NULL; + tdb_off_t off; + + /* Is locked key the old key? If so, traverse will be reliable. */ + if (tdb->travlocks.off) { + if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw)) + return tdb_null; + if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 + || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), + rec.key_len)) + || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { + /* No, it wasn't: unlock it and start from scratch */ + if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) { + tdb_trace_1rec_retrec(tdb, "tdb_nextkey", + oldkey, tdb_null); + SAFE_FREE(k); + return tdb_null; + } + if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) { + SAFE_FREE(k); + return tdb_null; + } + tdb->travlocks.off = 0; + } + + SAFE_FREE(k); + } + + if (!tdb->travlocks.off) { + /* No previous element: do normal find, and lock record */ + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec); + if (!tdb->travlocks.off) { + tdb_trace_1rec_retrec(tdb, "tdb_nextkey", oldkey, tdb_null); + return tdb_null; + } + tdb->travlocks.hash = BUCKET(rec.full_hash); + if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + return tdb_null; + } + } + oldhash = tdb->travlocks.hash; + + /* Grab next record: locks chain and returned record, + unlocks old record */ + off = tdb_next_lock(tdb, &tdb->travlocks, &rec); + if (off != TDB_NEXT_LOCK_ERR && off != 0) { + key.dsize = rec.key_len; + key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), + key.dsize); + /* Unlock the chain of this new record */ + if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + } + /* Unlock the chain of old record */ + if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0) + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + tdb_trace_1rec_retrec(tdb, "tdb_nextkey", oldkey, key); + return key; +} + diff --git a/libatalk/unicode/Makefile.am b/libatalk/unicode/Makefile.am new file mode 100644 index 0000000..abf6f32 --- /dev/null +++ b/libatalk/unicode/Makefile.am @@ -0,0 +1,22 @@ +# Makefile.am for libatalk/util/ + +noinst_LTLIBRARIES = libunicode.la + +AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys @ICONV_CFLAGS@ + +SUBDIRS = charsets + +LIBUNICODE_DEPS = charsets/libcharsets.la + +libunicode_la_SOURCES = \ + util_unistr.c \ + iconv.c \ + charcnv.c \ + utf8.c \ + utf16_case.c + +libunicode_la_LIBADD = $(LIBUNICODE_DEPS) + +noinst_HEADERS = utf16_casetable.h precompose.h + +LIBS=@ICONV_LIBS@ diff --git a/libatalk/unicode/Makefile.in b/libatalk/unicode/Makefile.in new file mode 100644 index 0000000..cbd1c1f --- /dev/null +++ b/libatalk/unicode/Makefile.in @@ -0,0 +1,806 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/util/ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/unicode +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libunicode_la_DEPENDENCIES = $(LIBUNICODE_DEPS) +am_libunicode_la_OBJECTS = util_unistr.lo iconv.lo charcnv.lo utf8.lo \ + utf16_case.lo +libunicode_la_OBJECTS = $(am_libunicode_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libunicode_la_SOURCES) +DIST_SOURCES = $(libunicode_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @ICONV_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libunicode.la +AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys @ICONV_CFLAGS@ +SUBDIRS = charsets +LIBUNICODE_DEPS = charsets/libcharsets.la +libunicode_la_SOURCES = \ + util_unistr.c \ + iconv.c \ + charcnv.c \ + utf8.c \ + utf16_case.c + +libunicode_la_LIBADD = $(LIBUNICODE_DEPS) +noinst_HEADERS = utf16_casetable.h precompose.h +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/unicode/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/unicode/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libunicode.la: $(libunicode_la_OBJECTS) $(libunicode_la_DEPENDENCIES) $(EXTRA_libunicode_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libunicode_la_OBJECTS) $(libunicode_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/charcnv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iconv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf16_case.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util_unistr.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist cscopelist-recursive ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am + + +# 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/libatalk/unicode/charcnv.c b/libatalk/unicode/charcnv.c new file mode 100644 index 0000000..7242b57 --- /dev/null +++ b/libatalk/unicode/charcnv.c @@ -0,0 +1,1046 @@ +/* + Unix SMB/CIFS implementation. + Character set conversion Extensions + Copyright (C) Igor Vergeichik 2001 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Simo Sorce 2001 + Copyright (C) Martin Pool 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_USABLE_ICONV +#include +#endif +#include + +#include +#include +#include +#include +#include + + +/** + * @file + * + * @brief Character-set conversion routines built on our iconv. + * + * @note Samba's internal character set (at least in the 3.0 series) + * is always the same as the one for the Unix filesystem. It is + * not necessarily UTF-8 and may be different on machines that + * need i18n filenames to be compatible with Unix software. It does + * have to be a superset of ASCII. All multibyte sequences must start + * with a byte with the high bit set. + * + * @sa lib/iconv.c + */ + + +#define MAX_CHARSETS 20 + +#define CHECK_FLAGS(a,b) (((a)!=NULL) ? (*(a) & (b)) : 0 ) + +static atalk_iconv_t conv_handles[MAX_CHARSETS][MAX_CHARSETS]; +static char* charset_names[MAX_CHARSETS]; +static struct charset_functions* charsets[MAX_CHARSETS]; +static char hexdig[] = "0123456789abcdef"; +#define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' ) + + +/** + * Return the name of a charset to give to iconv(). + **/ +static const char *charset_name(charset_t ch) +{ + const char *ret = NULL; + + if (ch == CH_UCS2) ret = "UCS-2"; + else if (ch == CH_UTF8) ret = "UTF8"; + else if (ch == CH_UTF8_MAC) ret = "UTF8-MAC"; + else ret = charset_names[ch]; + return ret; +} + +int set_charset_name(charset_t ch, const char *name) +{ + if (ch >= NUM_CHARSETS) + return -1; + charset_names[ch] = strdup(name); + return 0; +} + +void free_charset_names(void) +{ + for (int ch = 0; ch < MAX_CHARSETS; ch++) { + if (charset_names[ch]) { + free(charset_names[ch]); + charset_names[ch] = NULL; + } + } +} + +static struct charset_functions* get_charset_functions (charset_t ch) +{ + if (charsets[ch] != NULL) + return charsets[ch]; + + charsets[ch] = find_charset_functions(charset_name(ch)); + + return charsets[ch]; +} + + +static void lazy_initialize_conv(void) +{ + static int initialized = 0; + + if (!initialized) { + initialized = 1; + init_iconv(); + } +} + +charset_t add_charset(const char* name) +{ + static charset_t max_charset_t = NUM_CHARSETS-1; + charset_t cur_charset_t = max_charset_t+1; + unsigned int c1; + + lazy_initialize_conv(); + + for (c1=0; c1<=max_charset_t;c1++) { + if ( strcasecmp(name, charset_name(c1)) == 0) + return (c1); + } + + if ( cur_charset_t >= MAX_CHARSETS ) { + LOG (log_debug, logtype_default, "Adding charset %s failed, too many charsets (max. %u allowed)", + name, MAX_CHARSETS); + return (charset_t) -1; + } + + /* First try to setup the required conversions */ + + conv_handles[cur_charset_t][CH_UCS2] = atalk_iconv_open( charset_name(CH_UCS2), name); + if (conv_handles[cur_charset_t][CH_UCS2] == (atalk_iconv_t)-1) { + LOG(log_error, logtype_default, "Required conversion from %s to %s not supported", + name, charset_name(CH_UCS2)); + conv_handles[cur_charset_t][CH_UCS2] = NULL; + return (charset_t) -1; + } + + conv_handles[CH_UCS2][cur_charset_t] = atalk_iconv_open( name, charset_name(CH_UCS2)); + if (conv_handles[CH_UCS2][cur_charset_t] == (atalk_iconv_t)-1) { + LOG(log_error, logtype_default, "Required conversion from %s to %s not supported", + charset_name(CH_UCS2), name); + conv_handles[CH_UCS2][cur_charset_t] = NULL; + return (charset_t) -1; + } + + /* register the new charset_t name */ + charset_names[cur_charset_t] = strdup(name); + + charsets[cur_charset_t] = get_charset_functions (cur_charset_t); + max_charset_t++; + +#ifdef DEBUG + LOG(log_debug9, logtype_default, "Added charset %s with handle %u", name, cur_charset_t); +#endif + return (cur_charset_t); +} + +/** + * Initialize iconv conversion descriptors. + * + * This is called the first time it is needed, and also called again + * every time the configuration is reloaded, because the charset or + * codepage might have changed. + **/ +void init_iconv(void) +{ + int c1; + + for (c1=0;c1= 2) { + buf[len] = 0; + buf[len+1] = 0; + + } + else if ( to != CH_UCS2 && bytesleft > 0 ) + buf[len] = 0; + else { + errno = E2BIG; + return (size_t)(-1); + } + + return len; +} + + +/** + * Convert string from one encoding to another, making error checking etc + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string + * @returns the number of bytes occupied in the destination + **/ +static size_t convert_string_internal(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen) +{ + size_t i_len, o_len; + size_t retval; + const char* inbuf = (const char*)src; + char* outbuf = (char*)dest; + char* o_save = outbuf; + atalk_iconv_t descriptor; + + /* Fixed based on Samba 3.0.6 */ + if (srclen == (size_t)-1) { + if (from == CH_UCS2) { + srclen = (strlen_w((const ucs2_t *)src)) * 2; + } else { + srclen = strlen((const char *)src); + } + } + + + lazy_initialize_conv(); + + descriptor = conv_handles[from][to]; + + if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) { + return (size_t) -1; + } + + i_len=srclen; + o_len=destlen; + retval = atalk_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); + if(retval==(size_t)-1) { + const char *reason="unknown error"; + switch(errno) { + case EINVAL: + reason="Incomplete multibyte sequence"; + break; + case E2BIG: + reason="No more room"; + break; + case EILSEQ: + reason="Illegal multibyte sequence"; + break; + } + LOG(log_debug, logtype_default,"Conversion error: %s",reason); + return (size_t)-1; + } + + /* Terminate the string */ + return add_null( to, o_save, o_len, destlen -o_len); +} + + +size_t convert_string(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen) +{ + size_t i_len, o_len; + ucs2_t *u; + ucs2_t buffer[MAXPATHLEN]; + ucs2_t buffer2[MAXPATHLEN]; + + /* convert from_set to UCS2 */ + if ((size_t)-1 == ( o_len = convert_string_internal( from, CH_UCS2, src, srclen, + (char*) buffer, sizeof(buffer))) ) { + LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from)); + return (size_t) -1; + } + + /* Do pre/decomposition */ + i_len = sizeof(buffer2); + u = buffer2; + if (charsets[to] && (charsets[to]->flags & CHARSET_DECOMPOSED) ) { + if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) ) + return (size_t)-1; + } + else if (!charsets[from] || (charsets[from]->flags & CHARSET_DECOMPOSED)) { + if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) ) + return (size_t)-1; + } + else { + u = buffer; + i_len = o_len; + } + /* Convert UCS2 to to_set */ + if ((size_t)(-1) == ( o_len = convert_string_internal( CH_UCS2, to, (char*) u, i_len, dest, destlen)) ) { + LOG(log_error, logtype_default, "Conversion failed (CH_UCS2 to %s):%s", charset_name(to), strerror(errno)); + return (size_t) -1; + } + + return o_len; +} + + + +/** + * Convert between character sets, allocating a new buffer for the result. + * + * @param srclen length of source buffer. + * @param dest always set at least to NULL + * @note -1 is not accepted for srclen. + * + * @returns Size in bytes of the converted string; or -1 in case of error. + **/ + +static size_t convert_string_allocate_internal(charset_t from, charset_t to, + void const *src, size_t srclen, char **dest) +{ + size_t i_len, o_len, destlen; + size_t retval; + const char *inbuf = (const char *)src; + char *outbuf = NULL, *ob = NULL; + atalk_iconv_t descriptor; + + *dest = NULL; + + if (src == NULL || srclen == (size_t)-1) + return (size_t)-1; + + lazy_initialize_conv(); + + descriptor = conv_handles[from][to]; + + if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) { + /* conversion not supported, return -1*/ + LOG(log_debug, logtype_default, "convert_string_allocate: conversion not supported!"); + return -1; + } + + destlen = MAX(srclen, 512); +convert: + destlen = destlen * 2; + outbuf = (char *)realloc(ob, destlen); + if (!outbuf) { + LOG(log_debug, logtype_default,"convert_string_allocate: realloc failed!"); + SAFE_FREE(ob); + return (size_t)-1; + } else { + ob = outbuf; + } + inbuf = src; /* this restarts the whole conversion if buffer needed to be increased */ + i_len = srclen; + o_len = destlen; + retval = atalk_iconv(descriptor, + &inbuf, &i_len, + &outbuf, &o_len); + if(retval == (size_t)-1) { + const char *reason="unknown error"; + switch(errno) { + case EINVAL: + reason="Incomplete multibyte sequence"; + break; + case E2BIG: + goto convert; + case EILSEQ: + reason="Illegal multibyte sequence"; + break; + } + LOG(log_debug, logtype_default,"Conversion error: %s(%s)",reason,inbuf); + SAFE_FREE(ob); + return (size_t)-1; + } + + + destlen = destlen - o_len; + + /* Terminate the string */ + if (to == CH_UCS2 && o_len >= 2) { + ob[destlen] = 0; + ob[destlen+1] = 0; + *dest = (char *)realloc(ob,destlen+2); + } + else if ( to != CH_UCS2 && o_len > 0 ) { + ob[destlen] = 0; + *dest = (char *)realloc(ob,destlen+1); + } + else { + goto convert; /* realloc */ + } + + if (destlen && !*dest) { + LOG(log_debug, logtype_default, "convert_string_allocate: out of memory!"); + SAFE_FREE(ob); + return (size_t)-1; + } + + return destlen; +} + + +size_t convert_string_allocate(charset_t from, charset_t to, + void const *src, size_t srclen, + char ** dest) +{ + size_t i_len, o_len; + ucs2_t *u; + ucs2_t buffer[MAXPATHLEN]; + ucs2_t buffer2[MAXPATHLEN]; + + *dest = NULL; + + /* convert from_set to UCS2 */ + if ((size_t)(-1) == ( o_len = convert_string_internal( from, CH_UCS2, src, srclen, + buffer, sizeof(buffer))) ) { + LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from)); + return (size_t) -1; + } + + /* Do pre/decomposition */ + i_len = sizeof(buffer2); + u = buffer2; + if (charsets[to] && (charsets[to]->flags & CHARSET_DECOMPOSED) ) { + if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) ) + return (size_t)-1; + } + else if ( !charsets[from] || (charsets[from]->flags & CHARSET_DECOMPOSED) ) { + if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) ) + return (size_t)-1; + } + else { + u = buffer; + i_len = o_len; + } + + /* Convert UCS2 to to_set */ + if ((size_t)-1 == ( o_len = convert_string_allocate_internal( CH_UCS2, to, (char*)u, i_len, dest)) ) + LOG(log_error, logtype_default, "Conversion failed (CH_UCS2 to %s):%s", charset_name(to), strerror(errno)); + + return o_len; + +} + +size_t charset_strupper(charset_t ch, const char *src, size_t srclen, char *dest, size_t destlen) +{ + size_t size; + char *buffer; + + size = convert_string_allocate_internal(ch, CH_UCS2, src, srclen, + (char**) &buffer); + if (size == (size_t)-1) { + SAFE_FREE(buffer); + return size; + } + if (!strupper_w((ucs2_t *)buffer) && (dest == src)) { + free(buffer); + return srclen; + } + + size = convert_string_internal(CH_UCS2, ch, buffer, size, dest, destlen); + free(buffer); + return size; +} + +size_t charset_strlower(charset_t ch, const char *src, size_t srclen, char *dest, size_t destlen) +{ + size_t size; + char *buffer; + + size = convert_string_allocate_internal(ch, CH_UCS2, src, srclen, + (char **) &buffer); + if (size == (size_t)-1) { + SAFE_FREE(buffer); + return size; + } + if (!strlower_w((ucs2_t *)buffer) && (dest == src)) { + free(buffer); + return srclen; + } + + size = convert_string_internal(CH_UCS2, ch, buffer, size, dest, destlen); + free(buffer); + return size; +} + + +size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) +{ + return charset_strupper( CH_UNIX, src, srclen, dest, destlen); +} + +size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) +{ + return charset_strlower( CH_UNIX, src, srclen, dest, destlen); +} + +size_t utf8_strupper(const char *src, size_t srclen, char *dest, size_t destlen) +{ + return charset_strupper( CH_UTF8, src, srclen, dest, destlen); +} + +size_t utf8_strlower(const char *src, size_t srclen, char *dest, size_t destlen) +{ + return charset_strlower( CH_UTF8, src, srclen, dest, destlen); +} + +/** + * Copy a string from a charset_t char* src to a UCS2 destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ + +size_t charset_to_ucs2_allocate(charset_t ch, ucs2_t **dest, const char *src) +{ + size_t src_len = strlen(src); + + *dest = NULL; + return convert_string_allocate(ch, CH_UCS2, src, src_len, (char**) dest); +} + +/** ----------------------------------- + * Copy a string from a charset_t char* src to a UTF-8 destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +size_t charset_to_utf8_allocate(charset_t ch, char **dest, const char *src) +{ + size_t src_len = strlen(src); + + *dest = NULL; + return convert_string_allocate(ch, CH_UTF8, src, src_len, dest); +} + +/** ----------------------------------- + * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +size_t ucs2_to_charset(charset_t ch, const ucs2_t *src, char *dest, size_t destlen) +{ + size_t src_len = (strlen_w(src)) * sizeof(ucs2_t); + return convert_string(CH_UCS2, ch, src, src_len, dest, destlen); +} + +/* --------------------------------- */ +size_t ucs2_to_charset_allocate(charset_t ch, char **dest, const ucs2_t *src) +{ + size_t src_len = (strlen_w(src)) * sizeof(ucs2_t); + *dest = NULL; + return convert_string_allocate(CH_UCS2, ch, src, src_len, dest); +} + +/** --------------------------------- + * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +size_t utf8_to_charset_allocate(charset_t ch, char **dest, const char *src) +{ + size_t src_len = strlen(src); + *dest = NULL; + return convert_string_allocate(CH_UTF8, ch, src, src_len, dest); +} + +size_t charset_precompose ( charset_t ch, char * src, size_t inlen, char * dst, size_t outlen) +{ + char *buffer; + ucs2_t u[MAXPATHLEN]; + size_t len; + size_t ilen; + + if ((size_t)(-1) == (len = convert_string_allocate_internal(ch, CH_UCS2, src, inlen, &buffer)) ) + return len; + + ilen=sizeof(u); + + if ( (size_t)-1 == (ilen = precompose_w((ucs2_t *)buffer, len, u, &ilen)) ) { + free (buffer); + return (size_t)(-1); + } + + if ((size_t)(-1) == (len = convert_string_internal( CH_UCS2, ch, (char*)u, ilen, dst, outlen)) ) { + free (buffer); + return (size_t)(-1); + } + + free(buffer); + return (len); +} + +size_t charset_decompose ( charset_t ch, char * src, size_t inlen, char * dst, size_t outlen) +{ + char *buffer; + ucs2_t u[MAXPATHLEN]; + size_t len; + size_t ilen; + + if ((size_t)(-1) == (len = convert_string_allocate_internal(ch, CH_UCS2, src, inlen, &buffer)) ) + return len; + + ilen=sizeof(u); + + if ( (size_t)-1 == (ilen = decompose_w((ucs2_t *)buffer, len, u, &ilen)) ) { + free (buffer); + return (size_t)(-1); + } + + if ((size_t)(-1) == (len = convert_string_internal( CH_UCS2, ch, (char*)u, ilen, dst, outlen)) ) { + free (buffer); + return (size_t)(-1); + } + + free(buffer); + return (len); +} + +size_t utf8_precompose ( char * src, size_t inlen, char * dst, size_t outlen) +{ + return charset_precompose ( CH_UTF8, src, inlen, dst, outlen); +} + +size_t utf8_decompose ( char * src, size_t inlen, char * dst, size_t outlen) +{ + return charset_decompose ( CH_UTF8, src, inlen, dst, outlen); +} + +#if 0 +static char debugbuf[ MAXPATHLEN +1 ]; +char * debug_out ( char * seq, size_t len) +{ + size_t i = 0; + unsigned char *p; + char *q; + + p = (unsigned char*) seq; + q = debugbuf; + + for ( i = 0; i<=(len-1); i++) + { + sprintf(q, "%2.2x.", *p); + q += 3; + p++; + } + *q=0; + q = debugbuf; + return q; +} +#endif + +/* + * Convert from MB to UCS2 charset + * Flags: + * CONV_UNESCAPEHEX: ':XX' will be converted to an UCS2 character + * CONV_IGNORE: return the first convertable characters. + * CONV_FORCE: force convertion + * FIXME: + * This will *not* work if the destination charset is not multibyte, i.e. UCS2->UCS2 will fail + * The (un)escape scheme is not compatible to the old cap style escape. This is bad, we need it + * for e.g. HFS cdroms. + */ + +static size_t pull_charset_flags (charset_t from_set, charset_t to_set, charset_t cap_set, const char *src, size_t srclen, char* dest, size_t destlen, uint16_t *flags) +{ + const uint16_t option = (flags ? *flags : 0); + size_t i_len, o_len; + size_t j = 0; + const char* inbuf = (const char*)src; + char* outbuf = dest; + atalk_iconv_t descriptor; + atalk_iconv_t descriptor_cap; + char escch; /* 150210: uninitialized OK, depends on j */ + + if (srclen == (size_t)-1) + srclen = strlen(src) + 1; + + descriptor = conv_handles[from_set][CH_UCS2]; + descriptor_cap = conv_handles[cap_set][CH_UCS2]; + + if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) { + errno = EINVAL; + return (size_t)-1; + } + + i_len=srclen; + o_len=destlen; + + if ((option & CONV_ESCAPEDOTS) && i_len >= 2 && inbuf[0] == '.') { + if (o_len < 6) { + errno = E2BIG; + goto end; + } + ucs2_t ucs2 = ':'; + memcpy(outbuf, &ucs2, sizeof(ucs2_t)); + ucs2 = '2'; + memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t)); + ucs2 = 'e'; + memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t)); + outbuf += 6; + o_len -= 6; + inbuf++; + i_len--; + *flags |= CONV_REQESCAPE; + } + + while (i_len > 0) { + for (j = 0; j < i_len; ++j) + if (inbuf[j] == ':' || inbuf[j] == '/') { + escch = inbuf[j]; + break; + } + j = i_len - j; + i_len -= j; + + if (i_len > 0 && + atalk_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len) == (size_t)-1) { + if (errno == EILSEQ || errno == EINVAL) { + errno = EILSEQ; + if ((option & CONV_IGNORE)) { + *flags |= CONV_REQMANGLE; + return destlen - o_len; + } + if ((option & CONV__EILSEQ)) { + if (o_len < 2) { + errno = E2BIG; + goto end; + } + *((ucs2_t *)outbuf) = (ucs2_t) IGNORE_CHAR; /**inbuf */ + inbuf++; + i_len--; + outbuf += 2; + o_len -= 2; + /* FIXME reset stat ? */ + continue; + } + } + goto end; + } + + if (j) { + /* we have a ':' or '/' */ + i_len = j, j = 0; + + if (escch == ':') { + if ((option & CONV_UNESCAPEHEX)) { + /* treat it as a CAP hex encoded char */ + char h[MAXPATHLEN]; + size_t hlen = 0; + + while (i_len >= 3 && inbuf[0] == ':' && + isxdigit(inbuf[1]) && isxdigit(inbuf[2])) { + h[hlen++] = (hextoint(inbuf[1]) << 4) | hextoint(inbuf[2]); + inbuf += 3; + i_len -= 3; + } + if (hlen) { + const char *h_buf = h; + if (atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len) == (size_t)-1) { + i_len += hlen * 3; + inbuf -= hlen * 3; + if (errno == EILSEQ && (option & CONV_IGNORE)) { + *flags |= CONV_REQMANGLE; + return destlen - o_len; + } + goto end; + } + } else { + /* We have an invalid :xx sequence */ + errno = EILSEQ; + if ((option & CONV_IGNORE)) { + *flags |= CONV_REQMANGLE; + return destlen - o_len; + } + goto end; + } + } else if (option & CONV_ESCAPEHEX) { + if (o_len < 6) { + errno = E2BIG; + goto end; + } + ucs2_t ucs2 = ':'; + memcpy(outbuf, &ucs2, sizeof(ucs2_t)); + ucs2 = '3'; + memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t)); + ucs2 = 'a'; + memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t)); + outbuf += 6; + o_len -= 6; + inbuf++; + i_len--; + } else if (to_set == CH_UTF8_MAC || to_set == CH_MAC) { + /* convert to a '/' */ + ucs2_t slash = 0x002f; + memcpy(outbuf, &slash, sizeof(ucs2_t)); + outbuf += 2; + o_len -= 2; + inbuf++; + i_len--; + } else { + /* keep as ':' */ + ucs2_t ucs2 = 0x003a; + memcpy(outbuf, &ucs2, sizeof(ucs2_t)); + outbuf += 2; + o_len -= 2; + inbuf++; + i_len--; + } + } else { + /* '/' */ + if (option & CONV_ESCAPEHEX) { + if (o_len < 6) { + errno = E2BIG; + goto end; + } + ucs2_t ucs2 = ':'; + memcpy(outbuf, &ucs2, sizeof(ucs2_t)); + ucs2 = '2'; + memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t)); + ucs2 = 'f'; + memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t)); + outbuf += 6; + o_len -= 6; + inbuf++; + i_len--; + } else if ((from_set == CH_UTF8_MAC || from_set == CH_MAC) + && (to_set != CH_UTF8_MAC || to_set != CH_MAC)) { + /* convert to ':' */ + ucs2_t ucs2 = 0x003a; + memcpy(outbuf, &ucs2, sizeof(ucs2_t)); + outbuf += 2; + o_len -= 2; + inbuf++; + i_len--; + } else { + /* keep as '/' */ + ucs2_t ucs2 = 0x002f; + memcpy(outbuf, &ucs2, sizeof(ucs2_t)); + outbuf += 2; + o_len -= 2; + inbuf++; + i_len--; + } + } + } + } +end: + return (i_len + j == 0 || (option & CONV_FORCE)) ? destlen - o_len : (size_t)-1; +} + +/* + * Convert from UCS2 to MB charset + * Flags: + * CONV_ESCAPEDOTS: escape leading dots + * CONV_ESCAPEHEX: unconvertable characters and '/' will be escaped to :XX + * CONV_IGNORE: return the first convertable characters. + * CONV__EILSEQ: unconvertable characters will be replaced with '_' + * CONV_FORCE: force convertion + * FIXME: + * CONV_IGNORE and CONV_ESCAPEHEX can't work together. Should we check this ? + * This will *not* work if the destination charset is not multibyte, i.e. UCS2->UCS2 will fail + * The escape scheme is not compatible to the old cap style escape. This is bad, we need it + * for e.g. HFS cdroms. + */ + + +static size_t push_charset_flags (charset_t to_set, charset_t cap_set, char* src, size_t srclen, char* dest, size_t destlen, uint16_t *flags) +{ + const uint16_t option = (flags ? *flags : 0); + size_t i_len, o_len, i; + size_t j = 0; + const char* inbuf = (const char*)src; + char* outbuf = (char*)dest; + atalk_iconv_t descriptor; + atalk_iconv_t descriptor_cap; + + descriptor = conv_handles[CH_UCS2][to_set]; + descriptor_cap = conv_handles[CH_UCS2][cap_set]; + + if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) { + errno = EINVAL; + return (size_t) -1; + } + + i_len=srclen; + o_len=destlen; + + while (i_len >= 2) { + while (i_len > 0 && + atalk_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len) == (size_t)-1) { + if (errno == EILSEQ) { + if ((option & CONV_IGNORE)) { + *flags |= CONV_REQMANGLE; + return destlen - o_len; + } + if ((option & CONV_ESCAPEHEX)) { + const size_t bufsiz = o_len / 3 + 1; + char *buf = malloc(bufsiz); + size_t buflen; + + if (!buf) + goto end; + i = i_len; + for (buflen = 1; buflen <= bufsiz; ++buflen) { + char *b = buf; + size_t o = buflen; + if (atalk_iconv(descriptor_cap, &inbuf, &i, &b, &o) != (size_t)-1) { + buflen -= o; + break; + } else if (errno != E2BIG) { + SAFE_FREE(buf); + goto end; + } else if (o < buflen) { + buflen -= o; + break; + } + } + if (o_len < buflen * 3) { + SAFE_FREE(buf); + errno = E2BIG; + goto end; + } + o_len -= buflen * 3; + i_len = i; + for (i = 0; i < buflen; ++i) { + *outbuf++ = ':'; + *outbuf++ = hexdig[(buf[i] >> 4) & 0x0f]; + *outbuf++ = hexdig[buf[i] & 0x0f]; + } + SAFE_FREE(buf); + *flags |= CONV_REQESCAPE; + continue; + } + } + goto end; + } + } /* while (i_len >= 2) */ + + if (i_len > 0) errno = EINVAL; +end: + return (i_len + j == 0 || (option & CONV_FORCE)) ? destlen - o_len : (size_t)-1; +} + +/* + * FIXME the size is a mess we really need a malloc/free logic + *`dest size must be dest_len +2 + */ +size_t convert_charset ( charset_t from_set, charset_t to_set, charset_t cap_charset, const char *src, size_t src_len, char *dest, size_t dest_len, uint16_t *flags) +{ + size_t i_len, o_len; + ucs2_t *u; + ucs2_t buffer[MAXPATHLEN +2]; + ucs2_t buffer2[MAXPATHLEN +2]; + + lazy_initialize_conv(); + + /* convert from_set to UCS2 */ + if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, to_set, cap_charset, src, src_len, + (char *) buffer, sizeof(buffer) -2, flags)) ) { + LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from_set)); + return (size_t) -1; + } + + if ( o_len == 0) + return o_len; + + /* Do pre/decomposition */ + i_len = sizeof(buffer2) -2; + u = buffer2; + if (CHECK_FLAGS(flags, CONV_DECOMPOSE) || (charsets[to_set] && (charsets[to_set]->flags & CHARSET_DECOMPOSED)) ) { + if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) ) + return (size_t)(-1); + } + else if (CHECK_FLAGS(flags, CONV_PRECOMPOSE) || !charsets[from_set] || (charsets[from_set]->flags & CHARSET_DECOMPOSED)) { + if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) ) + return (size_t)(-1); + } + else { + u = buffer; + i_len = o_len; + } + /* null terminate */ + u[i_len] = 0; + u[i_len +1] = 0; + + /* Do case conversions */ + if (CHECK_FLAGS(flags, CONV_TOUPPER)) { + strupper_w(u); + } + else if (CHECK_FLAGS(flags, CONV_TOLOWER)) { + strlower_w(u); + } + + /* Convert UCS2 to to_set */ + if ((size_t)(-1) == ( o_len = push_charset_flags( to_set, cap_charset, (char *)u, i_len, dest, dest_len, flags )) ) { + LOG(log_error, logtype_default, + "Conversion failed (CH_UCS2 to %s):%s", charset_name(to_set), strerror(errno)); + return (size_t) -1; + } + /* null terminate */ + dest[o_len] = 0; + dest[o_len +1] = 0; + + return o_len; +} diff --git a/libatalk/unicode/charsets/Makefile.am b/libatalk/unicode/charsets/Makefile.am new file mode 100644 index 0000000..6114720 --- /dev/null +++ b/libatalk/unicode/charsets/Makefile.am @@ -0,0 +1,34 @@ +# Makefile.am for libatalk/unicode/charsets + +noinst_LTLIBRARIES = libcharsets.la + +AM_CFLAGS = -I$(top_srcdir)/sys @CFLAGS@ @ICONV_CFLAGS@ +LIBS = + +libcharsets_la_SOURCES = \ + mac_roman.c \ + mac_greek.c \ + mac_hebrew.c \ + mac_centraleurope.c \ + mac_turkish.c \ + mac_cyrillic.c \ + mac_japanese.c \ + mac_chinese_trad.c \ + mac_chinese_simp.c \ + mac_korean.c \ + generic_cjk.c \ + generic_mb.c + +noinst_HEADERS = \ + mac_roman.h \ + mac_greek.h \ + mac_centraleurope.h \ + mac_hebrew.h \ + mac_turkish.h \ + mac_cyrillic.h \ + mac_japanese.h \ + mac_chinese_trad.h \ + mac_chinese_simp.h \ + mac_korean.h \ + generic_cjk.h \ + generic_mb.h diff --git a/libatalk/unicode/charsets/Makefile.in b/libatalk/unicode/charsets/Makefile.in new file mode 100644 index 0000000..3a22c9e --- /dev/null +++ b/libatalk/unicode/charsets/Makefile.in @@ -0,0 +1,705 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/unicode/charsets + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = libatalk/unicode/charsets +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcharsets_la_LIBADD = +am_libcharsets_la_OBJECTS = mac_roman.lo mac_greek.lo mac_hebrew.lo \ + mac_centraleurope.lo mac_turkish.lo mac_cyrillic.lo \ + mac_japanese.lo mac_chinese_trad.lo mac_chinese_simp.lo \ + mac_korean.lo generic_cjk.lo generic_mb.lo +libcharsets_la_OBJECTS = $(am_libcharsets_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcharsets_la_SOURCES) +DIST_SOURCES = $(libcharsets_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libcharsets.la +AM_CFLAGS = -I$(top_srcdir)/sys @CFLAGS@ @ICONV_CFLAGS@ +libcharsets_la_SOURCES = \ + mac_roman.c \ + mac_greek.c \ + mac_hebrew.c \ + mac_centraleurope.c \ + mac_turkish.c \ + mac_cyrillic.c \ + mac_japanese.c \ + mac_chinese_trad.c \ + mac_chinese_simp.c \ + mac_korean.c \ + generic_cjk.c \ + generic_mb.c + +noinst_HEADERS = \ + mac_roman.h \ + mac_greek.h \ + mac_centraleurope.h \ + mac_hebrew.h \ + mac_turkish.h \ + mac_cyrillic.h \ + mac_japanese.h \ + mac_chinese_trad.h \ + mac_chinese_simp.h \ + mac_korean.h \ + generic_cjk.h \ + generic_mb.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/unicode/charsets/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/unicode/charsets/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libcharsets.la: $(libcharsets_la_OBJECTS) $(libcharsets_la_DEPENDENCIES) $(EXTRA_libcharsets_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libcharsets_la_OBJECTS) $(libcharsets_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic_cjk.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic_mb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_centraleurope.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_chinese_simp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_chinese_trad.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_cyrillic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_greek.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_hebrew.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_japanese.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_korean.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_roman.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac_turkish.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/unicode/charsets/generic_cjk.c b/libatalk/unicode/charsets/generic_cjk.c new file mode 100644 index 0000000..461af34 --- /dev/null +++ b/libatalk/unicode/charsets/generic_cjk.c @@ -0,0 +1,215 @@ +/* + * generic_cjk + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#if HAVE_USABLE_ICONV + +#include "generic_cjk.h" +#include + +static size_t cjk_iconv(void *cd, char **inbuf, char *end, + char **outbuf, size_t *outbytesleft) +{ + size_t n = end - *inbuf; + if (iconv(cd, (ICONV_CONST char**)inbuf, &n, outbuf, outbytesleft) == (size_t)-1) { + iconv(cd, NULL, NULL, NULL, NULL); + } + return n; +} + +size_t cjk_generic_push(size_t (*char_func)(uint8_t*, const ucs2_t*, size_t*), + void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + char *in = *inbuf; + + while (*inbytesleft >= sizeof(ucs2_t) && *outbytesleft > 0) { + uint8_t buf[CJK_PUSH_BUFFER]; + size_t size = *inbytesleft / sizeof(ucs2_t); + size_t n = (char_func)(buf, (const ucs2_t*)in, &size); + if (n == 0) { + in += size * sizeof(ucs2_t); + *inbytesleft -= size * sizeof(ucs2_t); + continue; + } + if (in != *inbuf) { + int err = errno; + + *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft); + if (in != *inbuf) return -1; + errno = err; + } + if (n == (size_t)-1) return -1; + if (*outbytesleft < n) break; + memcpy(*outbuf, buf, n); + *outbuf += n; + *outbytesleft -= n; + in += size * sizeof(ucs2_t); + *inbytesleft -= size * sizeof(ucs2_t); + *inbuf = in; + } + if (in != *inbuf) { + *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft); + if (in != *inbuf) return -1; + } + if (*inbytesleft > 0) { + errno = (*inbytesleft < sizeof(ucs2_t) ? EINVAL : E2BIG); + return -1; + } + return 0; +} + +size_t cjk_generic_pull(size_t (*char_func)(ucs2_t*, const uint8_t*, size_t*), + void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + char *in = *inbuf; + + while (*inbytesleft > 0 && *outbytesleft >= sizeof(ucs2_t)) { + ucs2_t buf[CJK_PULL_BUFFER]; + size_t size = *inbytesleft; + size_t n = (char_func)(buf, (const uint8_t*)in, &size); + if (n == 0) { + in += size; + *inbytesleft -= size; + continue; + } + if (in != *inbuf) { + int err = errno; + + *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft); + if (in != *inbuf) return -1; + errno = err; + } + if (n == (size_t)-1) return -1; + if (*outbytesleft < n * sizeof(ucs2_t)) break; + memcpy(*outbuf, buf, n * sizeof(ucs2_t)); + *outbuf += n * sizeof(ucs2_t); + *outbytesleft -= n * sizeof(ucs2_t); + in += size; + *inbytesleft -= size; + *inbuf = in; + } + if (in != *inbuf) { + *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft); + if (in != *inbuf) return -1; + } + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + return 0; +} + +size_t cjk_char_push(uint16_t c, uint8_t *out) +{ + if (!c) return 0; + if (c == (uint16_t)-1) { + errno = EILSEQ; + return (size_t)-1; + } + if (c <= 0xff) { + out[0] = (uint8_t)c; + return 1; + } + out[0] = (uint8_t)(c >> 8); + out[1] = (uint8_t)c; + return 2; +} + +size_t cjk_char_pull(ucs2_t wc, ucs2_t* out, const uint32_t* compose) +{ + if (!wc) return 0; + if ((wc & 0xf000) == 0xe000) { + ucs2_t buf[CJK_PULL_BUFFER]; + size_t i = sizeof(buf) / sizeof(*buf) - 1; + do { + uint32_t v = compose[wc & 0xfff]; + buf[i] = (ucs2_t)v; + wc = (ucs2_t)(v >> 16); + } while (--i && (wc & 0xf000) == 0xe000); + buf[i] = wc; + memcpy(out, buf + i, sizeof(buf) - sizeof(*buf) * i); + return sizeof(buf) / sizeof(*buf) - i; + } + *out = wc; + return 1; +} + +uint16_t cjk_lookup(uint16_t c, const cjk_index_t *index, const uint16_t *charset) +{ + while (index->summary && c >= index->range[0]) { + if (c <= index->range[1]) { + const uint16_t* summary = index->summary[(c - index->range[0]) >> 4]; + uint16_t used = 1 << (c & 15); + + if (summary[0] & used) { + used = summary[0] & (used - 1); + charset += summary[1]; + while (used) used &= used - 1, ++charset; + return *charset; + } + return 0; + } + ++index; + } + return 0; +} + +ucs2_t cjk_compose(ucs2_t base, ucs2_t comb, const uint32_t* table, size_t size) +{ + uint32_t v = ((uint32_t)base << 16) | comb; + size_t low = 0; + while (size > low) { + size_t n = (low + size) / 2; + if (table[n] == v) return 0xe000 + n; + if (table[n] < v) { + low = n + 1; + } else { + size = n; + } + } + return 0; +} + +ucs2_t cjk_compose_seq(const ucs2_t* in, size_t* len, const uint32_t* table, size_t size) +{ + static uint8_t sz[] = { 3, 4, 5, 5, 5, 5, 5, 3 }; + ucs2_t wc = in[0]; + size_t n = sz[wc & 7]; + size_t i = 0; + + if (n > *len) { + errno = EINVAL; + return 0; + } + while (++i < n) { + wc = cjk_compose(wc, in[i], table, size); + if (!wc) { + errno = EILSEQ; + return 0; + } + } + *len = n; + return wc; +} +#endif diff --git a/libatalk/unicode/charsets/generic_cjk.h b/libatalk/unicode/charsets/generic_cjk.h new file mode 100644 index 0000000..3c4a48c --- /dev/null +++ b/libatalk/unicode/charsets/generic_cjk.h @@ -0,0 +1,42 @@ +/* + * generic_cjk + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#define CJK_PUSH_BUFFER 4 +#define CJK_PULL_BUFFER 8 + +typedef struct { + uint16_t range[2]; + const uint16_t (*summary)[2]; +} cjk_index_t; + +extern size_t cjk_generic_push (size_t (*)(uint8_t*, const ucs2_t*, size_t*), + void*, char**, size_t*, char**, size_t*); +extern size_t cjk_generic_pull (size_t (*)(ucs2_t*, const uint8_t*, size_t*), + void*, char**, size_t*, char**, size_t*); + +extern size_t cjk_char_push (uint16_t, uint8_t*); +extern size_t cjk_char_pull (ucs2_t, ucs2_t*, const uint32_t*); + +extern uint16_t cjk_lookup (uint16_t, const cjk_index_t*, const uint16_t*); +extern ucs2_t cjk_compose (ucs2_t, ucs2_t, const uint32_t*, size_t); +extern ucs2_t cjk_compose_seq (const ucs2_t*, size_t*, const uint32_t*, size_t); diff --git a/libatalk/unicode/charsets/generic_mb.c b/libatalk/unicode/charsets/generic_mb.c new file mode 100644 index 0000000..0347c3e --- /dev/null +++ b/libatalk/unicode/charsets/generic_mb.c @@ -0,0 +1,113 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "generic_mb.h" + + + +/* ------------------------ */ + +size_t mb_generic_push( int (*char_func)(unsigned char *, ucs2_t), void *cd _U_, char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft) +{ + int len = 0; + unsigned char *tmpptr = (unsigned char *) *outbuf; + ucs2_t inval; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + + inval = SVAL((*inbuf),0); + if ( (char_func)( tmpptr, inval)) { + (*inbuf) += 2; + tmpptr++; + len++; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + } + else + { + errno = EILSEQ; + return (size_t) -1; + } + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return len; +} + +/* ------------------------ */ + +size_t mb_generic_pull ( int (*char_func)(ucs2_t *, const unsigned char *), void *cd _U_, + char **inbuf, size_t *inbytesleft,char **outbuf, size_t *outbytesleft) +{ + ucs2_t temp; + unsigned char *inptr; + size_t len = 0; + + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + + inptr = (unsigned char *) *inbuf; + if (char_func ( &temp, inptr)) { + SSVAL((*outbuf), 0, temp); + (*inbuf) +=1; + (*outbuf) +=2; + (*inbytesleft) -=1; + (*outbytesleft)-=2; + len++; + + } + else + { + errno = EILSEQ; + return (size_t) -1; + } + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return (size_t) -1; + } + + return len; + +} diff --git a/libatalk/unicode/charsets/generic_mb.h b/libatalk/unicode/charsets/generic_mb.h new file mode 100644 index 0000000..64a40a7 --- /dev/null +++ b/libatalk/unicode/charsets/generic_mb.h @@ -0,0 +1,2 @@ +size_t mb_generic_pull(int (*charfunc)(ucs2_t *, const unsigned char *), void *,char **, size_t *, char **, size_t *); +size_t mb_generic_push(int (*charfunc)(unsigned char *, ucs2_t), void *,char **, size_t *, char **, size_t *); diff --git a/libatalk/unicode/charsets/mac_centraleurope.c b/libatalk/unicode/charsets/mac_centraleurope.c new file mode 100644 index 0000000..40784be --- /dev/null +++ b/libatalk/unicode/charsets/mac_centraleurope.c @@ -0,0 +1,67 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include +#include + +#include + +#include "mac_centraleurope.h" +#include "generic_mb.h" + +static size_t mac_centraleurope_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_centraleurope_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_centraleurope = +{ + "MAC_CENTRALEUROPE", + 29, + mac_centraleurope_pull, + mac_centraleurope_push, + CHARSET_CLIENT | CHARSET_MULTIBYTE, + NULL, + NULL, NULL +}; + + +/* ------------------------ */ + +static size_t mac_centraleurope_push( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_push( char_ucs2_to_mac_centraleurope, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +/* ------------------------ */ + +static size_t mac_centraleurope_pull ( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_pull( char_mac_centraleurope_to_ucs2, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} diff --git a/libatalk/unicode/charsets/mac_centraleurope.h b/libatalk/unicode/charsets/mac_centraleurope.h new file mode 100644 index 0000000..dad99b0 --- /dev/null +++ b/libatalk/unicode/charsets/mac_centraleurope.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 1999-2001 Free Software Foundation, Inc. + * This file is part of the GNU LIBICONV Library. + * + * The GNU LIBICONV Library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * The GNU LIBICONV 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU LIBICONV Library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, Inc., 59 Temple Place - + * Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * MacCentralEurope + */ + +static const unsigned short mac_centraleurope_2uni[128] = { + /* 0x80 */ + 0x00c4, 0x0100, 0x0101, 0x00c9, 0x0104, 0x00d6, 0x00dc, 0x00e1, + 0x0105, 0x010c, 0x00e4, 0x010d, 0x0106, 0x0107, 0x00e9, 0x0179, + /* 0x90 */ + 0x017a, 0x010e, 0x00ed, 0x010f, 0x0112, 0x0113, 0x0116, 0x00f3, + 0x0117, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x011a, 0x011b, 0x00fc, + /* 0xa0 */ + 0x2020, 0x00b0, 0x0118, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df, + 0x00ae, 0x00a9, 0x2122, 0x0119, 0x00a8, 0x2260, 0x0123, 0x012e, + /* 0xb0 */ + 0x012f, 0x012a, 0x2264, 0x2265, 0x012b, 0x0136, 0x2202, 0x2211, + 0x0142, 0x013b, 0x013c, 0x013d, 0x013e, 0x0139, 0x013a, 0x0145, + /* 0xc0 */ + 0x0146, 0x0143, 0x00ac, 0x221a, 0x0144, 0x0147, 0x2206, 0x00ab, + 0x00bb, 0x2026, 0x00a0, 0x0148, 0x0150, 0x00d5, 0x0151, 0x014c, + /* 0xd0 */ + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca, + 0x014d, 0x0154, 0x0155, 0x0158, 0x2039, 0x203a, 0x0159, 0x0156, + /* 0xe0 */ + 0x0157, 0x0160, 0x201a, 0x201e, 0x0161, 0x015a, 0x015b, 0x00c1, + 0x0164, 0x0165, 0x00cd, 0x017d, 0x017e, 0x016a, 0x00d3, 0x00d4, + /* 0xf0 */ + 0x016b, 0x016e, 0x00da, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, + 0x00dd, 0x00fd, 0x0137, 0x017b, 0x0141, 0x017c, 0x0122, 0x02c7, +}; + +static int +char_mac_centraleurope_to_ucs2 (ucs2_t *pwc, const unsigned char *s) +{ + unsigned char c = *s; + if (c < 0x80) + *pwc = (ucs2_t) c; + else + *pwc = (ucs2_t) mac_centraleurope_2uni[c-0x80]; + return 1; +} + +static const unsigned char mac_centraleurope_page00[224] = { + 0xca, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa4, /* 0xa0-0xa7 */ + 0xac, 0xa9, 0x00, 0xc7, 0xc2, 0x00, 0xa8, 0x00, /* 0xa8-0xaf */ + 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, /* 0xb0-0xb7 */ + 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ + 0x00, 0xe7, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ + 0x00, 0x83, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, /* 0xc8-0xcf */ + 0x00, 0x00, 0x00, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */ + 0x00, 0x00, 0xf2, 0x00, 0x86, 0xf8, 0x00, 0xa7, /* 0xd8-0xdf */ + 0x00, 0x87, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ + 0x00, 0x8e, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, /* 0xe8-0xef */ + 0x00, 0x00, 0x00, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */ + 0x00, 0x00, 0x9c, 0x00, 0x9f, 0xf9, 0x00, 0x00, /* 0xf8-0xff */ + /* 0x0100 */ + 0x81, 0x82, 0x00, 0x00, 0x84, 0x88, 0x8c, 0x8d, /* 0x00-0x07 */ + 0x00, 0x00, 0x00, 0x00, 0x89, 0x8b, 0x91, 0x93, /* 0x08-0x0f */ + 0x00, 0x00, 0x94, 0x95, 0x00, 0x00, 0x96, 0x98, /* 0x10-0x17 */ + 0xa2, 0xab, 0x9d, 0x9e, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ + 0x00, 0x00, 0xfe, 0xae, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0xb1, 0xb4, 0x00, 0x00, 0xaf, 0xb0, /* 0x28-0x2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xfa, /* 0x30-0x37 */ + 0x00, 0xbd, 0xbe, 0xb9, 0xba, 0xbb, 0xbc, 0x00, /* 0x38-0x3f */ + 0x00, 0xfc, 0xb8, 0xc1, 0xc4, 0xbf, 0xc0, 0xc5, /* 0x40-0x47 */ + 0xcb, 0x00, 0x00, 0x00, 0xcf, 0xd8, 0x00, 0x00, /* 0x48-0x4f */ + 0xcc, 0xce, 0x00, 0x00, 0xd9, 0xda, 0xdf, 0xe0, /* 0x50-0x57 */ + 0xdb, 0xde, 0xe5, 0xe6, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ + 0xe1, 0xe4, 0x00, 0x00, 0xe8, 0xe9, 0x00, 0x00, /* 0x60-0x67 */ + 0x00, 0x00, 0xed, 0xf0, 0x00, 0x00, 0xf1, 0xf3, /* 0x68-0x6f */ + 0xf4, 0xf5, 0xf6, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ + 0x00, 0x8f, 0x90, 0xfb, 0xfd, 0xeb, 0xec, 0x00, /* 0x78-0x7f */ +}; +static const unsigned char mac_centraleurope_page20[48] = { + 0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */ + 0xa0, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ +}; +static const unsigned char mac_centraleurope_page22[32] = { + 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ + 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ +}; +static const unsigned char mac_centraleurope_page22_1[8] = { + 0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */ +}; + +static int +char_ucs2_to_mac_centraleurope(unsigned char *r, ucs2_t wc) +{ + unsigned char c = 0; + if (wc < 0x0080) { + *r = wc; + return 1; + } + else if (wc >= 0x00a0 && wc < 0x0180) + c = mac_centraleurope_page00[wc-0x00a0]; + else if (wc == 0x02c7) + c = 0xff; + else if (wc >= 0x2010 && wc < 0x2040) + c = mac_centraleurope_page20[wc-0x2010]; + else if (wc == 0x2122) + c = 0xaa; + else if (wc >= 0x2200 && wc < 0x2220) + c = mac_centraleurope_page22[wc-0x2200]; + else if (wc >= 0x2260 && wc < 0x2268) + c = mac_centraleurope_page22_1[wc-0x2260]; + else if (wc == 0x25ca) + c = 0xd7; + if (c != 0) { + *r = c; + return 1; + } + return 0; +} diff --git a/libatalk/unicode/charsets/mac_chinese_simp.c b/libatalk/unicode/charsets/mac_chinese_simp.c new file mode 100644 index 0000000..2ff6c2a --- /dev/null +++ b/libatalk/unicode/charsets/mac_chinese_simp.c @@ -0,0 +1,117 @@ +/* + * MacChineseSimp + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include + +#if HAVE_USABLE_ICONV + +#include "generic_cjk.h" +#include "mac_chinese_simp.h" + +static size_t mac_chinese_simp_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_chinese_simp_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_chinese_simp = { + "MAC_CHINESE_SIMP", + 25, + mac_chinese_simp_pull, + mac_chinese_simp_push, + CHARSET_ICONV | CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED | CHARSET_CLIENT, + "EUC-CN", + NULL, NULL +}; + +static size_t mac_chinese_simp_char_push(uint8_t* out, const ucs2_t* in, size_t* size) +{ + ucs2_t wc = in[0]; + + if (wc <= 0x7f) { + *size = 1; + out[0] = (uint8_t)wc; + return 1; + } else if ((wc & 0xf000) == 0xe000) { + *size = 1; + return 0; + } else if (*size >= 2 && (in[1] & ~15) == 0xf870) { + ucs2_t comp = cjk_compose(wc, in[1], mac_chinese_simp_compose, + sizeof(mac_chinese_simp_compose) / sizeof(uint32_t)); + if (comp) { + wc = comp; + *size = 2; + } else { + *size = 1; + } + } else { + *size = 1; + } + return cjk_char_push(cjk_lookup(wc, mac_chinese_simp_uni2_index, + mac_chinese_simp_uni2_charset), out); +} + +static size_t mac_chinese_simp_push(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_push(mac_chinese_simp_char_push, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +static size_t mac_chinese_simp_char_pull(ucs2_t* out, const uint8_t* in, size_t* size) +{ + uint16_t c = in[0]; + + if (c <= 0x7f) { + *size = 1; + *out = c; + return 1; + } else if (c >= 0xa1 && c <= 0xfc) { + if (*size >= 2) { + uint8_t c2 = in[1]; + + if (c2 >= 0xa1 && c2 <= 0xfe) { + *size = 2; + c = (c << 8) + c2; + } else { + errno = EILSEQ; + return (size_t)-1; + } + } else { + errno = EINVAL; + return (size_t)-1; + } + } else { + *size = 1; + } + return cjk_char_pull(cjk_lookup(c, mac_chinese_simp_2uni_index, + mac_chinese_simp_2uni_charset), + out, mac_chinese_simp_compose); +} + +static size_t mac_chinese_simp_pull(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_pull(mac_chinese_simp_char_pull, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} +#endif diff --git a/libatalk/unicode/charsets/mac_chinese_simp.h b/libatalk/unicode/charsets/mac_chinese_simp.h new file mode 100644 index 0000000..2521625 --- /dev/null +++ b/libatalk/unicode/charsets/mac_chinese_simp.h @@ -0,0 +1,146 @@ +/* + * MacChineseSimp + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +static const uint16_t mac_chinese_simp_uni2_page00[][2] = { + /* 0x00a */ { 0x022d, 0 }, { 0x0080, 5 }, + /* 0x00c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x010 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x014 */ { 0x0110, 6 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x018 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x01c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0200, 8 }, + /* 0x020 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x024 */ { 0x0000, 0 }, { 0x0002, 9 }, { 0x0002, 10 }, +}; + +static const uint16_t mac_chinese_simp_uni2_page1e[][2] = { + /* 0x1e3 */ { 0x8000, 11 }, +}; + +static const uint16_t mac_chinese_simp_uni2_page20[][2] = { + /* 0x201 */ { 0x0070, 12 }, { 0x0040, 15 }, { 0x4000, 16 }, +}; + +static const uint16_t mac_chinese_simp_uni2_page21[][2] = { + /* 0x212 */ { 0x0004, 17 }, +}; + +static const uint16_t mac_chinese_simp_uni2_page22[][2] = { + /* 0x22e */ { 0x8000, 18 }, +}; + +static const uint16_t mac_chinese_simp_uni2_page30[][2] = { + /* 0x301 */ { 0x1000, 19 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x304 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x308 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x30c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0800, 20 }, +}; + +static const uint16_t mac_chinese_simp_uni2_pagee0[][2] = { + /* 0xe00 */ { 0x07ff, 21 }, +}; + +static const uint16_t mac_chinese_simp_uni2_pagef8[][2] = { + /* 0xf88 */ { 0x0003, 32 }, +}; + +static const uint16_t mac_chinese_simp_uni2_pagefe[][2] = { + /* 0xfe3 */ { 0xfffa, 34 }, { 0x001f, 48 }, +}; + +static const uint16_t mac_chinese_simp_uni2_pageff[][2] = { + /* 0xff5 */ { 0x4000, 53 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xff8 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xffc */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x002b, 54 }, +}; + +static const cjk_index_t mac_chinese_simp_uni2_index[] = { + { { 0x00a0, 0x026f }, mac_chinese_simp_uni2_page00 }, + { { 0x1e30, 0x1e3f }, mac_chinese_simp_uni2_page1e }, + { { 0x2010, 0x203f }, mac_chinese_simp_uni2_page20 }, + { { 0x2120, 0x212f }, mac_chinese_simp_uni2_page21 }, + { { 0x22e0, 0x22ef }, mac_chinese_simp_uni2_page22 }, + { { 0x3010, 0x30ff }, mac_chinese_simp_uni2_page30 }, + { { 0xe000, 0xe00f }, mac_chinese_simp_uni2_pagee0 }, + { { 0xf880, 0xf88f }, mac_chinese_simp_uni2_pagef8 }, + { { 0xfe30, 0xfe4f }, mac_chinese_simp_uni2_pagefe }, + { { 0xff50, 0xffef }, mac_chinese_simp_uni2_pageff }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_chinese_simp_uni2_charset[] = { + 0x00a0, 0xa1e9, 0xa1ea, 0xa3a4, 0x00fd, 0xa1a4, 0xa8bd, 0xa8be, + 0xa8bf, 0xa8bb, 0xa8c0, 0xa8bc, 0xa1aa, 0xffff, 0xa1ac, 0x00ff, + 0xa3fe, 0x00fe, 0xa1ad, 0xa1ab, 0xffff, 0x0080, 0xa6f3, 0xa6db, + 0xa6da, 0xa6ec, 0xa6ed, 0xa6de, 0xa6d9, 0xa6dc, 0xa6dd, 0xa6df, + 0x0081, 0x0082, 0xa6f2, 0xa6f4, 0xa6f5, 0xa6e0, 0xa6e1, 0xa6f0, + 0xa6f1, 0xa6e2, 0xa6e3, 0xa6ee, 0xa6ef, 0xa6e6, 0xa6e7, 0xa6e4, + 0xa6e5, 0xa6e8, 0xa6e9, 0xa6ea, 0xa6eb, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, +}; + +static const uint16_t mac_chinese_simp_2uni_page00[][2] = { + /* 0x008 */ { 0x0007, 0 }, { 0x0000, 0 }, { 0x0001, 3 }, { 0x0000, 0 }, + /* 0x00c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0xe000, 4 }, +}; + +static const uint16_t mac_chinese_simp_2uni_pagea1[][2] = { + /* 0xa1a */ { 0x3c10, 7 }, { 0x0000, 0 }, + /* 0xa1c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0600, 12 }, +}; + +static const uint16_t mac_chinese_simp_2uni_pagea3[][2] = { + /* 0xa3a */ { 0x0010, 14 }, { 0x0000, 0 }, + /* 0xa3c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x4000, 15 }, +}; + +static const uint16_t mac_chinese_simp_2uni_pagea6[][2] = { + /* 0xa6d */ { 0xfe00, 16 }, { 0xffff, 23 }, { 0x003f, 39 }, +}; + +static const uint16_t mac_chinese_simp_2uni_pagea8[][2] = { + /* 0xa8b */ { 0xf800, 45 }, { 0x0001, 50 }, +}; + +static const cjk_index_t mac_chinese_simp_2uni_index[] = { + { { 0x0080, 0x00ff }, mac_chinese_simp_2uni_page00 }, + { { 0xa1a0, 0xa1ef }, mac_chinese_simp_2uni_pagea1 }, + { { 0xa3a0, 0xa3ff }, mac_chinese_simp_2uni_pagea3 }, + { { 0xa6d0, 0xa6ff }, mac_chinese_simp_2uni_pagea6 }, + { { 0xa8b0, 0xa8cf }, mac_chinese_simp_2uni_pagea8 }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_chinese_simp_2uni_charset[] = { + 0xe000, 0xf880, 0xf881, 0x00a0, 0x00a9, 0x2122, 0x2026, 0x00b7, + 0x2014, 0x301c, 0x2016, 0x22ef, 0x00a2, 0x00a3, 0x00a5, 0x203e, + 0xe007, 0xe003, 0xe002, 0xe008, 0xe009, 0xe006, 0xe00a, 0xfe35, + 0xfe36, 0xfe39, 0xfe3a, 0xfe3f, 0xfe40, 0xfe3d, 0xfe3e, 0xfe41, + 0xfe42, 0xfe43, 0xfe44, 0xe004, 0xe005, 0xfe3b, 0xfe3c, 0xfe37, + 0xfe38, 0xfe31, 0xe001, 0xfe33, 0xfe34, 0x0251, 0x1e3f, 0x0144, + 0x0148, 0x01f9, 0x0261, +}; + +static const uint32_t mac_chinese_simp_compose[] = { + 0x00fcf87f, 0x22eff87e, 0x3001f87e, 0x3002f87e, + 0x3016f87e, 0x3017f87e, 0xff01f87e, 0xff0cf87e, + 0xff1af87e, 0xff1bf87e, 0xff1ff87e, +}; diff --git a/libatalk/unicode/charsets/mac_chinese_trad.c b/libatalk/unicode/charsets/mac_chinese_trad.c new file mode 100644 index 0000000..116e8cd --- /dev/null +++ b/libatalk/unicode/charsets/mac_chinese_trad.c @@ -0,0 +1,122 @@ +/* + * MacChineseTrad + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include + +#if HAVE_USABLE_ICONV + +#include "generic_cjk.h" +#include "mac_chinese_trad.h" + +static size_t mac_chinese_trad_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_chinese_trad_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_chinese_trad = { + "MAC_CHINESE_TRAD", + 2, + mac_chinese_trad_pull, + mac_chinese_trad_push, + CHARSET_ICONV | CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED | CHARSET_CLIENT, + "BIG-5", + NULL, NULL +}; + +static size_t mac_chinese_trad_char_push(uint8_t* out, const ucs2_t* in, size_t* size) +{ + ucs2_t wc = in[0]; + + if (wc <= 0x7f) { + if (wc == 0x5c && *size >= 2 && in[1] == 0xf87f) { + *size = 2; + out[0] = 0x80; + } else { + *size = 1; + out[0] = (uint8_t)wc; + } + return 1; + } else if ((wc & 0xf000) == 0xe000) { + *size = 1; + return 0; + } else if (*size >= 2 && (in[1] & ~15) == 0xf870) { + ucs2_t comp = cjk_compose(wc, in[1], mac_chinese_trad_compose, + sizeof(mac_chinese_trad_compose) / sizeof(uint32_t)); + if (comp) { + wc = comp; + *size = 2; + } else { + *size = 1; + } + } else { + *size = 1; + } + return cjk_char_push(cjk_lookup(wc, mac_chinese_trad_uni2_index, + mac_chinese_trad_uni2_charset), out); +} + +static size_t mac_chinese_trad_push(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_push(mac_chinese_trad_char_push, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +static size_t mac_chinese_trad_char_pull(ucs2_t* out, const uint8_t* in, size_t* size) +{ + uint16_t c = in[0]; + + if (c <= 0x7f) { + *size = 1; + *out = c; + return 1; + } else if (c >= 0xa1 && c <= 0xfc) { + if (*size >= 2) { + uint8_t c2 = in[1]; + + if ((c2 >= 0x40 && c2 <= 0x7e) || (c2 >= 0xa1 && c2 <= 0xfe)) { + *size = 2; + c = (c << 8) + c2; + } else { + errno = EILSEQ; + return (size_t)-1; + } + } else { + errno = EINVAL; + return (size_t)-1; + } + } else { + *size = 1; + } + return cjk_char_pull(cjk_lookup(c, mac_chinese_trad_2uni_index, + mac_chinese_trad_2uni_charset), + out, mac_chinese_trad_compose); +} + +static size_t mac_chinese_trad_pull(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_pull(mac_chinese_trad_char_pull, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} +#endif diff --git a/libatalk/unicode/charsets/mac_chinese_trad.h b/libatalk/unicode/charsets/mac_chinese_trad.h new file mode 100644 index 0000000..00e0c51 --- /dev/null +++ b/libatalk/unicode/charsets/mac_chinese_trad.h @@ -0,0 +1,124 @@ +/* + * MacChineseTrad + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +static const uint16_t mac_chinese_trad_uni2_page00[][2] = { + /* 0x00a */ { 0x0201, 0 }, { 0x0080, 2 }, +}; + +static const uint16_t mac_chinese_trad_uni2_page20[][2] = { + /* 0x202 */ { 0x0044, 3 }, +}; + +static const uint16_t mac_chinese_trad_uni2_page21[][2] = { + /* 0x212 */ { 0x0004, 5 }, +}; + +static const uint16_t mac_chinese_trad_uni2_page22[][2] = { + /* 0x229 */ { 0x0020, 6 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x22c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x8000, 7 }, +}; + +static const uint16_t mac_chinese_trad_uni2_page25[][2] = { + /* 0x259 */ { 0x0020, 8 }, +}; + +static const uint16_t mac_chinese_trad_uni2_page26[][2] = { + /* 0x264 */ { 0x0002, 9 }, +}; + +static const uint16_t mac_chinese_trad_uni2_pagee0[][2] = { + /* 0xe00 */ { 0xffff, 10 }, { 0x00ff, 26 }, +}; + +static const uint16_t mac_chinese_trad_uni2_pagef8[][2] = { + /* 0xf88 */ { 0x0003, 34 }, +}; + +static const uint16_t mac_chinese_trad_uni2_pagefe[][2] = { + /* 0xfe4 */ { 0x1000, 36 }, { 0x7ef5, 37 }, +}; + +static const uint16_t mac_chinese_trad_uni2_pageff[][2] = { + /* 0xff6 */ { 0x0010, 49 }, +}; + +static const cjk_index_t mac_chinese_trad_uni2_index[] = { + { { 0x00a0, 0x00bf }, mac_chinese_trad_uni2_page00 }, + { { 0x2020, 0x202f }, mac_chinese_trad_uni2_page20 }, + { { 0x2120, 0x212f }, mac_chinese_trad_uni2_page21 }, + { { 0x2290, 0x22ef }, mac_chinese_trad_uni2_page22 }, + { { 0x2590, 0x259f }, mac_chinese_trad_uni2_page25 }, + { { 0x2640, 0x264f }, mac_chinese_trad_uni2_page26 }, + { { 0xe000, 0xe01f }, mac_chinese_trad_uni2_pagee0 }, + { { 0xf880, 0xf88f }, mac_chinese_trad_uni2_pagef8 }, + { { 0xfe40, 0xfe5f }, mac_chinese_trad_uni2_pagefe }, + { { 0xff60, 0xff6f }, mac_chinese_trad_uni2_pageff }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_chinese_trad_uni2_charset[] = { + 0x00a0, 0x00fd, 0xa145, 0xffff, 0x00ff, 0x00fe, 0xa1f2, 0xa14b, + 0xffff, 0xffff, 0x0080, 0xa1c3, 0xa279, 0xa14e, 0xa1a3, 0xa1a4, + 0xa2cc, 0xa2ce, 0xa1cb, 0xa154, 0xa17d, 0xa17e, 0xa14d, 0xa14f, + 0xa150, 0xa1fe, 0xa152, 0xa151, 0xa153, 0xa240, 0xa1c5, 0xa15a, + 0xa1a1, 0xa1a2, 0x0081, 0x0082, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, +}; + +static const uint16_t mac_chinese_trad_2uni_page00[][2] = { + /* 0x008 */ { 0x0007, 0 }, { 0x0000, 0 }, { 0x0001, 3 }, { 0x0000, 0 }, + /* 0x00c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0xe000, 4 }, +}; + +static const uint16_t mac_chinese_trad_2uni_pagea1[][2] = { + /* 0xa14 */ { 0xe820, 7 }, { 0x041f, 12 }, { 0x0000, 0 }, { 0x6000, 18 }, + /* 0xa18 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x001e, 20 }, { 0x0000, 0 }, + /* 0xa1c */ { 0x0828, 24 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x4004, 27 }, + /* 0xa20 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa24 */ { 0x0001, 29 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0200, 30 }, + /* 0xa28 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa2c */ { 0x5000, 31 }, +}; + +static const cjk_index_t mac_chinese_trad_2uni_index[] = { + { { 0x0080, 0x00ff }, mac_chinese_trad_2uni_page00 }, + { { 0xa140, 0xa2cf }, mac_chinese_trad_2uni_pagea1 }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_chinese_trad_2uni_charset[] = { + 0xe000, 0xf880, 0xf881, 0x00a0, 0x00a9, 0x2122, 0x2026, 0x00b7, + 0x22ef, 0xe00c, 0xe003, 0xe00d, 0xe00e, 0xe011, 0xe010, 0xe012, + 0xe009, 0xe015, 0xe00a, 0xe00b, 0xe016, 0xe017, 0xe004, 0xe005, + 0xe001, 0xe014, 0xe008, 0x2295, 0xe00f, 0xe013, 0xe002, 0xe006, + 0xe007, +}; + +static const uint32_t mac_chinese_trad_compose[] = { + 0x005cf87f, 0x203ef87c, 0x2502f87f, 0x3001f87d, + 0x3014f87f, 0x3015f87f, 0x5341f87f, 0x5345f87f, + 0xfe4bf87c, 0xff01f87d, 0xff08f87f, 0xff09f87f, + 0xff0cf87d, 0xff0ef87d, 0xff0ef87e, 0xff0ff87f, + 0xff1af87d, 0xff1bf87d, 0xff1ff87d, 0xff3cf87f, + 0xff3ff87c, 0xff3ff87f, 0xff5bf87f, 0xff5df87f, +}; diff --git a/libatalk/unicode/charsets/mac_cyrillic.c b/libatalk/unicode/charsets/mac_cyrillic.c new file mode 100644 index 0000000..fde6486 --- /dev/null +++ b/libatalk/unicode/charsets/mac_cyrillic.c @@ -0,0 +1,67 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include /* for size_t */ +#include + +#include + +#include "mac_cyrillic.h" +#include "generic_mb.h" + +static size_t mac_cyrillic_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_cyrillic_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_cyrillic = +{ + "MAC_CYRILLIC", + 7, + mac_cyrillic_pull, + mac_cyrillic_push, + CHARSET_CLIENT | CHARSET_MULTIBYTE, + NULL, + NULL, NULL +}; + + +/* ------------------------ */ + +static size_t mac_cyrillic_push( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_push( char_ucs2_to_mac_cyrillic, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +/* ------------------------ */ + +static size_t mac_cyrillic_pull ( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_pull( char_mac_cyrillic_to_ucs2, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} diff --git a/libatalk/unicode/charsets/mac_cyrillic.h b/libatalk/unicode/charsets/mac_cyrillic.h new file mode 100644 index 0000000..4c6681a --- /dev/null +++ b/libatalk/unicode/charsets/mac_cyrillic.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 1999-2001 Free Software Foundation, Inc. + * This file is part of the GNU LIBICONV Library. + * + * The GNU LIBICONV Library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * The GNU LIBICONV 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU LIBICONV Library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, Inc., 59 Temple Place - + * Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * MacCyrillic + */ + +static const unsigned short mac_cyrillic_2uni[128] = { + /* 0x80 */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + /* 0x90 */ + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + /* 0xa0 */ + 0x2020, 0x00b0, 0x0490, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x0406, + 0x00ae, 0x00a9, 0x2122, 0x0402, 0x0452, 0x2260, 0x0403, 0x0453, + /* 0xb0 */ + 0x221e, 0x00b1, 0x2264, 0x2265, 0x0456, 0x00b5, 0x0491, 0x0408, + 0x0404, 0x0454, 0x0407, 0x0457, 0x0409, 0x0459, 0x040a, 0x045a, + /* 0xc0 */ + 0x0458, 0x0405, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab, + 0x00bb, 0x2026, 0x00a0, 0x040b, 0x045b, 0x040c, 0x045c, 0x0455, + /* 0xd0 */ + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x201e, + 0x040e, 0x045e, 0x040f, 0x045f, 0x2116, 0x0401, 0x0451, 0x044f, + /* 0xe0 */ + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + /* 0xf0 */ + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x20ac, +}; + +static int +char_mac_cyrillic_to_ucs2 (ucs2_t *pwc, const unsigned char *s) +{ + unsigned char c = *s; + if (c >= 0x80) + *pwc = (ucs2_t) mac_cyrillic_2uni[c-0x80]; + else + *pwc = (ucs2_t) c; + return 1; +} + +static const unsigned char mac_cyrillic_page00[32] = { + 0xca, 0x00, 0xa2, 0xa3, 0xff, 0x00, 0x00, 0xa4, /* 0xa0-0xa7 */ + 0x00, 0xa9, 0x00, 0xc7, 0xc2, 0x00, 0xa8, 0x00, /* 0xa8-0xaf */ + 0xa1, 0xb1, 0x00, 0x00, 0x00, 0xb5, 0xa6, 0x00, /* 0xb0-0xb7 */ + 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ +}; +static const unsigned char mac_cyrillic_page04[96] = { + 0x00, 0xdd, 0xab, 0xae, 0xb8, 0xc1, 0xa7, 0xba, /* 0x00-0x07 */ + 0xb7, 0xbc, 0xbe, 0xcb, 0xcd, 0x00, 0xd8, 0xda, /* 0x08-0x0f */ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x10-0x17 */ + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x18-0x1f */ + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x20-0x27 */ + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x28-0x2f */ + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x30-0x37 */ + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x38-0x3f */ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x40-0x47 */ + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0x48-0x4f */ + 0x00, 0xde, 0xac, 0xaf, 0xb9, 0xcf, 0xb4, 0xbb, /* 0x50-0x57 */ + 0xc0, 0xbd, 0xbf, 0xcc, 0xce, 0x00, 0xd9, 0xdb, /* 0x58-0x5f */ +}; +static const unsigned char mac_cyrillic_page20[24] = { + 0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0xd4, 0xd5, 0x00, 0x00, 0xd2, 0xd3, 0xd7, 0x00, /* 0x18-0x1f */ + 0xa0, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */ +}; +static const unsigned char mac_cyrillic_page21[24] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, /* 0x10-0x17 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ + 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ +}; +static const unsigned char mac_cyrillic_page22[104] = { + 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ + 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ + 0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */ +}; + +static int +char_ucs2_to_mac_cyrillic(unsigned char *r, ucs2_t wc) +{ + unsigned char c = 0; + if (wc < 0x0080) { + *r = wc; + return 1; + } + else if (wc >= 0x00a0 && wc < 0x00c0) + c = mac_cyrillic_page00[wc-0x00a0]; + else if (wc == 0x00f7) + c = 0xd6; + else if (wc == 0x0192) + c = 0xc4; + else if (wc >= 0x0400 && wc < 0x0460) + c = mac_cyrillic_page04[wc-0x0400]; + else if (wc == 0x0490) + c = 0xa2; + else if (wc == 0x0491) + c = 0xb6; + else if (wc >= 0x2010 && wc < 0x2028) + c = mac_cyrillic_page20[wc-0x2010]; + else if (wc == 0x20ac) + c = 0xff; + else if (wc >= 0x2110 && wc < 0x2128) + c = mac_cyrillic_page21[wc-0x2110]; + else if (wc >= 0x2200 && wc < 0x2268) + c = mac_cyrillic_page22[wc-0x2200]; + if (c != 0) { + *r = c; + return 1; + } + return 0; +} diff --git a/libatalk/unicode/charsets/mac_greek.c b/libatalk/unicode/charsets/mac_greek.c new file mode 100644 index 0000000..e48237b --- /dev/null +++ b/libatalk/unicode/charsets/mac_greek.c @@ -0,0 +1,112 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + Copyright (C) Panos Christeas 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include +#include + +#include + +#include "mac_greek.h" +#include "generic_mb.h" + +static size_t mac_greek_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_greek_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_greek = +{ + "MAC_GREEK", + 6, + mac_greek_pull, + mac_greek_push, + CHARSET_CLIENT | CHARSET_MULTIBYTE, + NULL, + NULL, NULL +}; + +/* ------------------------ */ +static int +char_ucs2_to_mac_greek ( unsigned char *r, ucs2_t wc) +{ + unsigned char c = 0; + if (wc < 0x0080) { + *r = wc; + return 1; + } + else if (wc >= 0x00a0 && wc < 0x0100) + c = mac_greek_page00[wc-0x00a0]; + else if (wc == 0x0153) + c = 0xcf; + else if (wc >= 0x0380 && wc < 0x03d0) + c = mac_greek_page03[wc-0x0380]; + else if (wc >= 0x2010 && wc < 0x2038) + c = mac_greek_page20[wc-0x2010]; + else if (wc == 0x2122) + c = 0x93; + else if (wc >= 0x2248 && wc < 0x2268) + c = mac_greek_page22[wc-0x2248]; + if (c != 0) { + *r = c; + return 1; + } + return 0; + } + +static size_t mac_greek_push( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + /* No special handling required */ + return (size_t) mb_generic_push( char_ucs2_to_mac_greek, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +/* ------------------------ */ +static int +char_mac_greek_to_ucs2 (ucs2_t *pwc, const unsigned char *s) +{ + unsigned char c = *s; + if (c < 0x80) { + *pwc = (ucs2_t) c; + return 1; + } + else { + unsigned short wc = mac_greek_2uni[c-0x80]; + if (wc != 0xfffd) { + *pwc = (ucs2_t) wc; + return 1; + } + } + return 0; +} + +static size_t mac_greek_pull ( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_pull( char_mac_greek_to_ucs2, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} diff --git a/libatalk/unicode/charsets/mac_greek.h b/libatalk/unicode/charsets/mac_greek.h new file mode 100644 index 0000000..6e0851b --- /dev/null +++ b/libatalk/unicode/charsets/mac_greek.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 1999-2001 Free Software Foundation, Inc. + * This file is part of the GNU LIBICONV Library. + * + * The GNU LIBICONV Library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * The GNU LIBICONV 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU LIBICONV Library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, Inc., 59 Temple Place - + * Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * MacGreek + */ + +static const unsigned short mac_greek_2uni[128] = { + /* 0x80 */ + 0x00c4, 0x00b9, 0x00b2, 0x00c9, 0x00b3, 0x00d6, 0x00dc, 0x0385, + 0x00e0, 0x00e2, 0x00e4, 0x0384, 0x00a8, 0x00e7, 0x00e9, 0x00e8, + /* 0x90 */ + 0x00ea, 0x00eb, 0x00a3, 0x2122, 0x00ee, 0x00ef, 0x2022, 0x00bd, + 0x2030, 0x00f4, 0x00f6, 0x00a6, 0x00ad, 0x00f9, 0x00fb, 0x00fc, + /* 0xa0 */ + 0x2020, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03a0, 0x00df, + 0x00ae, 0x00a9, 0x03a3, 0x03aa, 0x00a7, 0x2260, 0x00b0, 0x0387, + /* 0xb0 */ + 0x0391, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x0392, 0x0395, 0x0396, + 0x0397, 0x0399, 0x039a, 0x039c, 0x03a6, 0x03ab, 0x03a8, 0x03a9, + /* 0xc0 */ + 0x03ac, 0x039d, 0x00ac, 0x039f, 0x03a1, 0x2248, 0x03a4, 0x00ab, + 0x00bb, 0x2026, 0x00a0, 0x03a5, 0x03a7, 0x0386, 0x0388, 0x0153, + /* 0xd0 */ + 0x2013, 0x2015, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x0389, + 0x038a, 0x038c, 0x038e, 0x03ad, 0x03ae, 0x03af, 0x03cc, 0x038f, + /* 0xe0 */ + 0x03cd, 0x03b1, 0x03b2, 0x03c8, 0x03b4, 0x03b5, 0x03c6, 0x03b3, + 0x03b7, 0x03b9, 0x03be, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf, + /* 0xf0 */ + 0x03c0, 0x03ce, 0x03c1, 0x03c3, 0x03c4, 0x03b8, 0x03c9, 0x03c2, + 0x03c7, 0x03c5, 0x03b6, 0x03ca, 0x03cb, 0x0390, 0x03b0, 0xfffd, +}; + +static const unsigned char mac_greek_page00[96] = { + 0xca, 0x00, 0x00, 0x92, 0x00, 0xb4, 0x9b, 0xac, /* 0xa0-0xa7 */ + 0x8c, 0xa9, 0x00, 0xc7, 0xc2, 0x9c, 0xa8, 0x00, /* 0xa8-0xaf */ + 0xae, 0xb1, 0x82, 0x84, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ + 0x00, 0x81, 0x00, 0xc8, 0x00, 0x97, 0x00, 0x00, /* 0xb8-0xbf */ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ + 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0xd0-0xd7 */ + 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0xa7, /* 0xd8-0xdf */ + 0x88, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x00, 0x8d, /* 0xe0-0xe7 */ + 0x8f, 0x8e, 0x90, 0x91, 0x00, 0x00, 0x94, 0x95, /* 0xe8-0xef */ + 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x9a, 0xd6, /* 0xf0-0xf7 */ + 0x00, 0x9d, 0x00, 0x9e, 0x9f, 0x00, 0x00, 0x00, /* 0xf8-0xff */ +}; +static const unsigned char mac_greek_page03[80] = { + 0x00, 0x00, 0x00, 0x00, 0x8b, 0x87, 0xcd, 0xaf, /* 0x80-0x87 */ + 0xce, 0xd7, 0xd8, 0x00, 0xd9, 0x00, 0xda, 0xdf, /* 0x88-0x8f */ + 0xfd, 0xb0, 0xb5, 0xa1, 0xa2, 0xb6, 0xb7, 0xb8, /* 0x90-0x97 */ + 0xa3, 0xb9, 0xba, 0xa4, 0xbb, 0xc1, 0xa5, 0xc3, /* 0x98-0x9f */ + 0xa6, 0xc4, 0x00, 0xaa, 0xc6, 0xcb, 0xbc, 0xcc, /* 0xa0-0xa7 */ + 0xbe, 0xbf, 0xab, 0xbd, 0xc0, 0xdb, 0xdc, 0xdd, /* 0xa8-0xaf */ + 0xfe, 0xe1, 0xe2, 0xe7, 0xe4, 0xe5, 0xfa, 0xe8, /* 0xb0-0xb7 */ + 0xf5, 0xe9, 0xeb, 0xec, 0xed, 0xee, 0xea, 0xef, /* 0xb8-0xbf */ + 0xf0, 0xf2, 0xf7, 0xf3, 0xf4, 0xf9, 0xe6, 0xf8, /* 0xc0-0xc7 */ + 0xe3, 0xf6, 0xfb, 0xfc, 0xde, 0xe0, 0xf1, 0x00, /* 0xc8-0xcf */ +}; +static const unsigned char mac_greek_page20[40] = { + 0x00, 0x00, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0x00, /* 0x10-0x17 */ + 0xd4, 0xd5, 0x00, 0x00, 0xd2, 0xd3, 0x00, 0x00, /* 0x18-0x1f */ + 0xa0, 0x00, 0x96, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ +}; +static const unsigned char mac_greek_page22[32] = { + 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ + 0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */ +}; + diff --git a/libatalk/unicode/charsets/mac_hebrew.c b/libatalk/unicode/charsets/mac_hebrew.c new file mode 100644 index 0000000..34d9690 --- /dev/null +++ b/libatalk/unicode/charsets/mac_hebrew.c @@ -0,0 +1,222 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include +#include +#include +#include + +#include +#include +#include + +#include "mac_hebrew.h" + +static size_t mac_hebrew_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_hebrew_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_hebrew = +{ + "MAC_HEBREW", + 5, + mac_hebrew_pull, + mac_hebrew_push, + CHARSET_CLIENT | CHARSET_MULTIBYTE, + NULL, + NULL, NULL +}; + + +/* ------------------------ + * from unicode to mac hebrew code page +*/ +static int +char_ucs2_to_mac_hebrew ( unsigned char *r, ucs2_t wc) +{ + unsigned char c = 0; + if (wc < 0x0080) { + *r = wc; + return 1; + } + else if (wc >= 0x00a0 && wc < 0x0100) + c = mac_hebrew_page00[wc-0x00a0]; + else if (wc >= 0x05b0 && wc < 0x05f0) + c = mac_hebrew_page05[wc-0x05b0]; + else if (wc >= 0x2010 && wc < 0x2028) + c = mac_hebrew_page20[wc-0x2010]; + else if (wc == 0x20aa) + c = 0xa6; + else if (wc >= 0xfb18 && wc < 0xfb50) + c = mac_hebrew_pagefb[wc-0xfb18]; + if (c != 0) { + *r = c; + return 1; + } + return 0; +} + +static size_t mac_hebrew_push( void *cd _U_, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + unsigned char c = 0; + int len = 0; + unsigned char *tmpptr = (unsigned char *) *outbuf; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + ucs2_t inptr = SVAL((*inbuf),0); + if (inptr == 0x05b8) { + (*inbuf) += 2; + (*inbytesleft) -= 2; + if (*inbytesleft >= 2 && SVAL((*inbuf),0) == 0xf87f ) { + (*inbuf) += 2; + (*inbytesleft) -= 2; + c = 0xde; + } + else { + c = 0xcb; + } + *tmpptr = c; + } + else if (inptr == 0x05f2 && *inbytesleft >= 4 && SVAL((*inbuf),2) == 0x05b7) { + (*inbuf) += 4; + (*inbytesleft) -= 4; + *tmpptr = 0x81; + } + else if (inptr == 0xf86a && *inbytesleft >= 6 && SVAL((*inbuf),2) == 0x05dc && SVAL((*inbuf),4) == 0x05b9) { + (*inbuf) += 6; + (*inbytesleft) -= 6; + *tmpptr = 0xc0; + } + else if (char_ucs2_to_mac_hebrew ( tmpptr, inptr)) { + (*inbuf) += 2; + (*inbytesleft) -= 2; + } + else { + errno = EILSEQ; + return (size_t) -1; + } + (*outbytesleft) -= 1; + tmpptr++; + len++; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return len; +} + +/* ------------------------ */ +static int +char_mac_hebrew_to_ucs2 (ucs2_t *pwc, const unsigned char *s) +{ + unsigned char c = *s; + if (c < 0x80) { + *pwc = (ucs2_t) c; + return 1; + } + else { + unsigned short wc = mac_hebrew_2uni[c-0x80]; + if (wc != 0xfffd) { + *pwc = (ucs2_t) wc; + return 1; + } + } + return 0; +} + +static size_t mac_hebrew_pull ( void *cd _U_, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + ucs2_t temp; + unsigned char *inptr; + size_t len = 0; + + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + inptr = (unsigned char *) *inbuf; + if (char_mac_hebrew_to_ucs2 ( &temp, inptr)) { + if (temp == 1) { /* 0x81 --> 0x05f2+0x05b7 */ + if (*outbytesleft < 4) { + errno = E2BIG; + return (size_t) -1; + } + SSVAL((*outbuf),0,0x05f2); + SSVAL((*outbuf),2,0x05b7); + (*outbuf) +=4; + (*outbytesleft)-=4; + len += 2; + } + else if (temp == 2) { /* 0xc0 -> 0xf86a 0x05dc 0x05b9*/ + if (*outbytesleft < 6) { + errno = E2BIG; + return (size_t) -1; + } + SSVAL((*outbuf),0,0xf86a); + SSVAL((*outbuf),2,0x05dc); + SSVAL((*outbuf),4,0x05b9); + (*outbuf) +=6; + (*outbytesleft)-=6; + len += 3; + } + else if (temp == 3) { /* 0xde --> 0x05b8 0xf87f */ + if (*outbytesleft < 4) { + errno = E2BIG; + return (size_t) -1; + } + SSVAL((*outbuf),0,0x05b8); + SSVAL((*outbuf),2,0xf87f); + (*outbuf) +=4; + (*outbytesleft)-=4; + len += 2; + } + else { + SSVAL((*outbuf),0,temp); + (*outbuf) +=2; + (*outbytesleft)-=2; + len++; + } + (*inbuf) +=1; + (*inbytesleft) -=1; + } + else + { + errno = EILSEQ; + return (size_t) -1; + } + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return (size_t) -1; + } + return len; +} + diff --git a/libatalk/unicode/charsets/mac_hebrew.h b/libatalk/unicode/charsets/mac_hebrew.h new file mode 100644 index 0000000..dbb55fe --- /dev/null +++ b/libatalk/unicode/charsets/mac_hebrew.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 1999-2001 Free Software Foundation, Inc. + * This file is part of the GNU LIBICONV Library. + * + * The GNU LIBICONV Library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * The GNU LIBICONV 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU LIBICONV Library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, Inc., 59 Temple Place - + * Suite 330, Boston, MA 02111-1307, USA. + * + * from libiconv + * modified for round trip by didier gautheron + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +/* + * MacHebrew + */ + +static const unsigned short mac_hebrew_2uni[128] = { + /* 0x80 0x81 -> 0x05f2+0x05b7 was 0xfb1f */ + 0x00c4, 01, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1, + 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8, + + /* 0x90 */ + 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3, + 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc, + + /* 0xa0 */ + /* 0xffd move to right to left (not 0x20aa) */ + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x20aa, 0x0027, + 0x0029, 0x0028, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + + /* 0xb0 */ + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + + /* 0xc0 -> 0xf86a 0x05dc 0x05b9*/ + 02, 0x201e, 0xf89b, 0xf89c, 0xf89d, 0xf89e, 0x05bc, 0xfb4b, + 0xfb35, 0x2026, 0x00a0, 0x05b8, 0x05b7, 0x05b5, 0x05b6, 0x05b4, + + /* 0xd0 + 0xde --> 0x05b8 0xf87f + */ + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xfb2a, 0xfb2b, + 0x05bf, 0x05b0, 0x05b2, 0x05b1, 0x05bb, 0x05b9, 03, 0x05b3, + /* 0xe0 */ + 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, + 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, + /* 0xf0 */ + 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, + 0x05e8, 0x05e9, 0x05ea, 0x007d, 0x005d, 0x007b, 0x005b, 0x007c, +}; + +/* (wc >= 0x00a0 && wc < 0x0100) */ + +static const unsigned char mac_hebrew_page00[96] = { + 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x82, /* 0xc0-0xc7 */ + 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ + 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0xd0-0xd7 */ + 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ + 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0x00, 0x8d, /* 0xe0-0xe7 */ + 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */ + 0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0x00, /* 0xf0-0xf7 */ + 0x00, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0x00, /* 0xf8-0xff */ +}; + +/* (wc >= 0x05b0 && wc < 0x05f0) */ +static const unsigned char mac_hebrew_page05[64] = { + 0xd9, 0xdb, 0xda, 0xdf, 0xcf, 0xcd, 0xce, 0xcc, /* 0xb0-0xb7 */ + 0xcb, 0xdd, 0x00, 0xdc, 0xc6, 0x00, 0x00, 0xd8, /* 0xb8-0xbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xd0-0xd7 */ + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xd8-0xdf */ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xe0-0xe7 */ + 0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ +}; + +/* (wc >= 0x2010 && wc < 0x2028) */ +static const unsigned char mac_hebrew_page20[24] = { + 0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0xd4, 0xd5, 0x00, 0x00, 0xd2, 0xd3, 0xc1, 0x00, /* 0x18-0x1f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */ +}; + +/* (wc >= 0xfb18 && wc < 0xfb50) */ +static const unsigned char mac_hebrew_pagefb[56] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, /* 0x18-0x1f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0xd6, 0xd7, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ + 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ +}; + diff --git a/libatalk/unicode/charsets/mac_japanese.c b/libatalk/unicode/charsets/mac_japanese.c new file mode 100644 index 0000000..9f32f66 --- /dev/null +++ b/libatalk/unicode/charsets/mac_japanese.c @@ -0,0 +1,130 @@ +/* + * MacJapanese + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include + +#if HAVE_USABLE_ICONV + +#include "generic_cjk.h" +#include "mac_japanese.h" + +static size_t mac_japanese_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_japanese_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_japanese = { + "MAC_JAPANESE", + 1, + mac_japanese_pull, + mac_japanese_push, + CHARSET_ICONV | CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED | CHARSET_CLIENT, + "SHIFT_JIS", + NULL, NULL +}; + +static size_t mac_japanese_char_push(uint8_t* out, const ucs2_t* in, size_t* size) +{ + ucs2_t wc = in[0]; + + if (wc <= 0x7f) { + *size = 1; + out[0] = (uint8_t)(wc == 0x5c ? 0x80 : wc); + return 1; + } else if ((wc & 0xf000) == 0xe000) { /* user defined */ + *size = 1; + if (wc > 0xe98b) return 0; + wc -= 0xe000; + out[0] = (uint8_t)(wc / 188 + 0xf0); + out[1] = (uint8_t)(wc % 188 + 0x40); + if (out[1] >= 0x7f) ++out[1]; + return 2; + } else if ((wc & ~7) == 0xf860) { + wc = cjk_compose_seq(in, size, mac_japanese_compose, + sizeof(mac_japanese_compose) / sizeof(uint32_t)); + if (!wc) return (size_t)-1; + } else if (*size >= 2 && ((in[1] & ~15) == 0xf870 || in[1] == 0x20dd)) { + ucs2_t comp = cjk_compose(wc, in[1], mac_japanese_compose, + sizeof(mac_japanese_compose) / sizeof(uint32_t)); + if (comp) { + wc = comp; + *size = 2; + } else { + *size = 1; + } + } else { + *size = 1; + } + return cjk_char_push(cjk_lookup(wc, mac_japanese_uni2_index, + mac_japanese_uni2_charset), out); +} + +static size_t mac_japanese_push(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_push(mac_japanese_char_push, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +static size_t mac_japanese_char_pull(ucs2_t* out, const uint8_t* in, size_t* size) +{ + uint16_t c = in[0]; + + if (c <= 0x7f) { + *size = 1; + *out = (c == 0x5c ? 0xa5 : c); + return 1; + } else if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc)) { + if (*size >= 2) { + uint8_t c2 = in[1]; + + if ((c2 >= 0x40 && c2 <= 0x7e) || (c2 >= 0x80 && c2 <= 0xfc)) { + *size = 2; + if (c >= 0xf0) { /* user defined */ + *out = 0xe000 + (c - 0xf0) * 188 + c2 - (c2 < 0x80 ? 0x40 : 0x41); + return 1; + } + c = (c << 8) + c2; + } else { + errno = EILSEQ; + return (size_t)-1; + } + } else { + errno = EINVAL; + return (size_t)-1; + } + } else { + *size = 1; + } + return cjk_char_pull(cjk_lookup(c, mac_japanese_2uni_index, + mac_japanese_2uni_charset), + out, mac_japanese_compose); +} + +static size_t mac_japanese_pull(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_pull(mac_japanese_char_pull, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} +#endif diff --git a/libatalk/unicode/charsets/mac_japanese.h b/libatalk/unicode/charsets/mac_japanese.h new file mode 100644 index 0000000..e27e450 --- /dev/null +++ b/libatalk/unicode/charsets/mac_japanese.h @@ -0,0 +1,252 @@ +/* + * MacJapanese + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +static const uint16_t mac_japanese_uni2_page00[][2] = { + /* 0x00a */ { 0x0201, 1 }, +}; + +static const uint16_t mac_japanese_uni2_page20[][2] = { + /* 0x201 */ { 0x0030, 3 }, { 0x0000, 0 }, { 0x4000, 5 }, + /* 0x204 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x208 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x20c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x210 */ { 0x0200, 6 }, { 0x0048, 7 }, { 0x0006, 9 }, { 0x0000, 0 }, + /* 0x214 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0fff, 11 }, { 0x0fff, 23 }, + /* 0x218 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x21c */ { 0x0070, 35 }, { 0x0000, 0 }, { 0x03c0, 38 }, { 0x0000, 0 }, + /* 0x220 */ { 0x0000, 0 }, { 0x8000, 42 }, { 0x4000, 43 }, { 0x0000, 0 }, + /* 0x224 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x228 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x8000, 44 }, +}; + +static const uint16_t mac_japanese_uni2_page24[][2] = { + /* 0x246 */ { 0xffff, 45 }, { 0xffff, 61 }, + /* 0x248 */ { 0xffff, 77 }, { 0xf001, 93 }, { 0xffff, 98 }, { 0x003f, 114 }, +}; + +static const uint16_t mac_japanese_uni2_page26[][2] = { + /* 0x260 */ { 0x4000, 120 }, { 0xf000, 121 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x264 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x00ff, 125 }, { 0x0000, 0 }, + /* 0x268 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x26c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x270 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x274 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x7fc0, 133 }, +}; + +static const uint16_t mac_japanese_uni2_page30[][2] = { + /* 0x300 */ { 0x0010, 142 }, { 0xa000, 143 }, { 0x0001, 145 }, { 0x0000, 0 }, + /* 0x304 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x308 */ { 0x0000, 0 }, { 0x0010, 146 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x30c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0780, 147 }, +}; + +static const uint16_t mac_japanese_uni2_page32[][2] = { + /* 0x322 */ { 0xfc00, 151 }, { 0xffff, 157 }, + /* 0x324 */ { 0x000d, 173 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x328 */ { 0x0000, 0 }, { 0x6340, 176 }, { 0x03f0, 181 }, { 0x0000, 0 }, + /* 0x32c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x330 */ { 0x2029, 187 }, { 0x4170, 191 }, { 0x0ccc, 196 }, { 0x0a4a, 202 }, + /* 0x334 */ { 0x6684, 207 }, { 0x0082, 213 }, { 0x0000, 0 }, { 0xf800, 215 }, + /* 0x338 */ { 0xc0e0, 220 }, { 0xf1c1, 225 }, { 0x0037, 233 }, { 0x000f, 238 }, + /* 0x33c */ { 0x2810, 242 }, { 0x0010, 245 }, +}; + +static const uint16_t mac_japanese_uni2_pagee0[][2] = { + /* 0xe00 */ { 0xffff, 246 }, { 0xffff, 262 }, { 0x0fff, 278 }, { 0x001f, 290 }, + /* 0xe04 */ { 0x7f00, 295 }, +}; + +static const uint16_t mac_japanese_uni2_pagefe[][2] = { + /* 0xfe3 */ { 0xffeb, 302 }, + /* 0xfe4 */ { 0x001f, 316 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xfe8 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xfec */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xff0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x1000, 321 }, +}; + +static const cjk_index_t mac_japanese_uni2_index[] = { + { { 0x00a0, 0x00af }, mac_japanese_uni2_page00 }, + { { 0x2010, 0x22bf }, mac_japanese_uni2_page20 }, + { { 0x2460, 0x24bf }, mac_japanese_uni2_page24 }, + { { 0x2600, 0x277f }, mac_japanese_uni2_page26 }, + { { 0x3000, 0x30ff }, mac_japanese_uni2_page30 }, + { { 0x3220, 0x33df }, mac_japanese_uni2_page32 }, + { { 0xe000, 0xe04f }, mac_japanese_uni2_pagee0 }, + { { 0xfe30, 0xff3f }, mac_japanese_uni2_pagefe }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_japanese_uni2_charset[] = { + 0x0080, 0x00a0, 0x00fd, 0x815c, 0xffff, 0xffff, 0x8656, 0x8650, + 0x869b, 0x869d, 0x00fe, 0x859f, 0x85a0, 0x85a1, 0x85a2, 0x85a3, + 0x85a4, 0x85a5, 0x85a6, 0x85a7, 0x85a8, 0x85a9, 0x85aa, 0x85b3, + 0x85b4, 0x85b5, 0x85b6, 0x85b7, 0x85b8, 0x85b9, 0x85ba, 0x85bb, + 0x85bc, 0x85bd, 0x85be, 0x86cc, 0x86cd, 0x86cb, 0x86d0, 0x86d1, + 0x86cf, 0x86d2, 0x8841, 0x8840, 0x8842, 0x8540, 0x8541, 0x8542, + 0x8543, 0x8544, 0x8545, 0x8546, 0x8547, 0x8548, 0x8549, 0x854a, + 0x854b, 0x854c, 0x854d, 0x854e, 0x854f, 0x8550, 0x8551, 0x8552, + 0x8553, 0x855e, 0x855f, 0x8560, 0x8561, 0x8562, 0x8563, 0x8564, + 0x8565, 0x8566, 0x8567, 0x8568, 0x8569, 0x856a, 0x856b, 0x856c, + 0x856d, 0x856e, 0x856f, 0x8570, 0x8571, 0x8592, 0x8593, 0x8594, + 0x8595, 0x8596, 0x8597, 0x8598, 0x8599, 0x859a, 0x85db, 0x85dc, + 0x85dd, 0x85de, 0x85df, 0x85e0, 0x85e1, 0x85e2, 0x85e3, 0x85e4, + 0x85e5, 0x85e6, 0x85e7, 0x85e8, 0x85e9, 0x85ea, 0x85eb, 0x85ec, + 0x85ed, 0x85ee, 0x85ef, 0x85f0, 0x85f1, 0x85f2, 0x85f3, 0x85f4, + 0x86b4, 0x86c8, 0x86c9, 0x86c7, 0x86ca, 0x86a3, 0x86a1, 0x86a2, + 0x86a4, 0x869f, 0x86a5, 0x86a6, 0x86a0, 0x857c, 0x857d, 0x857e, + 0x8580, 0x8581, 0x8582, 0x8583, 0x8584, 0x8585, 0x86b5, 0x8854, + 0x8855, 0x86b3, 0x8868, 0x886a, 0x886b, 0x886c, 0x886d, 0x8741, + 0x8742, 0x8743, 0x8744, 0x8745, 0x8746, 0x8740, 0x874d, 0x8750, + 0x8753, 0x874f, 0x8754, 0x8752, 0x8748, 0x8758, 0x874b, 0x874c, + 0x8751, 0x8755, 0x8756, 0x874e, 0x8757, 0x8747, 0x8749, 0x874a, + 0x8799, 0x879b, 0x879e, 0x879a, 0x879c, 0x8793, 0x8794, 0x8795, + 0x8796, 0x8797, 0x8798, 0x87bd, 0x87a7, 0x87a4, 0x87b0, 0x87a2, + 0x87aa, 0x87a3, 0x87a9, 0x87be, 0x87a0, 0x87b2, 0x87b3, 0x87ab, + 0x87bf, 0x87b5, 0x87c0, 0x87a5, 0x87a8, 0x87ae, 0x87b4, 0x87b1, + 0x87c1, 0x879f, 0x87ad, 0x87a1, 0x87a6, 0x87ac, 0x87af, 0x87e8, + 0x87e7, 0x87e6, 0x87e5, 0x87fa, 0x865a, 0x865b, 0x865c, 0x864a, + 0x864c, 0x8659, 0x864e, 0x864f, 0x8651, 0x8640, 0x8642, 0x8648, + 0x8641, 0x8643, 0x8646, 0x8649, 0x8644, 0x8647, 0x8655, 0x8654, + 0x8653, 0x8652, 0x864d, 0x8658, 0x869c, 0x8657, 0xeb5d, 0xeb61, + 0xeb63, 0x00ff, 0x86d4, 0x86d5, 0x86d3, 0x86d6, 0xeb41, 0xeb42, + 0xeb60, 0xec9f, 0xeca1, 0xeca3, 0xeca5, 0xeca7, 0xecc1, 0xece1, + 0xece3, 0xece5, 0xecec, 0xed40, 0xed42, 0xed44, 0xed46, 0xed48, + 0xed62, 0xed83, 0xed85, 0xed87, 0xed8e, 0xed95, 0xed96, 0xeb5b, + 0x8791, 0x8792, 0x879d, 0x85ab, 0x85bf, 0x87fb, 0x87fc, 0x869e, + 0x85ac, 0x85c0, 0x8591, 0x865d, 0x85ad, 0x85c1, 0x86ce, 0xeb81, + 0xeb6d, 0xeb6e, 0x864b, 0x8645, 0xeb62, 0xeb50, 0xeb64, 0xeb5c, + 0xeb51, 0xeb69, 0xeb6a, 0xeb6f, 0xeb70, 0xeb6b, 0xeb6c, 0xeb79, + 0xeb7a, 0xeb73, 0xeb74, 0xeb71, 0xeb72, 0xeb75, 0xeb76, 0xeb77, + 0xeb78, 0x815f, +}; + +static const uint16_t mac_japanese_2uni_page00[][2] = { + /* 0x008 */ { 0x0001, 0 }, { 0x0000, 0 }, { 0x0001, 1 }, { 0x0000, 0 }, + /* 0x00c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0xe000, 2 }, +}; + +static const uint16_t mac_japanese_2uni_page81[][2] = { + /* 0x815 */ { 0x9000, 5 }, +}; + +static const uint16_t mac_japanese_2uni_page85[][2] = { + /* 0x854 */ { 0xffff, 7 }, { 0xc00f, 23 }, { 0xffff, 29 }, { 0x7003, 45 }, + /* 0x858 */ { 0x003f, 50 }, { 0x87fe, 56 }, { 0x3fff, 67 }, { 0xfff8, 81 }, + /* 0x85c */ { 0x0003, 94 }, { 0xf800, 96 }, { 0xffff, 101 }, { 0x001f, 117 }, + /* 0x860 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x864 */ { 0xffff, 122 }, { 0x3fff, 138 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x868 */ { 0x0000, 0 }, { 0xf800, 152 }, { 0x007f, 157 }, { 0x0038, 164 }, + /* 0x86c */ { 0xff80, 167 }, { 0x007f, 176 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x870 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x874 */ { 0xffff, 183 }, { 0x01ff, 199 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x878 */ { 0x0000, 0 }, { 0xfffe, 208 }, { 0xffff, 223 }, { 0xe03f, 239 }, + /* 0x87c */ { 0x0003, 248 }, { 0x0000, 0 }, { 0x01e0, 250 }, { 0x1c00, 254 }, + /* 0x880 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x884 */ { 0x0007, 257 }, { 0x0030, 260 }, { 0x3d00, 262 }, +}; + +static const uint16_t mac_japanese_2uni_pageeb[][2] = { + /* 0xeb4 */ { 0x0006, 267 }, { 0x3803, 269 }, { 0xfe1f, 274 }, { 0x07ff, 286 }, + /* 0xeb8 */ { 0x0002, 297 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xebc */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xec0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xec4 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xec8 */ { 0x0000, 0 }, { 0x8000, 298 }, { 0x00aa, 299 }, { 0x0000, 0 }, + /* 0xecc */ { 0x0002, 303 }, { 0x0000, 0 }, { 0x102a, 304 }, { 0x0000, 0 }, + /* 0xed0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xed4 */ { 0x0155, 308 }, { 0x0000, 0 }, { 0x0004, 313 }, { 0x0000, 0 }, + /* 0xed8 */ { 0x40a8, 314 }, { 0x0060, 318 }, +}; + +static const cjk_index_t mac_japanese_2uni_index[] = { + { { 0x0080, 0x00ff }, mac_japanese_2uni_page00 }, + { { 0x8150, 0x815f }, mac_japanese_2uni_page81 }, + { { 0x8540, 0x886f }, mac_japanese_2uni_page85 }, + { { 0xeb40, 0xed9f }, mac_japanese_2uni_pageeb }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_japanese_2uni_charset[] = { + 0x005c, 0x00a0, 0x00a9, 0x2122, 0xe003, 0x2014, 0xff3c, 0x2460, + 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, + 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, + 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, + 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, 0x2480, + 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, 0x2776, + 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, 0x277d, 0x277e, + 0xe030, 0x2488, 0x2489, 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, + 0x248f, 0x2490, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, + 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, 0xe025, 0xe02a, + 0xe032, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, + 0x2177, 0x2178, 0x2179, 0x217a, 0x217b, 0xe026, 0xe02b, 0xe033, + 0x249c, 0x249d, 0x249e, 0x249f, 0x24a0, 0x24a1, 0x24a2, 0x24a3, + 0x24a4, 0x24a5, 0x24a6, 0x24a7, 0x24a8, 0x24a9, 0x24aa, 0x24ab, + 0x24ac, 0x24ad, 0x24ae, 0x24af, 0x24b0, 0x24b1, 0x24b2, 0x24b3, + 0x24b4, 0x24b5, 0x339c, 0x339f, 0x339d, 0x33a0, 0x33a4, 0xe04c, + 0x33a1, 0x33a5, 0x339e, 0x33a2, 0x338e, 0xe04b, 0x338f, 0x33c4, + 0x3396, 0x3397, 0x2113, 0x3398, 0x33b3, 0x33b2, 0x33b1, 0x33b0, + 0x2109, 0x33d4, 0x33cb, 0x3390, 0x3385, 0x3386, 0x3387, 0xe031, + 0x2116, 0x33cd, 0x2121, 0xe029, 0x2664, 0x2667, 0x2661, 0x2662, + 0x2660, 0x2663, 0x2665, 0x2666, 0x3020, 0x260e, 0x3004, 0x261e, + 0x261c, 0x261d, 0x261f, 0x21c6, 0x21c4, 0x21c5, 0xe034, 0x21e8, + 0x21e6, 0x21e7, 0x21e9, 0xe006, 0xe004, 0xe005, 0xe007, 0x3230, + 0x322a, 0x322b, 0x322c, 0x322d, 0x322e, 0x322f, 0x3240, 0x3237, + 0x3242, 0x3243, 0x3239, 0x323a, 0x3231, 0x323e, 0x3234, 0x3232, + 0x323b, 0x3236, 0x3233, 0x3235, 0x323c, 0x323d, 0x323f, 0x3238, + 0xe022, 0xe023, 0x32a4, 0x32a5, 0x32a6, 0x32a7, 0x32a8, 0x32a9, + 0x3296, 0x329d, 0x3298, 0x329e, 0xe024, 0x3299, 0x3349, 0x3322, + 0x334d, 0x3314, 0x3316, 0x3305, 0x3333, 0x334e, 0x3303, 0x3336, + 0x3318, 0x3315, 0x3327, 0x3351, 0x334a, 0x3339, 0x3357, 0x330d, + 0x3342, 0x3323, 0x3326, 0x333b, 0x332b, 0x3300, 0x331e, 0x332a, + 0x3331, 0x3347, 0x337e, 0x337d, 0x337c, 0x337b, 0x337f, 0xe027, + 0xe028, 0x222e, 0x221f, 0x22bf, 0x301d, 0x301f, 0x3094, 0x30f7, + 0x30f8, 0x30f9, 0x30fa, 0xe008, 0xe009, 0xe04e, 0xfe33, 0xe021, + 0xfe31, 0xe000, 0xe00a, 0xe001, 0xe04d, 0xe002, 0xfe30, 0xfe35, + 0xfe36, 0xfe39, 0xfe3a, 0xe049, 0xe04a, 0xfe37, 0xfe38, 0xfe3f, + 0xfe40, 0xfe3d, 0xfe3e, 0xfe41, 0xfe42, 0xfe43, 0xfe44, 0xfe3b, + 0xfe3c, 0xe048, 0xe00b, 0xe00c, 0xe00d, 0xe00e, 0xe00f, 0xe010, + 0xe011, 0xe012, 0xe013, 0xe014, 0xe015, 0xe016, 0xe017, 0xe018, + 0xe019, 0xe01a, 0xe01b, 0xe01c, 0xe01d, 0xe01e, 0xe01f, 0xe020, +}; + +static const uint32_t mac_japanese_compose[] = { + 0x2010f87e, 0x2016f87e, 0x2026f87e, 0x2026f87f, + 0x21e6f87a, 0x21e7f87a, 0x21e8f87a, 0x21e9f87a, + 0x3001f87e, 0x3002f87e, 0x301cf87e, 0x3041f87e, + 0x3043f87e, 0x3045f87e, 0x3047f87e, 0x3049f87e, + 0x3063f87e, 0x3083f87e, 0x3085f87e, 0x3087f87e, + 0x308ef87e, 0x30a1f87e, 0x30a3f87e, 0x30a5f87e, + 0x30a7f87e, 0x30a9f87e, 0x30c3f87e, 0x30e3f87e, + 0x30e5f87e, 0x30e7f87e, 0x30eef87e, 0x30f5f87e, + 0x30f6f87e, 0x30fcf87e, 0x592720dd, 0x5c0f20dd, + 0x63a720dd, 0xe02c0049, 0xe02d0069, 0xe02e793e, + 0xe02f4eba, 0xe0350058, 0xe0360056, 0xe0370076, + 0xe0380049, 0xe0390069, 0xe03a4f1a, 0xe03b6cd5, + 0xe03c002e, 0xe03d0042, 0xe03e0056, 0xe03f0076, + 0xe0402191, 0xe0410041, 0xe0420049, 0xe0430069, + 0xe0440049, 0xe0450069, 0xe0469650, 0xe04756e3, + 0xf8600030, 0xf8600054, 0xf8600058, 0xf8600078, + 0xf8602193, 0xf8610046, 0xf8610058, 0xf8610078, + 0xf8620058, 0xf8620078, 0xf8626709, 0xf8628ca1, + 0xff1df87e, 0xff3bf87e, 0xff3df87e, 0xff47f87f, + 0xff4df87f, 0xff5cf87e, 0xffe3f87e, +}; diff --git a/libatalk/unicode/charsets/mac_korean.c b/libatalk/unicode/charsets/mac_korean.c new file mode 100644 index 0000000..26f387d --- /dev/null +++ b/libatalk/unicode/charsets/mac_korean.c @@ -0,0 +1,126 @@ +/* + * MacKorean + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include + +#if HAVE_USABLE_ICONV + +#include "generic_cjk.h" +#include "mac_korean.h" + +static size_t mac_korean_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_korean_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_korean = { + "MAC_KOREAN", + 3, + mac_korean_pull, + mac_korean_push, + CHARSET_ICONV | CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED | CHARSET_CLIENT, + "EUC-KR", + NULL, NULL +}; + +static size_t mac_korean_char_push(uint8_t* out, const ucs2_t* in, size_t* size) +{ + ucs2_t wc = in[0]; + + if ((wc & ~7) == 0xf860) { + wc = cjk_compose_seq(in, size, mac_korean_compose, + sizeof(mac_korean_compose) / sizeof(uint32_t)); + if (!wc) return (size_t)-1; + } else if ((wc & 0xf000) == 0xe000) { + *size = 1; + return 0; + } else if (*size >= 2) { + ucs2_t comb = in[1]; + size_t n = 1; + + while ((comb & ~15) == 0xf870 || + (comb >= 0x0300 && comb <= 0x036f) || + (comb >= 0x20d0 && comb <= 0x20ea)) { + ucs2_t comp = cjk_compose(wc, comb, mac_korean_compose, + sizeof(mac_korean_compose) / sizeof(uint32_t)); + if (!comp) break; + wc = comp; + if (++n == *size) break; + comb = in[n]; + } + *size = n; + } else { + *size = 1; + } + if (wc <= 0x7f) { + out[0] = (uint8_t)wc; + return 1; + } + return cjk_char_push(cjk_lookup(wc, mac_korean_uni2_index, + mac_korean_uni2_charset), out); +} + +static size_t mac_korean_push(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_push(mac_korean_char_push, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +static size_t mac_korean_char_pull(ucs2_t* out, const uint8_t* in, size_t* size) +{ + uint16_t c = in[0]; + + if (c <= 0x7f) { + *size = 1; + *out = c; + return 1; + } else if (c >= 0xa1 && c <= 0xfe) { + if (*size >= 2) { + uint8_t c2 = in[1]; + if ((c2 >= 0x41 && c2 <= 0x7d) || (c2 >= 0x81 && c2 <= 0xfe)) { + *size = 2; + c = (c << 8) + c2; + } else { + errno = EILSEQ; + return (size_t)-1; + } + } else { + errno = EINVAL; + return (size_t)-1; + } + } else { + *size = 1; + } + return cjk_char_pull(cjk_lookup(c, mac_korean_2uni_index, + mac_korean_2uni_charset), + out, mac_korean_compose); +} + +static size_t mac_korean_pull(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return cjk_generic_pull(mac_korean_char_pull, + cd, inbuf, inbytesleft, outbuf, outbytesleft); +} +#endif diff --git a/libatalk/unicode/charsets/mac_korean.h b/libatalk/unicode/charsets/mac_korean.h new file mode 100644 index 0000000..2febaa2 --- /dev/null +++ b/libatalk/unicode/charsets/mac_korean.h @@ -0,0 +1,771 @@ +/* + * MacKorean + * Copyright (C) TSUBAKIMOTO Hiroya 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Reference + * http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ + */ + +static const uint16_t mac_korean_uni2_page00[][2] = { + /* 0x00a */ { 0x7a2d, 0 }, { 0x0880, 9 }, +}; + +static const uint16_t mac_korean_uni2_page02[][2] = { + /* 0x02b */ { 0x1000, 11 }, + /* 0x02c */ { 0x0000, 0 }, { 0x1001, 12 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x030 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x034 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x038 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x03c */ { 0x0000, 0 }, { 0x0020, 14 }, +}; + +static const uint16_t mac_korean_uni2_page20[][2] = { + /* 0x201 */ { 0x8878, 15 }, { 0x0004, 21 }, { 0x5670, 22 }, + /* 0x204 */ { 0x7284, 29 }, { 0x0002, 35 }, { 0x0000, 0 }, { 0x7c00, 36 }, + /* 0x208 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x1200, 41 }, { 0x0000, 0 }, + /* 0x20c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x210 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x214 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x218 */ { 0x0000, 0 }, { 0x3000, 43 }, { 0x0000, 0 }, { 0x10df, 45 }, + /* 0x21c */ { 0xa031, 53 }, { 0x0001, 58 }, { 0x03cf, 59 }, { 0x0001, 67 }, + /* 0x220 */ { 0x1240, 68 }, { 0x8008, 71 }, { 0x0064, 73 }, { 0x1080, 76 }, + /* 0x224 */ { 0x0128, 78 }, { 0x040b, 81 }, { 0xccc4, 85 }, { 0x0ecf, 92 }, + /* 0x228 */ { 0x0033, 101 }, { 0x02e0, 105 }, { 0x0018, 109 }, { 0x1800, 111 }, + /* 0x22c */ { 0xc000, 113 }, { 0x0c00, 115 }, { 0x4000, 117 }, { 0x0000, 0 }, + /* 0x230 */ { 0x0040, 118 }, { 0x0010, 119 }, +}; + +static const uint16_t mac_korean_uni2_page24[][2] = { + /* 0x246 */ { 0x8000, 120 }, { 0x000f, 121 }, + /* 0x248 */ { 0x00f8, 125 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0xffc0, 130 }, + /* 0x24c */ { 0xffff, 140 }, { 0x0000, 0 }, { 0xf800, 156 }, { 0x001f, 161 }, + /* 0x250 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x254 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x258 */ { 0x0100, 166 }, { 0x0000, 0 }, { 0x2004, 167 }, { 0x8222, 169 }, + /* 0x25c */ { 0x3608, 173 }, { 0x0000, 0 }, { 0x8040, 178 }, { 0x1800, 180 }, + /* 0x260 */ { 0x0000, 0 }, { 0xa001, 182 }, { 0x8000, 185 }, { 0x0000, 0 }, + /* 0x264 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x8040, 186 }, { 0x0000, 0 }, + /* 0x268 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x26c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x270 */ { 0x0000, 0 }, { 0x0440, 188 }, { 0x0009, 190 }, { 0xa002, 192 }, + /* 0x274 */ { 0x2083, 195 }, { 0x0040, 199 }, { 0x0000, 0 }, { 0xffc0, 200 }, + /* 0x278 */ { 0xfc00, 210 }, { 0x581f, 216 }, { 0x0012, 224 }, { 0x0024, 226 }, +}; + +static const uint16_t mac_korean_uni2_page29[][2] = { + /* 0x293 */ { 0x02f0, 228 }, + /* 0x294 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x003c, 233 }, { 0x0000, 0 }, + /* 0x298 */ { 0x0062, 237 }, { 0x0180, 240 }, { 0x0008, 242 }, { 0xc000, 243 }, + /* 0x29c */ { 0x0100, 245 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x2a0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0040, 246 }, { 0x0100, 247 }, + /* 0x2a4 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0004, 248 }, + /* 0x2a8 */ { 0x1800, 249 }, { 0x0006, 251 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x2ac */ { 0x1860, 253 }, { 0x0000, 0 }, { 0x0100, 257 }, +}; + +static const uint16_t mac_korean_uni2_page30[][2] = { + /* 0x301 */ { 0xd3c4, 258 }, { 0x0001, 266 }, { 0x0040, 267 }, +}; + +static const uint16_t mac_korean_uni2_page32[][2] = { + /* 0x323 */ { 0x0202, 268 }, + /* 0x324 */ { 0x0000, 0 }, { 0x07fe, 270 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x328 */ { 0xfc00, 280 }, { 0x4011, 286 }, { 0x0020, 289 }, +}; + +static const uint16_t mac_korean_uni2_page33[][2] = { + /* 0x33c */ { 0x0800, 290 }, +}; + +static const uint16_t mac_korean_uni2_pagee0[][2] = { + /* 0xe00 */ { 0xffff, 291 }, { 0xffff, 307 }, { 0xffff, 323 }, { 0xffff, 339 }, + /* 0xe04 */ { 0xffff, 355 }, { 0xffff, 371 }, { 0xffff, 387 }, { 0xffff, 403 }, + /* 0xe08 */ { 0xffff, 419 }, { 0xffff, 435 }, { 0xffff, 451 }, { 0xffff, 467 }, + /* 0xe0c */ { 0xffff, 483 }, { 0xffff, 499 }, { 0xffff, 515 }, { 0xffff, 531 }, + /* 0xe10 */ { 0xffff, 547 }, { 0xffff, 563 }, { 0xffff, 579 }, { 0xffff, 595 }, + /* 0xe14 */ { 0xffff, 611 }, { 0xffff, 627 }, { 0xffff, 643 }, { 0xffff, 659 }, + /* 0xe18 */ { 0xffff, 675 }, { 0xffff, 691 }, { 0xffde, 707 }, { 0xfff7, 721 }, + /* 0xe1c */ { 0xdfff, 736 }, { 0xffbf, 751 }, { 0xffe7, 766 }, { 0xff9f, 780 }, + /* 0xe20 */ { 0xffff, 794 }, { 0xffff, 810 }, { 0xffff, 826 }, { 0xffff, 842 }, + /* 0xe24 */ { 0xffff, 858 }, { 0xffff, 874 }, { 0xffff, 890 }, { 0xffff, 906 }, + /* 0xe28 */ { 0xffff, 922 }, { 0xffff, 938 }, { 0xffff, 954 }, { 0xffff, 970 }, + /* 0xe2c */ { 0xffff, 986 }, { 0x07ff, 1002 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xe30 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0xfffc, 1013 }, + /* 0xe34 */ { 0xffff, 1027 }, { 0xffff, 1043 }, { 0xffff, 1059 }, { 0xffff, 1075 }, + /* 0xe38 */ { 0xffff, 1091 }, { 0x1fff, 1107 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xe3c */ { 0xfc00, 1120 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xe40 */ { 0x0000, 0 }, { 0x1ffc, 1126 }, +}; + +static const uint16_t mac_korean_uni2_pagef8[][2] = { + /* 0xf80 */ { 0x1fe0, 1137 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x2000, 1145 }, + /* 0xf84 */ { 0xffff, 1146 }, +}; + +static const uint16_t mac_korean_uni2_pagefe[][2] = { + /* 0xfe5 */ { 0x0600, 1162 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xfe8 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xfec */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xff0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xff4 */ { 0x0000, 0 }, { 0x4000, 1164 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xff8 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xffc */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x002f, 1165 }, +}; + +static const cjk_index_t mac_korean_uni2_index[] = { + { { 0x00a0, 0x00bf }, mac_korean_uni2_page00 }, + { { 0x02b0, 0x03df }, mac_korean_uni2_page02 }, + { { 0x2010, 0x231f }, mac_korean_uni2_page20 }, + { { 0x2460, 0x27bf }, mac_korean_uni2_page24 }, + { { 0x2930, 0x2aef }, mac_korean_uni2_page29 }, + { { 0x3010, 0x303f }, mac_korean_uni2_page30 }, + { { 0x3230, 0x32af }, mac_korean_uni2_page32 }, + { { 0x33c0, 0x33cf }, mac_korean_uni2_page33 }, + { { 0xe000, 0xe41f }, mac_korean_uni2_pagee0 }, + { { 0xf800, 0xf84f }, mac_korean_uni2_pagef8 }, + { { 0xfe50, 0xffef }, mac_korean_uni2_pagefe }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_korean_uni2_charset[] = { + 0x0080, 0xa1cb, 0xa1cc, 0xa1cd, 0x0083, 0xa65c, 0xa1fe, 0xffff, + 0xffff, 0xa1a4, 0xa65d, 0xa198, 0xa2b0, 0xa2a6, 0xa76a, 0xa1a9, + 0xa1aa, 0xffff, 0xa1ab, 0xa170, 0xa16f, 0xa655, 0xa5de, 0xadad, + 0xadab, 0xa65a, 0xa65b, 0xa784, 0xa3fe, 0xa64d, 0xa787, 0xa785, + 0xa196, 0xa197, 0xa64e, 0xa16d, 0xa171, 0xa172, 0xa17a, 0xa17c, + 0xa17d, 0x0081, 0xffff, 0xac53, 0xac52, 0xa882, 0xa87c, 0xa87b, + 0xa883, 0xa881, 0xac50, 0xac51, 0xa892, 0xa893, 0xa89e, 0xa89f, + 0xa84b, 0xa84a, 0xa849, 0xac6a, 0xac6c, 0xac6b, 0xac6d, 0xac72, + 0xac74, 0xac73, 0xac75, 0xac41, 0xa751, 0xa773, 0xa774, 0xa75c, + 0xa753, 0xa768, 0xa755, 0xa756, 0xa2fe, 0xffff, 0xa49a, 0xa499, + 0xa49b, 0xa769, 0xa759, 0xa758, 0xa777, 0xa764, 0xa75a, 0xa75b, + 0xa1ec, 0xa1ed, 0xa76f, 0xa770, 0xa487, 0xa488, 0xa489, 0xa48a, + 0xa48f, 0xa490, 0xa491, 0xa481, 0xa482, 0xa485, 0xa486, 0xa772, + 0xa771, 0xa75d, 0xa75e, 0xa75f, 0xffff, 0xa76c, 0xa49d, 0xa775, + 0xa776, 0xa483, 0xa484, 0xa492, 0xa493, 0xa2fd, 0xa778, 0xa761, + 0xa7f0, 0xa7f1, 0xa7f2, 0xa7f3, 0xa7f4, 0xaaf4, 0xaaf5, 0xaaf6, + 0xaaf7, 0xaaf8, 0xa386, 0xa387, 0xa388, 0xa389, 0xa38a, 0xa38b, + 0xa38c, 0xa38d, 0xa38e, 0xa38f, 0xa390, 0xa391, 0xa392, 0xa393, + 0xa394, 0xa395, 0xa396, 0xa397, 0xa398, 0xa399, 0xa39a, 0xa39b, + 0xa39c, 0xa39d, 0xa39e, 0xa39f, 0xa6ef, 0xa6f0, 0xa6f1, 0xa6f2, + 0xa6f3, 0xa6f4, 0xa6f5, 0xa6f6, 0xa6f7, 0xa6f8, 0xa78f, 0xa678, + 0xa74a, 0xa766, 0xa795, 0xa796, 0xa794, 0xa797, 0xa2c1, 0xa79c, + 0xa675, 0xa684, 0xa790, 0xa66f, 0xa746, 0xa79a, 0xa677, 0xac8d, + 0xac8e, 0xa693, 0xa798, 0xa648, 0xa66d, 0xa66c, 0xa688, 0xa672, + 0xa653, 0xa652, 0xa67c, 0xa699, 0xa68d, 0xa654, 0xa683, 0xa673, + 0xa6e5, 0xa6e6, 0xa6e7, 0xa6e8, 0xa6e9, 0xa6ea, 0xa6eb, 0xa6ec, + 0xa6ed, 0xa6ee, 0xa355, 0xa356, 0xa357, 0xa358, 0xa359, 0xa35a, + 0xa35b, 0xa35c, 0xa35d, 0xa35e, 0xac5e, 0xa86a, 0xa860, 0xa878, + 0xa874, 0xac48, 0xa85c, 0xac43, 0xa88d, 0xa889, 0xa886, 0xa88b, + 0xa88c, 0xa86f, 0xa871, 0xa870, 0xa872, 0xa799, 0xa159, 0xa15a, + 0xa199, 0xa19a, 0xa49c, 0xa668, 0xa66e, 0xa664, 0xa47d, 0xa760, + 0xa77b, 0xa494, 0xa495, 0xa496, 0xa497, 0xa48b, 0xa48d, 0xa48c, + 0xa48e, 0xa76b, 0xa742, 0xa15d, 0xa15e, 0xa15f, 0xa160, 0xa1ad, + 0xada9, 0xadaa, 0xa69e, 0xa743, 0xa79d, 0xa79e, 0xa7f5, 0xa7f6, + 0xa7f7, 0xa7f8, 0xa7f9, 0xa7fa, 0xa7fb, 0xa7fc, 0xa7fd, 0xa7fe, + 0xad71, 0xad72, 0xad73, 0xad74, 0xad75, 0xad76, 0xad70, 0xab5c, + 0xa782, 0xab6c, 0xa79f, 0xa18a, 0xadb0, 0xa157, 0xa24b, 0xa158, + 0xa24c, 0xa16c, 0xa767, 0xa541, 0xa542, 0xa543, 0xa544, 0xa545, + 0xa546, 0xa547, 0xa548, 0xa549, 0xa54a, 0xa179, 0xa765, 0xa762, + 0xa178, 0xa183, 0xa161, 0xa163, 0xa184, 0xa162, 0xa164, 0xa181, + 0xa182, 0xa647, 0xa176, 0xa2fa, 0xa173, 0x0082, 0xa2fb, 0xa2fc, + 0xa16b, 0xa169, 0xa643, 0xa167, 0xa16a, 0xa168, 0x00ff, 0xadae, + 0xa5dc, 0xadac, 0xa5dd, 0xa786, 0xa651, 0xa64f, 0xa64b, 0xa1a0, + 0xa19d, 0xa690, 0xac89, 0xa869, 0xa86b, 0xac5d, 0xac66, 0xa863, + 0xac62, 0xa853, 0xac55, 0xa842, 0xa84e, 0xa85f, 0xac8b, 0xa86d, + 0xac60, 0xac68, 0xa865, 0xac64, 0xa855, 0xac57, 0xa843, 0xa84f, + 0xa861, 0xac8a, 0xa86c, 0xac67, 0xa864, 0xac63, 0xa854, 0xac56, + 0xa841, 0xa84d, 0xac8c, 0xa86e, 0xac61, 0xac69, 0xa866, 0xac65, + 0xa856, 0xac58, 0xa844, 0xa850, 0xa862, 0xa851, 0xa852, 0xa845, + 0xa846, 0xa847, 0xa848, 0xac7a, 0xac85, 0xa88a, 0xac77, 0xac82, + 0xa887, 0xac78, 0xa87d, 0xac83, 0xa888, 0xa899, 0xac4d, 0xa898, + 0xac4c, 0xa89b, 0xa89a, 0xa895, 0xa84c, 0xa85b, 0xa857, 0xac47, + 0xa897, 0xac6e, 0xada6, 0xa88e, 0xa873, 0xa877, 0xac59, 0xac4f, + 0xa85d, 0xa859, 0xac70, 0xada7, 0xa890, 0xa875, 0xa879, 0xac5b, + 0xadaf, 0xa858, 0xac46, 0xa896, 0xac6f, 0xada5, 0xa88f, 0xac5a, + 0xac4e, 0xa85e, 0xa85a, 0xac71, 0xada8, 0xa891, 0xa876, 0xa87a, + 0xac5c, 0xa752, 0xa188, 0xa189, 0xa177, 0xa174, 0xa498, 0xa49e, + 0xa185, 0xa757, 0xa186, 0xa754, 0xa779, 0xa175, 0xa17b, 0xa76e, + 0xa763, 0xa187, 0xa76d, 0xa77a, 0xa748, 0xa54c, 0xa54d, 0xa54e, + 0xa54f, 0xa550, 0xa551, 0xa552, 0xa553, 0xa554, 0xa54b, 0xa473, + 0xa35f, 0xa474, 0xa360, 0xa475, 0xa361, 0xa476, 0xa362, 0xa477, + 0xa363, 0xa478, 0xa364, 0xa479, 0xa365, 0xa47a, 0xa366, 0xa47b, + 0xa367, 0xa47c, 0xa368, 0xa656, 0xa659, 0xa78d, 0xa78e, 0xa78c, + 0xa68a, 0xa749, 0xa66b, 0xa66a, 0xa745, 0xa79b, 0xa665, 0xa78b, + 0xa662, 0xa657, 0xa789, 0xa78a, 0xa788, 0xa74e, 0xa689, 0xa682, + 0xa791, 0xa792, 0xa744, 0xa669, 0xa793, 0xa670, 0xa671, 0xa676, + 0xa65e, 0xac8f, 0xa65f, 0xac90, 0xa698, 0xa697, 0xa741, 0xa687, + 0xa679, 0xa67b, 0xa69b, 0xa67a, 0xa68e, 0xa469, 0xa46a, 0xa46b, + 0xa46c, 0xa46d, 0xa46e, 0xa46f, 0xa470, 0xa471, 0xa472, 0xa685, + 0xac7d, 0xac88, 0xa885, 0xac79, 0xac84, 0xac76, 0xac81, 0xac7b, + 0xac86, 0xac7c, 0xac87, 0xa884, 0xac45, 0xac44, 0xa243, 0xa241, + 0xa153, 0xa165, 0xa155, 0xa151, 0xa244, 0xa242, 0xa154, 0xa166, + 0xa156, 0xa152, 0xa667, 0xa49f, 0xa5db, 0xa18b, 0xa14b, 0xa14c, + 0xa149, 0xa14a, 0xada1, 0xa143, 0xa145, 0xa141, 0xada2, 0xa144, + 0xa146, 0xa142, 0xada3, 0xa147, 0xada4, 0xa148, 0xa249, 0xa15b, + 0xa24a, 0xa15c, 0xa67d, 0xa247, 0xa248, 0xa6f9, 0xa6fa, 0xa6fb, + 0xa6fc, 0xa6fd, 0xa6fe, 0xa5f9, 0xa5fa, 0xa5fb, 0xa5fc, 0xa783, + 0xad55, 0xa18c, 0xad5b, 0xa192, 0xad57, 0xa18e, 0xad5d, 0xa194, + 0xad56, 0xa18d, 0xad59, 0xa190, 0xab6d, 0xaa6e, 0xab5a, 0xaa5a, + 0xaa66, 0xad5c, 0xa193, 0xad5a, 0xa191, 0xaa9f, 0xaa58, 0xa750, + 0xa74f, 0xab60, 0xaa69, 0xab5e, 0xaa62, 0xab63, 0xaa6c, 0xab5b, + 0xaa5c, 0xad5e, 0xa195, 0xa692, 0xab44, 0xaa54, 0xab65, 0xab5d, + 0xaa5f, 0xaa5d, 0xad58, 0xa18f, 0xab6b, 0xad6f, 0xaa68, 0xaa63, + 0xab69, 0xaa70, 0xaa65, 0xab58, 0xaa57, 0xab59, 0xaa6d, 0xab62, + 0xaa6b, 0xab67, 0xad69, 0xad6a, 0xad6d, 0xab46, 0xab66, 0xaa61, + 0xad6c, 0xab64, 0xaa6f, 0xaa67, 0xad6b, 0xab68, 0xaa5e, 0xaa59, + 0xaa6a, 0xab5f, 0xab45, 0xaa60, 0xa77c, 0xaa55, 0xaa64, 0xad6e, + 0xab6a, 0xab61, 0xaa5b, 0xab75, 0xab55, 0xab43, 0xaa50, 0xab56, + 0xab47, 0xaa96, 0xaa9e, 0xab42, 0xab76, 0xaa8c, 0xaa8b, 0xab77, + 0xac91, 0xab48, 0xaa42, 0xaa8e, 0xaa45, 0xaa94, 0xaa4b, 0xaa53, + 0xaa81, 0xaa82, 0xaa8d, 0xaa44, 0xaa83, 0xaa97, 0xaa4d, 0xab49, + 0xaa9a, 0xaa90, 0xaa47, 0xaa95, 0xaa4c, 0xab6e, 0xaa84, 0xab4a, + 0xab4b, 0xac93, 0xaa98, 0xaa93, 0xaa4a, 0xaa9c, 0xab6f, 0xab4c, + 0xab57, 0xaa85, 0xaa9b, 0xaa51, 0xab4d, 0xab4e, 0xaa56, 0xab53, + 0xaa41, 0xab4f, 0xaa9d, 0xab71, 0xab72, 0xac96, 0xaa99, 0xaa52, + 0xac95, 0xab70, 0xaa86, 0xaa4e, 0xab50, 0xaa91, 0xaa48, 0xaa92, + 0xaa49, 0xab41, 0xaa71, 0xaa7d, 0xaa43, 0xab51, 0xac94, 0xab73, + 0xaa87, 0xac92, 0xaa88, 0xab52, 0xaa89, 0xaa4f, 0xaa8a, 0xab74, + 0xab78, 0xaa8f, 0xaa46, 0xab54, 0xac97, 0xacc2, 0xa455, 0xa341, + 0xa2e6, 0xa441, 0xacc3, 0xa456, 0xa342, 0xa2e7, 0xa442, 0xacc4, + 0xa457, 0xa343, 0xa2e8, 0xa443, 0xacc5, 0xa458, 0xa344, 0xa2e9, + 0xa444, 0xacc6, 0xa459, 0xa345, 0xa2ea, 0xa445, 0xacc7, 0xa45a, + 0xa346, 0xa2eb, 0xa446, 0xacc8, 0xa45b, 0xa347, 0xa2ec, 0xa447, + 0xacc9, 0xa45c, 0xa348, 0xa2ed, 0xa448, 0xacca, 0xa45d, 0xa349, + 0xa2ee, 0xa449, 0xa661, 0xad41, 0xad47, 0xad43, 0xad49, 0xad42, + 0xad45, 0xad48, 0xad46, 0xad4a, 0xad44, 0xad7d, 0xad77, 0xad78, + 0xad7b, 0xad7a, 0xad79, 0xaa76, 0xad7c, 0xab9b, 0xaa77, 0xab9c, + 0xab99, 0xab98, 0xab97, 0xab9d, 0xab8a, 0xab87, 0xaa73, 0xaa75, + 0xab9e, 0xab79, 0xaa72, 0xab7a, 0xab9a, 0xab89, 0xab86, 0xab88, + 0xab7b, 0xab8b, 0xab8c, 0xab7c, 0xab8d, 0xaa78, 0xab8e, 0xaa7c, + 0xab9f, 0xab8f, 0xab90, 0xaa79, 0xab91, 0xab7d, 0xaa7a, 0xab92, + 0xab93, 0xaa74, 0xab94, 0xab81, 0xab82, 0xab83, 0xab84, 0xab95, + 0xab85, 0xab96, 0xaa7b, 0xaaf9, 0xaafa, 0xaafb, 0xaafc, 0xaafd, + 0xaafe, 0xabf7, 0xabf8, 0xabf9, 0xabfa, 0xa44a, 0xa44b, 0xa44c, + 0xa44d, 0xa44e, 0xa44f, 0xa450, 0xa451, 0xa452, 0xa453, 0xa454, + 0xad68, 0xad5f, 0xad65, 0xad61, 0xad67, 0xad60, 0xad63, 0xad66, + 0xad64, 0xad62, 0xa77d, 0xa2ef, 0xa2f0, 0xa2f1, 0xa2f2, 0xa2f3, + 0xa2f4, 0xa2f5, 0xa2f6, 0xa2f7, 0xa2f8, 0xa2f9, 0xad54, 0xad4b, + 0xad51, 0xad4d, 0xad53, 0xad4c, 0xad4f, 0xad52, 0xad50, 0xad4e, + 0xa781, 0xa34a, 0xa34b, 0xa34c, 0xa34d, 0xa34e, 0xa34f, 0xa350, + 0xa351, 0xa352, 0xa353, 0xa354, 0xa45e, 0xa45f, 0xa460, 0xa461, + 0xa462, 0xa463, 0xa464, 0xa465, 0xa466, 0xa467, 0xa468, 0xaccb, + 0xaccc, 0xaccd, 0xacce, 0xaccf, 0xacd0, 0xacf2, 0xacf3, 0xacf4, + 0xacf5, 0xacf6, 0xa369, 0xa36a, 0xa36b, 0xa36c, 0xa36d, 0xa36e, + 0xa36f, 0xa370, 0xa371, 0xa372, 0xa373, 0xa374, 0xa375, 0xa376, + 0xa377, 0xa378, 0xa379, 0xa37a, 0xa37b, 0xa37c, 0xa37d, 0xa381, + 0xa382, 0xa383, 0xa384, 0xa385, 0xa646, 0xa64c, 0xa555, 0xa941, + 0xa556, 0xa942, 0xa557, 0xa943, 0xa558, 0xa944, 0xa559, 0xa945, + 0xa55a, 0xa946, 0xa55b, 0xa947, 0xa55c, 0xa948, 0xa55d, 0xa949, + 0xa55e, 0xa94a, 0xa55f, 0xa94b, 0xa560, 0xa94c, 0xa561, 0xa94d, + 0xa562, 0xa94e, 0xa563, 0xa94f, 0xa564, 0xa950, 0xa565, 0xa951, + 0xa566, 0xa952, 0xa567, 0xa953, 0xa568, 0xa954, 0xa569, 0xa955, + 0xa56a, 0xa956, 0xa56b, 0xa957, 0xa56c, 0xa958, 0xa56d, 0xa959, + 0xa56e, 0xa95a, 0xa56f, 0xa95b, 0xa570, 0xa95c, 0xa571, 0xa95d, + 0xa572, 0xa95e, 0xa573, 0xa95f, 0xa574, 0xa960, 0xa575, 0xa961, + 0xa576, 0xa962, 0xa577, 0xa963, 0xa578, 0xa964, 0xa579, 0xa965, + 0xa57a, 0xa966, 0xa57b, 0xa967, 0xa57c, 0xa968, 0xa57d, 0xa969, + 0xa581, 0xa96a, 0xa582, 0xa96b, 0xa583, 0xa96c, 0xa584, 0xa96d, + 0xa585, 0xa96e, 0xa586, 0xa96f, 0xa587, 0xa970, 0xa588, 0xa971, + 0xa589, 0xa972, 0xa58a, 0xa973, 0xa58b, 0xa974, 0xa644, 0xa645, + 0xa650, 0xa666, 0xa660, 0xa691, 0xa686, 0xa641, 0xa245, 0xa14f, + 0xa246, 0xa150, 0xa5da, 0xa19f, 0xa64a, 0xa19c, 0xa19e, 0xa649, + 0x0084, 0xa658, 0xa663, 0xa69f, 0xa68f, 0xa681, 0xa674, 0xa696, + 0xa69a, 0xa642, 0xa16e, 0xa894, 0xac54, 0xac42, 0xac49, 0xac5f, + 0xa867, 0xa868, 0xa89d, 0xa89c, 0xac4b, 0xac4a, 0xa747, 0xa74b, + 0xa74c, 0xa74d, 0xa14d, 0xa14e, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, +}; + +static const uint16_t mac_korean_2uni_page00[][2] = { + /* 0x008 */ { 0x001f, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0x00c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x8000, 5 }, +}; + +static const uint16_t mac_korean_2uni_pagea1[][2] = { + /* 0xa14 */ { 0xfffe, 6 }, { 0xffff, 21 }, { 0xffff, 37 }, { 0x3fff, 53 }, + /* 0xa18 */ { 0xfffe, 67 }, { 0xf7ff, 82 }, { 0x2e11, 97 }, { 0x0000, 0 }, + /* 0xa1c */ { 0x3800, 103 }, { 0x0000, 0 }, { 0x3000, 106 }, { 0x4000, 108 }, + /* 0xa20 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa24 */ { 0x1ffe, 109 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa28 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0040, 121 }, { 0x0001, 122 }, + /* 0xa2c */ { 0x0002, 123 }, { 0x0000, 0 }, { 0xffc0, 124 }, { 0x7fff, 134 }, + /* 0xa30 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa34 */ { 0xfffe, 149 }, { 0xffff, 164 }, { 0xffff, 180 }, { 0x3fff, 196 }, + /* 0xa38 */ { 0xfffe, 210 }, { 0xffff, 225 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa3c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x4000, 241 }, + /* 0xa40 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa44 */ { 0xfffe, 242 }, { 0xffff, 257 }, { 0xffff, 273 }, { 0x3fff, 289 }, + /* 0xa48 */ { 0xfffe, 303 }, { 0xffff, 318 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa4c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa50 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa54 */ { 0xfffe, 334 }, { 0xffff, 349 }, { 0xffff, 365 }, { 0x3fff, 381 }, + /* 0xa58 */ { 0x0ffe, 395 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa5c */ { 0x0000, 0 }, { 0x7c00, 406 }, { 0x0000, 0 }, { 0x1e00, 411 }, + /* 0xa60 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa64 */ { 0xfffe, 415 }, { 0xffff, 430 }, { 0xffff, 446 }, { 0x3fff, 462 }, + /* 0xa68 */ { 0xe7fe, 476 }, { 0xcfcf, 489 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa6c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0xffe0, 501 }, { 0x7fff, 512 }, + /* 0xa70 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa74 */ { 0xfffe, 527 }, { 0xffff, 542 }, { 0xffff, 558 }, { 0x3fff, 574 }, + /* 0xa78 */ { 0xfffe, 588 }, { 0xffff, 603 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa7c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x7fff, 619 }, + /* 0xa80 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa84 */ { 0xfffe, 634 }, { 0xffff, 649 }, { 0xffff, 665 }, { 0x3fff, 681 }, + /* 0xa88 */ { 0xfffe, 695 }, { 0xffff, 710 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa8c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa90 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa94 */ { 0xfffe, 726 }, { 0xffff, 741 }, { 0xffff, 757 }, { 0x001f, 773 }, + /* 0xa98 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xa9c */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xaa0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xaa4 */ { 0xfffe, 778 }, { 0xffff, 793 }, { 0xffff, 809 }, { 0x3fff, 825 }, + /* 0xaa8 */ { 0xfffe, 839 }, { 0xffff, 854 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xaac */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x7ff0, 870 }, + /* 0xab0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xab4 */ { 0xfffe, 881 }, { 0xffff, 896 }, { 0xffff, 912 }, { 0x3fff, 928 }, + /* 0xab8 */ { 0xfffe, 942 }, { 0xffff, 957 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xabc */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0780, 973 }, + /* 0xac0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xac4 */ { 0xfffe, 977 }, { 0xffff, 992 }, { 0xffff, 1008 }, { 0x3fff, 1024 }, + /* 0xac8 */ { 0xfffe, 1038 }, { 0x00ff, 1053 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xacc */ { 0xfffc, 1061 }, { 0x0001, 1075 }, { 0x0000, 0 }, { 0x007c, 1076 }, + /* 0xad0 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, { 0x0000, 0 }, + /* 0xad4 */ { 0xfffe, 1081 }, { 0xffff, 1096 }, { 0xffff, 1112 }, { 0x3fff, 1128 }, + /* 0xad8 */ { 0x0000, 0 }, { 0x0000, 0 }, { 0xfffe, 1142 }, { 0x0001, 1157 }, +}; + +static const cjk_index_t mac_korean_2uni_index[] = { + { { 0x0080, 0x00ff }, mac_korean_2uni_page00 }, + { { 0xa140, 0xadbf }, mac_korean_2uni_pagea1 }, + { { 0, 0 }, NULL } +}; + +static const uint16_t mac_korean_2uni_charset[] = { + 0x00a0, 0x20a9, 0xe022, 0x00a9, 0xe41c, 0xe02b, 0xe12a, 0xe12e, + 0xe128, 0xe12c, 0xe129, 0xe12d, 0xe130, 0xe132, 0xe125, 0xe126, + 0xe123, 0xe124, 0xfe59, 0xfe5a, 0xe413, 0xe415, 0xe118, 0xe11e, + 0xe115, 0xe11b, 0xe117, 0xe11d, 0xe002, 0xe004, 0x2985, 0x2986, + 0xe134, 0xe136, 0x3016, 0x3017, 0x3018, 0x3019, 0xe017, 0xe01a, + 0xe018, 0xe01b, 0xe116, 0xe11c, 0xe028, 0xe02a, 0xe026, 0xe029, + 0xe025, 0xe006, 0x2051, 0xf840, 0x201f, 0x201b, 0x207a, 0x207b, + 0xe021, 0xe0a2, 0xe0aa, 0xe01f, 0xe0a1, 0xe015, 0xe012, 0x207c, + 0xe0ab, 0x207d, 0x207e, 0xe01c, 0xe01d, 0xe016, 0xe019, 0xe0a5, + 0xe0a7, 0xe0ae, 0xe09f, 0xe0a0, 0xe000, 0xe122, 0xe146, 0xe14e, + 0xe14a, 0xe170, 0xe150, 0xe159, 0xe148, 0xe157, 0xe14c, 0xe167, + 0x204c, 0x204d, 0x02bc, 0x2997, 0x2998, 0xe419, 0xe035, 0xe41a, + 0xe417, 0xe034, 0x00b7, 0x2013, 0x2014, 0x2016, 0x301c, 0x00a2, + 0x00a3, 0x00a5, 0x226a, 0x226b, 0x00ac, 0xe114, 0xe11a, 0xe113, + 0xe119, 0xe412, 0xe414, 0xe138, 0xe139, 0xe133, 0xe135, 0xe003, + 0xe005, 0x02dc, 0x02d0, 0x25c9, 0xe1fe, 0xe203, 0xe208, 0xe20d, + 0xe212, 0xe217, 0xe21c, 0xe221, 0xe226, 0xe289, 0xe28a, 0xe28b, + 0xe28c, 0xe28d, 0xe28e, 0xe28f, 0xe290, 0xe291, 0xe292, 0xe293, + 0xe020, 0xe023, 0xe024, 0x22ee, 0x2237, 0xe1fd, 0xe202, 0xe207, + 0xe20c, 0xe211, 0xe216, 0xe21b, 0xe220, 0xe225, 0xe29f, 0xe2a0, + 0xe2a1, 0xe2a2, 0xe2a3, 0xe2a4, 0xe2a5, 0xe2a6, 0xe2a7, 0xe2a8, + 0xe2a9, 0x278a, 0x278b, 0x278c, 0x278d, 0x278e, 0x278f, 0x2790, + 0x2791, 0x2792, 0x2793, 0xe0bd, 0xe0bf, 0xe0c1, 0xe0c3, 0xe0c5, + 0xe0c7, 0xe0c9, 0xe0cb, 0xe0cd, 0xe0cf, 0xe2c0, 0xe2c1, 0xe2c2, + 0xe2c3, 0xe2c4, 0xe2c5, 0xe2c6, 0xe2c7, 0xe2c8, 0xe2c9, 0xe2ca, + 0xe2cb, 0xe2cc, 0xe2cd, 0xe2ce, 0xe2cf, 0xe2d0, 0xe2d1, 0xe2d2, + 0xe2d3, 0xe2d4, 0xe2d5, 0xe2d6, 0xe2d7, 0xe2d8, 0xe2d9, 0x24b6, + 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd, 0x24be, + 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5, 0x24c6, + 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd, 0x24ce, + 0x24cf, 0x203e, 0xe1ff, 0xe204, 0xe209, 0xe20e, 0xe213, 0xe218, + 0xe21d, 0xe222, 0xe227, 0xe273, 0xe274, 0xe275, 0xe276, 0xe277, + 0xe278, 0xe279, 0xe27a, 0xe27b, 0xe27c, 0xe27d, 0xe1fc, 0xe201, + 0xe206, 0xe20b, 0xe210, 0xe215, 0xe21a, 0xe21f, 0xe224, 0xe2aa, + 0xe2ab, 0xe2ac, 0xe2ad, 0xe2ae, 0xe2af, 0xe2b0, 0xe2b1, 0xe2b2, + 0xe2b3, 0xe2b4, 0xe0fa, 0xe0fb, 0xe0fc, 0xe0fd, 0xe0fe, 0xe0ff, + 0xe100, 0xe101, 0xe102, 0xe103, 0xe0bc, 0xe0be, 0xe0c0, 0xe0c2, + 0xe0c4, 0xe0c6, 0xe0c8, 0xe0ca, 0xe0cc, 0xe0ce, 0x2a26, 0x227a, + 0x227b, 0x22ce, 0x22cf, 0x2280, 0x2281, 0x2270, 0x2271, 0x2272, + 0x2273, 0x2ac5, 0x2acb, 0x2ac6, 0x2acc, 0x2276, 0x2277, 0x2279, + 0x22da, 0x22db, 0x2a8b, 0x2a8c, 0x2a91, 0x2a92, 0xe0a3, 0x2245, + 0x2243, 0x2248, 0x29a3, 0x22a4, 0xe0a4, 0xe120, 0xe008, 0xe009, + 0xe00a, 0xe00b, 0xe00c, 0xe00d, 0xe00e, 0xe00f, 0xe010, 0xe011, + 0xe0bb, 0xe0b2, 0xe0b3, 0xe0b4, 0xe0b5, 0xe0b6, 0xe0b7, 0xe0b8, + 0xe0b9, 0xe0ba, 0xe333, 0xe335, 0xe337, 0xe339, 0xe33b, 0xe33d, + 0xe33f, 0xe341, 0xe343, 0xe345, 0xe347, 0xe349, 0xe34b, 0xe34d, + 0xe34f, 0xe351, 0xe353, 0xe355, 0xe357, 0xe359, 0xe35b, 0xe35d, + 0xe35f, 0xe361, 0xe363, 0xe365, 0xe367, 0xe369, 0xe36b, 0xe36d, + 0xe36f, 0xe371, 0xe373, 0xe375, 0xe377, 0xe379, 0xe37b, 0xe37d, + 0xe37f, 0xe381, 0xe383, 0xe385, 0xe387, 0xe389, 0xe38b, 0xe38d, + 0xe38f, 0xe391, 0xe393, 0xe395, 0xe397, 0xe399, 0xe416, 0xe121, + 0xe02d, 0xe02f, 0x2034, 0xe140, 0xe141, 0xe142, 0xe143, 0xe3cf, + 0xf83d, 0xe027, 0xe39b, 0xe39c, 0xe2da, 0xe01e, 0x266f, 0xe41b, + 0xe418, 0xe033, 0xe332, 0x2042, 0x204e, 0xe032, 0xe3ca, 0xe031, + 0x273d, 0x2731, 0x2747, 0x2022, 0xe0d0, 0xe0de, 0xf805, 0xe0d1, + 0x2039, 0x203a, 0x00ab, 0x00bb, 0xe0ed, 0xe0ef, 0xe3cc, 0xe228, + 0xe0dd, 0xf806, 0x29c8, 0xe0db, 0xe3cb, 0xe11f, 0x29be, 0xe0e8, + 0xe0d8, 0xe0d7, 0x271a, 0x2716, 0x29bf, 0x25ef, 0xe0ea, 0xe0eb, + 0x2723, 0x2756, 0xf80a, 0x25cc, 0xe0ec, 0x2610, 0x25a2, 0xe0f5, + 0xe0f8, 0xe0f6, 0x273f, 0xe137, 0xf809, 0xe0e4, 0x274d, 0x25cd, + 0xe104, 0xe3ce, 0xe0f4, 0x2720, 0xe0e3, 0xe0d5, 0x2741, 0xe0f9, + 0xf808, 0xe036, 0xe3cd, 0xe168, 0x262f, 0xf80b, 0xe0f2, 0xe0f1, + 0x2740, 0xf80c, 0xe0f7, 0x3020, 0xf807, 0x2776, 0x2777, 0x2778, + 0x2779, 0x277a, 0x277b, 0x277c, 0x277d, 0x277e, 0x277f, 0x24eb, + 0x24ec, 0x24ed, 0x24ee, 0x24ef, 0x24f0, 0x24f1, 0x24f2, 0x24f3, + 0x24f4, 0xe13a, 0xe13b, 0xe13c, 0xe13d, 0xe13e, 0xe13f, 0xe0f3, + 0x3012, 0x3036, 0xe0e7, 0xe0d9, 0x25fb, 0xf84c, 0xe0b1, 0xe0d6, + 0x25ad, 0xf84d, 0xf84e, 0xf84f, 0xe0e2, 0xe15d, 0xe15c, 0x2206, + 0xe09e, 0x221f, 0xe0a8, 0x2225, 0x2226, 0xe0a6, 0x2253, 0x2251, + 0x2266, 0x2267, 0x2213, 0x2295, 0x2296, 0x2297, 0x2a38, 0x2314, + 0xe014, 0xe0ad, 0x2262, 0xe013, 0x25b1, 0xe007, 0x2222, 0x2250, + 0x03d5, 0x2ae8, 0x22a3, 0xe0af, 0xe0ac, 0x226e, 0x226f, 0x2285, + 0x2284, 0x2209, 0x220c, 0x22bb, 0x22bc, 0x225a, 0x2306, 0xe0a9, + 0xe0b0, 0x2a72, 0xe191, 0xe288, 0xe29e, 0x329e, 0xe144, 0x203c, + 0x2049, 0xe030, 0x2047, 0xe0e1, 0xe0df, 0xe0e0, 0xe0dc, 0xe0d4, + 0xe0d2, 0xe0d3, 0x2588, 0x25e6, 0xe0e5, 0xe0e6, 0xe0e9, 0x25bf, + 0x25b5, 0x25b9, 0x25c3, 0x2666, 0x2981, 0x25fc, 0xe0da, 0x25ca, + 0x3231, 0x3239, 0x33cb, 0x246f, 0x2470, 0x2471, 0x2472, 0x2473, + 0x3251, 0x3252, 0x3253, 0x3254, 0x3255, 0x3256, 0x3257, 0x3258, + 0x3259, 0x325a, 0xe055, 0xe040, 0xe04b, 0xe05f, 0xe064, 0xe065, + 0xe066, 0xe067, 0x21d0, 0x21cf, 0x21cd, 0xe079, 0xe056, 0xe041, + 0xe04c, 0xe060, 0xe062, 0xe063, 0xe03e, 0xe053, 0xe049, 0xe05d, + 0xe07b, 0xe08e, 0xe086, 0xe097, 0xe07a, 0x27b2, 0xe085, 0xe096, + 0xe042, 0x279c, 0xe04d, 0xe061, 0xe03c, 0xe051, 0xe047, 0xe05b, + 0xf846, 0xf847, 0xe038, 0x279b, 0xe039, 0xe04f, 0xe044, 0xe058, + 0x2962, 0x2964, 0x2963, 0x2965, 0xe081, 0x27a1, 0xe08a, 0xe09b, + 0xe082, 0x279e, 0xe08b, 0xe09c, 0x21b2, 0x21b1, 0xe06f, 0x21b4, + 0x21b0, 0x21b3, 0xe110, 0xe107, 0x2936, 0xe06d, 0xe071, 0x2935, + 0xe06a, 0x2937, 0x2939, 0x2934, 0xe080, 0xe093, 0xe089, 0xe09a, + 0x21bc, 0x21c0, 0xf841, 0xe078, 0xe090, 0xe07d, 0xe074, 0xe072, + 0xe077, 0xe076, 0xf849, 0xf848, 0x21c4, 0x21c5, 0xe334, 0xe336, + 0xe338, 0xe33a, 0xe33c, 0xe33e, 0xe340, 0xe342, 0xe344, 0xe346, + 0xe348, 0xe34a, 0xe34c, 0xe34e, 0xe350, 0xe352, 0xe354, 0xe356, + 0xe358, 0xe35a, 0xe35c, 0xe35e, 0xe360, 0xe362, 0xe364, 0xe366, + 0xe368, 0xe36a, 0xe36c, 0xe36e, 0xe370, 0xe372, 0xe374, 0xe376, + 0xe378, 0xe37a, 0xe37c, 0xe37e, 0xe380, 0xe382, 0xe384, 0xe386, + 0xe388, 0xe38a, 0xe38c, 0xe38e, 0xe390, 0xe392, 0xe394, 0xe396, + 0xe398, 0xe39a, 0xe1d1, 0xe1a9, 0xe1e8, 0xe1b2, 0xe1ab, 0xe1f8, + 0xe1ba, 0xe1e0, 0xe1e2, 0xe1c4, 0xe1ad, 0xe1bc, 0xe1b6, 0xe1dd, + 0xe1f1, 0xe19b, 0xe1cb, 0xe1d9, 0xe1ae, 0xe16a, 0xe192, 0xe1cf, + 0xe179, 0xe15b, 0xe18c, 0xe154, 0xe197, 0xe165, 0xe16e, 0xe18b, + 0xe16d, 0xe190, 0xe184, 0xe161, 0xe174, 0xe193, 0xe177, 0xe155, + 0xe188, 0xe173, 0xe15f, 0xe18d, 0xe17d, 0xe163, 0xe17b, 0xe152, + 0xe187, 0xe176, 0xe1e6, 0xe248, 0xe244, 0xe25f, 0xe245, 0xe239, + 0xe23c, 0xe253, 0xe259, 0xe25c, 0xe268, 0xe255, 0xe1e7, 0xe1af, + 0xe1b0, 0xe1b4, 0xe1be, 0xe1c9, 0xe1dc, 0xe1ec, 0xe1ee, 0xe1f0, + 0xe1f2, 0xe1a4, 0xe1a3, 0xe1b1, 0xe1aa, 0xe1f7, 0xe1b9, 0xe1df, + 0xe1e1, 0xe1c3, 0xe1ac, 0xe1bb, 0xe19e, 0xe1b5, 0xe1c2, 0xe1d8, + 0xe1b8, 0xe1ca, 0xe1c5, 0xe1d3, 0xe19f, 0xe15a, 0x2483, 0x2484, + 0x2485, 0x2486, 0x2487, 0xe269, 0xe26a, 0xe26b, 0xe26c, 0xe26d, + 0xe26e, 0xe1e5, 0xe1a1, 0xe19a, 0xe169, 0xe18f, 0xe182, 0xe19d, + 0xe1a8, 0xe1b7, 0xe1bf, 0xe1c0, 0xe1c7, 0xe1cc, 0xe1ce, 0xe1d2, + 0xe1de, 0xe1e9, 0xe1ef, 0xe1d0, 0xe1f9, 0xe199, 0xe19c, 0xe1c8, + 0xe178, 0xe17a, 0xe153, 0xe164, 0x3294, 0xe16c, 0xe160, 0xe18e, + 0xe15e, 0xe196, 0xe17c, 0xe162, 0xe186, 0xe16b, 0xe183, 0xe17e, + 0xe18a, 0xe175, 0xe195, 0xe171, 0x32a5, 0xe151, 0xe1bd, 0xe1c6, + 0xe1db, 0xe1d4, 0xe1d5, 0xe1eb, 0xe1f3, 0xe198, 0xe1a2, 0xe1a6, + 0xe1f4, 0xe247, 0xe249, 0xe24e, 0xe251, 0xe25b, 0xe261, 0xe262, + 0xe263, 0xe264, 0xe266, 0xe24c, 0xe243, 0xe24d, 0xe24b, 0xe242, + 0xe24f, 0xe250, 0xe252, 0xe254, 0xe257, 0xe258, 0xe25a, 0xe25d, + 0xe25e, 0xe260, 0xe265, 0xe267, 0xe240, 0xe23f, 0xe23e, 0xe24a, + 0xe23b, 0xe23d, 0xe241, 0xe246, 0xe256, 0xe26f, 0xe270, 0xe271, + 0xe272, 0x21f0, 0xf843, 0x27b5, 0xe112, 0xe111, 0xe08f, 0xe07c, + 0x27a4, 0xf844, 0xf84b, 0xf84a, 0xe075, 0xe073, 0xe095, 0xe084, + 0x21b6, 0x21b7, 0x219d, 0x219c, 0xf842, 0xe03f, 0xe054, 0xe04a, + 0xe05e, 0xe083, 0xe094, 0xe08c, 0xe09d, 0xe03a, 0x2794, 0xf845, + 0xe045, 0xe059, 0xe03d, 0xe052, 0xe048, 0xe05c, 0xe03b, 0xe050, + 0xe046, 0xe05a, 0x21e0, 0x21e2, 0x21e1, 0x21e3, 0xe07e, 0xe091, + 0xe087, 0xe098, 0x21e6, 0x21e8, 0x21e7, 0x21e9, 0xe10a, 0xe06b, + 0xe06e, 0xe108, 0xe068, 0xe10c, 0xe10e, 0xe105, 0xe10b, 0xe06c, + 0xe070, 0xe109, 0xe069, 0xe10d, 0xe10f, 0xe106, 0xe037, 0xe04e, + 0xe043, 0xe057, 0x261d, 0x261f, 0xe0ee, 0xe0f0, 0xe1a7, 0xe1ed, + 0xe1c1, 0xe1ea, 0xe1da, 0xe1d7, 0xe1fa, 0xe1fb, 0xe200, 0xe205, + 0xe20a, 0xe20f, 0xe214, 0xe219, 0xe21e, 0xe223, 0xe2b5, 0xe2b6, + 0xe2b7, 0xe2b8, 0xe2b9, 0xe2ba, 0xe2bb, 0xe2bc, 0xe2bd, 0xe2be, + 0xe2bf, 0xe229, 0xe22d, 0xe22b, 0xe232, 0xe22e, 0xe230, 0xe22a, + 0xe22f, 0xe22c, 0xe231, 0xe295, 0xe299, 0xe297, 0xe29d, 0xe29a, + 0xe29c, 0xe296, 0xe29b, 0xe298, 0xe294, 0xe145, 0xe14d, 0xe149, + 0xe16f, 0xe14f, 0xe158, 0xe147, 0xe156, 0xe14b, 0xe166, 0xe27f, + 0xe283, 0xe281, 0xe287, 0xe284, 0xe286, 0xe280, 0xe285, 0xe282, + 0xe27e, 0xe17f, 0xe180, 0xe189, 0xe185, 0xe181, 0xe194, 0xe172, + 0x3290, 0x328a, 0x328b, 0x328c, 0x328d, 0x328e, 0x328f, 0xe234, + 0xe235, 0xe238, 0xe237, 0xe236, 0xe23a, 0xe233, 0xe127, 0xe12b, + 0xe12f, 0xe131, 0xe092, 0xe07f, 0xe088, 0xe099, 0x301e, 0x301f, + 0x2036, 0xe02e, 0x2035, 0xe02c, 0xe08d, 0xe001, +}; + +static const uint32_t mac_korean_compose[] = { + 0x0021f877, 0x0021f87f, 0x0028f87c, 0x0028f87f, + 0x0029f87c, 0x0029f87f, 0x002af877, 0x002d0308, + 0x003020de, 0x003120de, 0x003220de, 0x003320de, + 0x003420de, 0x003520de, 0x003620de, 0x003720de, + 0x003820de, 0x003920de, 0x003cf877, 0x003d20d2, + 0x003d20e5, 0x003ef877, 0x005bf877, 0x005bf87b, + 0x005bf87c, 0x005df877, 0x005df87b, 0x005df87c, + 0x007bf877, 0x007df877, 0x00a7f87c, 0x00b1f877, + 0x00b6f87f, 0x00d7f877, 0x2013f87f, 0x2016f87b, + 0x2016f87c, 0x2020f877, 0x2020f87b, 0x2020f87c, + 0x2020f87f, 0x2021f87c, 0x2021f87f, 0x2026f87f, + 0x2032f873, 0x2032f87f, 0x2033f873, 0x2033f87f, + 0x203cf87f, 0x2042f879, 0x2051f871, 0x2051f874, + 0x2051f879, 0x2051f87c, 0x20a9f87f, 0x2190f870, + 0x2190f871, 0x2190f872, 0x2190f873, 0x2190f874, + 0x2190f875, 0x2190f878, 0x2190f879, 0x2190f87a, + 0x2190f87b, 0x2190f87c, 0x2190f87f, 0x2191f870, + 0x2191f872, 0x2191f873, 0x2191f874, 0x2191f875, + 0x2191f878, 0x2191f879, 0x2191f87a, 0x2191f87b, + 0x2191f87c, 0x2191f87f, 0x2192f870, 0x2192f872, + 0x2192f874, 0x2192f875, 0x2192f878, 0x2192f879, + 0x2192f87a, 0x2192f87b, 0x2192f87c, 0x2193f870, + 0x2193f872, 0x2193f873, 0x2193f874, 0x2193f875, + 0x2193f878, 0x2193f879, 0x2193f87a, 0x2193f87b, + 0x2193f87c, 0x2193f87f, 0x2194f87c, 0x2195f87c, + 0x2196f87b, 0x2197f87b, 0x2198f87b, 0x2199f87b, + 0x21b0f87a, 0x21b0f87c, 0x21b0f87f, 0x21b1f87a, + 0x21b1f87c, 0x21b1f87f, 0x21bbf87a, 0x21bbf87b, + 0x21bbf87c, 0x21bbf87f, 0x21bcf879, 0x21bcf87f, + 0x21c0f879, 0x21c0f87f, 0x21d0f87c, 0x21d2f87c, + 0x21d4f879, 0x21d4f87f, 0x21e620dd, 0x21e620de, + 0x21e6f870, 0x21e6f874, 0x21e6f875, 0x21e6f878, + 0x21e6f879, 0x21e6f87a, 0x21e6f87b, 0x21e6f87c, + 0x21e6f87f, 0x21e720dd, 0x21e720de, 0x21e7f875, + 0x21e7f878, 0x21e7f879, 0x21e7f87a, 0x21e7f87b, + 0x21e7f87c, 0x21e7f87f, 0x21e820de, 0x21e8f870, + 0x21e8f874, 0x21e8f875, 0x21e8f878, 0x21e8f879, + 0x21e8f87c, 0x21e8f87f, 0x21e920dd, 0x21e920de, + 0x21e9f875, 0x21e9f878, 0x21e9f879, 0x21e9f87a, + 0x21e9f87b, 0x21e9f87c, 0x2206f87f, 0x2208f877, + 0x2211f877, 0x2213f877, 0x221ef877, 0x2222f87f, + 0x22250347, 0x2229f877, 0x2229f87f, 0x222af877, + 0x222af87f, 0x223d0336, 0x223df877, 0x2260f877, + 0x226120d2, 0x226120e5, 0x2282f877, 0x22a50338, + 0x2314f87f, 0x2394f876, 0x2460f87f, 0x2461f87f, + 0x2462f87f, 0x2463f87f, 0x2464f87f, 0x2465f87f, + 0x2466f87f, 0x2467f87f, 0x2468f87f, 0x24eaf87f, + 0x24ebf878, 0x24ebf87f, 0x24ecf878, 0x24ecf87f, + 0x24edf878, 0x24edf87f, 0x24eef878, 0x24eef87f, + 0x24eff878, 0x24eff87f, 0x24f0f878, 0x24f0f87f, + 0x24f1f878, 0x24f1f87f, 0x24f2f878, 0x24f2f87f, + 0x24f3f878, 0x24f3f87f, 0x24f4f878, 0x24f4f87f, + 0x25a020df, 0x25a120df, 0x25a1f879, 0x25a1f87b, + 0x25a1f87c, 0x25a8f87f, 0x25adf878, 0x25b220dd, + 0x25b320dd, 0x25b3f87f, 0x25b420e4, 0x25c620de, + 0x25c6f879, 0x25c720de, 0x25c720df, 0x25c7f879, + 0x25c7f87b, 0x25c7f87c, 0x25c7f87f, 0x25c8f87f, + 0x25c920dd, 0x25cbf879, 0x25cbf87b, 0x25cbf87f, + 0x25ce20dd, 0x25cff879, 0x25eff87c, 0x2610f87c, + 0x2610f87f, 0x261cf87f, 0x261df87f, 0x261ef87f, + 0x261ff87f, 0x262ff876, 0x262ff87a, 0x2642f87f, + 0x2720f87a, 0x2723f87a, 0x273ff87a, 0x274820d8, + 0x2756f87a, 0x2756f87f, 0x278af87f, 0x278bf87f, + 0x278cf87f, 0x278df87f, 0x278ef87f, 0x278ff87f, + 0x2790f87f, 0x2791f87f, 0x2792f87f, 0x2793f87f, + 0x27e120dd, 0x2934f87a, 0x2934f87c, 0x2934f87f, + 0x2935f87a, 0x2935f87c, 0x2936f87a, 0x2936f87c, + 0x2937f87a, 0x2937f87c, 0x2939f87a, 0x2939f87c, + 0x2939f87f, 0x2962f87f, 0x2964f87f, 0x2985f873, + 0x2985f878, 0x2985f879, 0x2985f87b, 0x2985f87c, + 0x2985f87f, 0x2986f873, 0x2986f878, 0x2986f879, + 0x2986f87b, 0x2986f87c, 0x2986f87f, 0x29c820de, + 0x2afd0347, 0x3002f87d, 0x3007f876, 0x3008f878, + 0x3009f878, 0x300af878, 0x300bf878, 0x300cf879, + 0x300cf87b, 0x300cf87c, 0x300cf87f, 0x300df879, + 0x300df87b, 0x300df87c, 0x300df87f, 0x300ef879, + 0x300ef87c, 0x300ff879, 0x300ff87c, 0x3010f878, + 0x3010f87f, 0x3011f878, 0x3011f87f, 0x3013f87c, + 0x3016f878, 0x3017f878, 0x3251f87a, 0x3252f87a, + 0x3253f87a, 0x3254f87a, 0x3255f87a, 0x3256f87a, + 0x3257f87a, 0x3258f87a, 0x3259f87a, 0x325af87a, + 0x329ef87f, 0x4e0020de, 0x4e00f876, 0x4e0320de, + 0x4e03f876, 0x4e0920de, 0x4e09f876, 0x4e5d20de, + 0x4e5df876, 0x4e8c20de, 0x4e8cf876, 0x4e9420de, + 0x4e94f876, 0x4ed620dd, 0x4ed620de, 0x4ee320dd, + 0x4ee320de, 0x4f8b20de, 0x516b20de, 0x516bf876, + 0x516d20de, 0x516df876, 0x51a020dd, 0x51a020de, + 0x51f8f87f, 0x51f9f87f, 0x524d20dd, 0x524d20de, + 0x526f20dd, 0x526f20de, 0x52a920dd, 0x52a920de, + 0x52d520dd, 0x52d520de, 0x534120de, 0x5341f876, + 0x534df87f, 0x537020dd, 0x537020de, 0x53c320dd, + 0x53cd20dd, 0x53cd20de, 0x540d20de, 0x56db20de, + 0x56dbf876, 0x570b20dd, 0x571f20de, 0x5b5020de, + 0x5e8f20de, 0x5f6220dd, 0x5f6220de, 0x5f7120de, + 0x611f20dd, 0x611f20de, 0x616320dd, 0x630720de, + 0x63a520dd, 0x63a520de, 0x65b020dd, 0x65e520de, + 0x670820de, 0x672820de, 0x672b20dd, 0x672c20dd, + 0x672c20de, 0x6c3420de, 0x6ce820dd, 0x6d3e20de, + 0x6e9020de, 0x706b20de, 0x73fe20dd, 0x76ee20de, + 0x7b5420de, 0x7bc020de, 0x81ea20dd, 0x886320dd, + 0x88dc20de, 0x88dc20e4, 0x8a3b20de, 0x902320de, + 0x91d120de, 0x959320dd, 0x96fb20dd, 0x982d20de, + 0xac0020dd, 0xac0420dd, 0xac1020dd, 0xac1020de, + 0xac1920dd, 0xac7020dd, 0xac8c20dd, 0xad0020dd, + 0xad5020de, 0xad6d20dd, 0xb09820dd, 0xb0ae20dd, + 0xb19220dd, 0xb29020dd, 0xb2e420dd, 0xb2e820dd, + 0xb2f520dd, 0xb2f520de, 0xb30020dd, 0xb30020de, + 0xb3d920dd, 0xb3d920de, 0xb73b20de, 0xb77c20dd, + 0xb9c820dd, 0xba8520dd, 0xba8520de, 0xbb3820de, + 0xbc1420dd, 0xbc1820dd, 0xbc1820de, 0xbcc020dd, + 0xbcf820dd, 0xbd8020dd, 0xbd8020de, 0xbe4420dd, + 0xbe4420de, 0xbe6020dd, 0xc0ac20dd, 0xc0c120dd, + 0xc13c20dd, 0xc18c20dd, 0xc18d20dd, 0xc21820dd, + 0xc21820de, 0xc21920dd, 0xc2dc20dd, 0xc2e020dd, + 0xc2e420dd, 0xc54420dd, 0xc57d20dd, 0xc57d20de, + 0xc5ec20dd, 0xc5ed20de, 0xc60820dd, 0xc60820de, + 0xc67820dd, 0xc6b420de, 0xc6d020dd, 0xc72020dd, + 0xc73c20dd, 0xc74c20dd, 0xc74c20de, 0xc77420dd, + 0xc77820dd, 0xc77820de, 0xc77c20dd, 0xc78520dd, + 0xc79020dd, 0xc79020de, 0xc79120dd, 0xc80420dd, + 0xc80420de, 0xc81120dd, 0xc81120de, 0xc81520de, + 0xc81c20dd, 0xc87020dd, 0xc87020de, 0xc87420dd, + 0xc8fc20de, 0xc90020dd, 0xc91120dd, 0xc9c120dd, + 0xcc2820dd, 0xcc3820dd, 0xce7420dd, 0xd0b920dd, + 0xd0c020dd, 0xd0c020de, 0xd30c20dd, 0xd45c20dd, + 0xd55820dd, 0xd57420dd, 0xd57420de, 0xd61520dd, + 0xd61520de, 0xd65c20dd, 0xd73420dd, 0xe009f875, + 0xe009f87a, 0xe009f87b, 0xe009f87c, 0xe009f87f, + 0xe00af875, 0xe00af87a, 0xe00af87b, 0xe00af87c, + 0xe00af87f, 0xe00bf875, 0xe00bf87a, 0xe00bf87b, + 0xe00bf87c, 0xe00bf87f, 0xe00cf875, 0xe00cf87a, + 0xe00cf87b, 0xe00cf87c, 0xe00cf87f, 0xe00df875, + 0xe00df87a, 0xe00df87b, 0xe00df87c, 0xe00df87f, + 0xe00ef875, 0xe00ef87a, 0xe00ef87b, 0xe00ef87c, + 0xe00ef87f, 0xe00ff875, 0xe00ff87a, 0xe00ff87b, + 0xe00ff87c, 0xe00ff87f, 0xe010f875, 0xe010f87a, + 0xe010f87b, 0xe010f87c, 0xe010f87f, 0xe011f875, + 0xe011f87a, 0xe011f87b, 0xe011f87c, 0xe011f87f, + 0xe0de20df, 0xe145f87a, 0xe147f87a, 0xe149f87a, + 0xe14bf87a, 0xe14df87a, 0xe14ff87a, 0xe156f87a, + 0xe158f87a, 0xe166f87a, 0xe16ff87a, 0xe172f87c, + 0xe17ff87c, 0xe180f87c, 0xe181f87c, 0xe185f87c, + 0xe189f87c, 0xe192f87a, 0xe194f87c, 0xe198f87a, + 0xe1a0f87a, 0xe1a2f87a, 0xe1a3f87a, 0xe1a4f87a, + 0xe1a5f87a, 0xe1a6f87a, 0xe1a7f87a, 0xe1a8f87a, + 0xe1a9f87a, 0xe1aef87a, 0xe1aff87a, 0xe1b0f87a, + 0xe1b3f87a, 0xe1b4f87a, 0xe1b5f87a, 0xe1b8f87a, + 0xe1bbf87a, 0xe1bdf87a, 0xe1bef87a, 0xe1c0f87a, + 0xe1c6f87a, 0xe1c9f87a, 0xe1ccf87a, 0xe1cdf87a, + 0xe1cef87a, 0xe1cff87a, 0xe1d0f87a, 0xe1d4f87a, + 0xe1d5f87a, 0xe1d6f87a, 0xe1dbf87a, 0xe1dcf87a, + 0xe1e3f87a, 0xe1e4f87a, 0xe1e7f87a, 0xe1e8f87a, + 0xe1e9f87a, 0xe1ecf87a, 0xe1eef87a, 0xe1f0f87a, + 0xe1f2f87a, 0xe1f3f87a, 0xe1f4f87a, 0xe1f5f87a, + 0xe1f6f87a, 0xe2db0029, 0xe2dc0029, 0xe2dd0029, + 0xe2de0029, 0xe2df0029, 0xe2e00029, 0xe2e10029, + 0xe2e20029, 0xe2e30029, 0xe2e40029, 0xe2e5005d, + 0xe2e6005d, 0xe2e7005d, 0xe2e8005d, 0xe2e9005d, + 0xe2ea005d, 0xe2eb005d, 0xe2ec005d, 0xe2ed005d, + 0xe2ee005d, 0xe2ef005d, 0xe2f0005d, 0xe2f1005d, + 0xe2f2005d, 0xe2f3005d, 0xe2f4005d, 0xe2f5005d, + 0xe2f6005d, 0xe2f7005d, 0xe2f8005d, 0xe2f9005d, + 0xe2fac0ac, 0xe2fb005d, 0xe2fc005d, 0xe2fd005d, + 0xe2fe005d, 0xe2ff005d, 0xe300005d, 0xe301005d, + 0xe302005d, 0xe303005d, 0xe304005d, 0xe305005d, + 0xe306005d, 0xe307005d, 0xe308005d, 0xe309005d, + 0xe30a005d, 0xe30b005d, 0xe30c005d, 0xe30d005d, + 0xe30e005d, 0xe30f005d, 0xe310c0ac, 0xe311005d, + 0xe312005d, 0xe313005d, 0xe314005d, 0xe315005d, + 0xe316005d, 0xe317005d, 0xe318005d, 0xe319005d, + 0xe31a005d, 0xe31b005d, 0xe31c005d, 0xe31d005d, + 0xe31e005d, 0xe31f005d, 0xe320005d, 0xe321005d, + 0xe322005d, 0xe323005d, 0xe324005d, 0xe325005d, + 0xe326005d, 0xe327005d, 0xe328005d, 0xe329005d, + 0xe32a005d, 0xe32b005d, 0xe32c005d, 0xe32d005d, + 0xe32e005d, 0xe32f005d, 0xe330005d, 0xe331005d, + 0xe39d0029, 0xe39e0029, 0xe39f0029, 0xe3a00029, + 0xe3a10029, 0xe3a20029, 0xe3a30029, 0xe3a40029, + 0xe3a50029, 0xe3a60029, 0xe3a70029, 0xe3a80029, + 0xe3a90029, 0xe3aa0029, 0xe3ab0029, 0xe3ac0029, + 0xe3ad0029, 0xe3ae0029, 0xe3af0029, 0xe3b00029, + 0xe3b10029, 0xe3b20029, 0xe3b30029, 0xe3b40029, + 0xe3b50029, 0xe3b60029, 0xe3b72020, 0xe3b80031, + 0xe3b80032, 0xe3b80033, 0xe3b80034, 0xe3b80035, + 0xe3b80036, 0xe3b80037, 0xe3b80038, 0xe3b80039, + 0xe3b90030, 0xe3ba0030, 0xe3ba0031, 0xe3ba0032, + 0xe3ba0033, 0xe3ba0034, 0xe3ba0035, 0xe3ba0036, + 0xe3ba0037, 0xe3ba0038, 0xe3ba0039, 0xe3bb0030, + 0xe3bc5341, 0xe3bd4e00, 0xe3bd4e03, 0xe3bd4e09, + 0xe3bd4e5d, 0xe3bd4e8c, 0xe3bd4e94, 0xe3bd516b, + 0xe3bd516d, 0xe3bd56db, 0xe3bed68c, 0xe3bf0030, + 0xe3bf0031, 0xe3bf0032, 0xe3bf0033, 0xe3bf0034, + 0xe3bf0035, 0xe3bf0036, 0xe3bf0037, 0xe3bf0038, + 0xe3bf0039, 0xe3c00030, 0xe3c15341, 0xe3c24e00, + 0xe3c24e03, 0xe3c24e09, 0xe3c24e5d, 0xe3c24e8c, + 0xe3c24e94, 0xe3c2516b, 0xe3c2516d, 0xe3c256db, + 0xe3c3d68c, 0xe3c40030, 0xe3c40031, 0xe3c40032, + 0xe3c40033, 0xe3c40034, 0xe3c40035, 0xe3c40036, + 0xe3c40037, 0xe3c40038, 0xe3c40039, 0xe3c50030, + 0xe3c60030, 0xe3c60031, 0xe3c60032, 0xe3c60033, + 0xe3c60034, 0xe3c60035, 0xe3c60036, 0xe3c60037, + 0xe3c60038, 0xe3c60039, 0xe3c70030, 0xe3c80030, + 0xe3c80031, 0xe3c80032, 0xe3c80033, 0xe3c80034, + 0xe3c80035, 0xe3c80036, 0xe3c80037, 0xe3c80038, + 0xe3c80039, 0xe3c90030, 0xe3d0002a, 0xe3d10029, + 0xe3d1002e, 0xe3d20029, 0xe3d2002e, 0xe3d30029, + 0xe3d3002e, 0xe3d40029, 0xe3d4002e, 0xe3d50029, + 0xe3d5002e, 0xe3d60029, 0xe3d6002e, 0xe3d70029, + 0xe3d7002e, 0xe3d80029, 0xe3d8002e, 0xe3d90029, + 0xe3d9002e, 0xe3da0029, 0xe3da002e, 0xe3db0029, + 0xe3db002e, 0xe3dc0029, 0xe3dc002e, 0xe3dd0029, + 0xe3dd002e, 0xe3de0029, 0xe3de002e, 0xe3df0029, + 0xe3df002e, 0xe3e00029, 0xe3e0002e, 0xe3e10029, + 0xe3e1002e, 0xe3e20029, 0xe3e2002e, 0xe3e30029, + 0xe3e3002e, 0xe3e40029, 0xe3e4002e, 0xe3e50029, + 0xe3e5002e, 0xe3e60029, 0xe3e6002e, 0xe3e70029, + 0xe3e7002e, 0xe3e80029, 0xe3e8002e, 0xe3e90029, + 0xe3e9002e, 0xe3ea0029, 0xe3ea002e, 0xe3eb0029, + 0xe3eb002e, 0xe3ec0029, 0xe3ec002e, 0xe3ed0029, + 0xe3ed002e, 0xe3ee0029, 0xe3ee002e, 0xe3ef0029, + 0xe3ef002e, 0xe3f00029, 0xe3f0002e, 0xe3f10029, + 0xe3f1002e, 0xe3f20029, 0xe3f2002e, 0xe3f30029, + 0xe3f3002e, 0xe3f40029, 0xe3f4002e, 0xe3f50029, + 0xe3f5002e, 0xe3f60029, 0xe3f6002e, 0xe3f70029, + 0xe3f7002e, 0xe3f80029, 0xe3f8002e, 0xe3f90029, + 0xe3f9002e, 0xe3fa0029, 0xe3fa002e, 0xe3fb0029, + 0xe3fb002e, 0xe3fc0029, 0xe3fc002e, 0xe3fd0029, + 0xe3fd002e, 0xe3fe0029, 0xe3fe002e, 0xe3ff0029, + 0xe3ff002e, 0xe4000029, 0xe400002e, 0xe4010029, + 0xe401002e, 0xe4020029, 0xe402002e, 0xe4030029, + 0xe403002e, 0xe4040029, 0xe404002e, 0xe4052020, + 0xe4062021, 0xe4070041, 0xe4070042, 0xe4070043, + 0xe4070044, 0xe4070045, 0xe4070046, 0xe4070047, + 0xe4070048, 0xe4070049, 0xe407004a, 0xe407004b, + 0xe407004c, 0xe407004d, 0xe407004e, 0xe407004f, + 0xe4070050, 0xe4070051, 0xe4070052, 0xe4070053, + 0xe4070054, 0xe4070055, 0xe4070056, 0xe4070057, + 0xe4070058, 0xe4070059, 0xe407005a, 0xe4082020, + 0xe4090032, 0xe4090033, 0xe40a0031, 0xe40a0032, + 0xe40a4e8c, 0xe40a5341, 0xe40bc2dd, 0xe40c0031, + 0xe40c0032, 0xe40c4e8c, 0xe40c5341, 0xe40dc2dd, + 0xe40e0031, 0xe40e0032, 0xe40f0031, 0xe40f0032, + 0xe4100031, 0xe4100032, 0xe411002a, 0xf80520de, + 0xf80620df, 0xf809f87a, 0xf80bf87f, 0xf83df87f, + 0xf860002a, 0xf8600041, 0xf8600042, 0xf8600043, + 0xf8600044, 0xf8600045, 0xf8600046, 0xf8600047, + 0xf8600048, 0xf8600049, 0xf860004a, 0xf860004b, + 0xf860004c, 0xf860004d, 0xf860004e, 0xf860004f, + 0xf8600050, 0xf8600051, 0xf8600052, 0xf8600053, + 0xf8600054, 0xf8600055, 0xf8600056, 0xf8600057, + 0xf8600058, 0xf8600059, 0xf860005a, 0xf8600061, + 0xf8600062, 0xf8600063, 0xf8600064, 0xf8600065, + 0xf8600066, 0xf8600067, 0xf8600068, 0xf8600069, + 0xf860006a, 0xf860006b, 0xf860006c, 0xf860006d, + 0xf860006e, 0xf860006f, 0xf8600070, 0xf8600071, + 0xf8600072, 0xf8600073, 0xf8600074, 0xf8600075, + 0xf8600076, 0xf8600077, 0xf8600078, 0xf8600079, + 0xf860007a, 0xf8602020, 0xf8602021, 0xf8610028, + 0xf8612020, 0xf8620028, 0xf862005b, 0xf862c8fc, + 0xf863005b, 0xf863c8fc, 0xf864005b, 0xf865005b, + 0xf866005b, 0xf867002a, 0xfe59f87c, 0xfe59f87f, + 0xfe5af87c, 0xfe5af87f, 0xff01f874, 0xff0af871, + 0xff0af873, 0xff0af874, 0xff0af875, 0xff0af87f, + 0xff3ff87f, +}; diff --git a/libatalk/unicode/charsets/mac_roman.c b/libatalk/unicode/charsets/mac_roman.c new file mode 100644 index 0000000..34ccaaf --- /dev/null +++ b/libatalk/unicode/charsets/mac_roman.c @@ -0,0 +1,118 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include +#include + +#include + +#include "mac_roman.h" +#include "generic_mb.h" + +static size_t mac_roman_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_roman_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_roman = +{ + "MAC_ROMAN", + 0, + mac_roman_pull, + mac_roman_push, + CHARSET_CLIENT | CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED, + NULL, + NULL, NULL +}; + +/* ------------------------ */ +static int +char_ucs2_to_mac_roman ( unsigned char *r, ucs2_t wc) +{ + unsigned char c = 0; + if (wc < 0x0080) { + *r = wc; + return 1; + } + else if (wc >= 0x00a0 && wc < 0x0100) + c = mac_roman_page00[wc-0x00a0]; + else if (wc >= 0x0130 && wc < 0x0198) + c = mac_roman_page01[wc-0x0130]; + else if (wc >= 0x02c0 && wc < 0x02e0) + c = mac_roman_page02[wc-0x02c0]; + else if (wc == 0x03c0) + c = 0xb9; + else if (wc >= 0x2010 && wc < 0x2048) + c = mac_roman_page20[wc-0x2010]; + else if (wc >= 0x2120 && wc < 0x2128) + c = mac_roman_page21[wc-0x2120]; + else if (wc >= 0x2200 && wc < 0x2268) + c = mac_roman_page22[wc-0x2200]; + else if (wc == 0x25ca) + c = 0xd7; + else if (wc >= 0xfb00 && wc < 0xfb08) + c = mac_roman_pagefb[wc-0xfb00]; + else if (wc == 0xf8ff) + c = 0xf0; + + if (c != 0) { + *r = c; + return 1; + } + return 0; +} + +static size_t mac_roman_push( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + /* No special handling required */ + return (size_t) mb_generic_push( char_ucs2_to_mac_roman, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +/* ------------------------ */ +static int +char_mac_roman_to_ucs2 (ucs2_t *pwc, const unsigned char *s) +{ + unsigned char c = *s; + if (c < 0x80) { + *pwc = (ucs2_t) c; + return 1; + } + else { + unsigned short wc = mac_roman_2uni[c-0x80]; + *pwc = (ucs2_t) wc; + return 1; + } + return 0; +} + +static size_t mac_roman_pull ( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_pull( char_mac_roman_to_ucs2, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} diff --git a/libatalk/unicode/charsets/mac_roman.h b/libatalk/unicode/charsets/mac_roman.h new file mode 100644 index 0000000..5d2c72e --- /dev/null +++ b/libatalk/unicode/charsets/mac_roman.h @@ -0,0 +1,117 @@ + +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * from GNU libiconv + * modified by Bjorn (Apple Logo 0xf0 to Apple unicode 0xf8ff ) + */ + + +static const unsigned char mac_roman_page00[96] = { + 0xca, 0xc1, 0xa2, 0xa3, 0xdb, 0xb4, 0x00, 0xa4, /* 0xa0-0xa7 */ + 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0x00, 0xa8, 0xf8, /* 0xa8-0xaf */ + 0xa1, 0xb1, 0x00, 0x00, 0xab, 0xb5, 0xa6, 0xe1, /* 0xb0-0xb7 */ + 0xfc, 0x00, 0xbc, 0xc8, 0x00, 0x00, 0x00, 0xc0, /* 0xb8-0xbf */ + 0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, /* 0xc0-0xc7 */ + 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, /* 0xc8-0xcf */ + 0x00, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */ + 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0x00, 0x00, 0xa7, /* 0xd8-0xdf */ + 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, /* 0xe0-0xe7 */ + 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */ + 0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */ + 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0xd8, /* 0xf8-0xff */ +}; +static const unsigned char mac_roman_page01[104] = { + 0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ + 0x00, 0x00, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ + 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ + 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ +}; +static const unsigned char mac_roman_page02[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xff, /* 0xc0-0xc7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ + 0xf9, 0xfa, 0xfb, 0xfe, 0xf7, 0xfd, 0x00, 0x00, /* 0xd8-0xdf */ +}; +static const unsigned char mac_roman_page20[56] = { + 0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */ + 0xa0, 0xe0, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ + 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x40-0x47 */ +}; +static const unsigned char mac_roman_page21[8] = { + 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xbd, 0x00, /* 0x20-0x27 */ +}; +static const unsigned char mac_roman_page22[104] = { + 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, /* 0x08-0x0f */ + 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ + 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ + 0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */ +}; +static const unsigned char mac_roman_pagefb[8] = { + 0x00, 0xde, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ +}; + + + + +static const unsigned short mac_roman_2uni[128] = { + /* 0x80 */ + 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1, + 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8, + /* 0x90 */ + 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3, + 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc, + /* 0xa0 */ + 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df, + 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8, + /* 0xb0 */ + 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211, + 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x2126, 0x00e6, 0x00f8, + /* 0xc0 */ + 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab, + 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153, + /* 0xd0 */ + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca, + 0x00ff, 0x0178, 0x2044, 0x00a4, 0x2039, 0x203a, 0xfb01, 0xfb02, + /* 0xe0 */ + 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1, + 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4, + /* 0xf0 */ + 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc, + 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7, +}; diff --git a/libatalk/unicode/charsets/mac_turkish.c b/libatalk/unicode/charsets/mac_turkish.c new file mode 100644 index 0000000..619f4b0 --- /dev/null +++ b/libatalk/unicode/charsets/mac_turkish.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include +#include + +#include + +#include "mac_turkish.h" +#include "generic_mb.h" + +static size_t mac_turkish_pull(void *,char **, size_t *, char **, size_t *); +static size_t mac_turkish_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_mac_turkish = +{ + "MAC_TURKISH", + 35, + mac_turkish_pull, + mac_turkish_push, + CHARSET_CLIENT | CHARSET_MULTIBYTE, + NULL, + NULL, NULL +}; + +static size_t mac_turkish_push( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_push( char_ucs2_to_mac_turkish, cd, inbuf, inbytesleft, outbuf, outbytesleft); +} + +/* ------------------------ */ + +static size_t mac_turkish_pull ( void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return (size_t) mb_generic_pull( char_mac_turkish_to_ucs2, cd, inbuf, inbytesleft, outbuf, outbytesleft); + +} diff --git a/libatalk/unicode/charsets/mac_turkish.h b/libatalk/unicode/charsets/mac_turkish.h new file mode 100644 index 0000000..66d22f8 --- /dev/null +++ b/libatalk/unicode/charsets/mac_turkish.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 1999-2001 Free Software Foundation, Inc. + * This file is part of the GNU LIBICONV Library. + * + * The GNU LIBICONV Library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * The GNU LIBICONV 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU LIBICONV Library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, Inc., 59 Temple Place - + * Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * MacTurkish + */ + +static const unsigned short mac_turkish_2uni[128] = { + /* 0x80 */ + 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1, + 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8, + /* 0x90 */ + 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3, + 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc, + /* 0xa0 */ + 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df, + 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8, + /* 0xb0 */ + 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211, + 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x2126, 0x00e6, 0x00f8, + /* 0xc0 */ + 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab, + 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153, + /* 0xd0 */ + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca, + 0x00ff, 0x0178, 0x011e, 0x011f, 0x0130, 0x0131, 0x015e, 0x015f, + /* 0xe0 */ + 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1, + 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4, + /* 0xf0 */ + 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0xf8a0, 0x02c6, 0x02dc, + 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7, +}; + +static int +char_mac_turkish_to_ucs2 (ucs2_t *pwc, const unsigned char *s) +{ + unsigned char c = *s; + if (c < 0x80) { + *pwc = (ucs2_t) c; + return 1; + } + else { + unsigned short wc = mac_turkish_2uni[c-0x80]; + if (wc != 0xfffd) { + *pwc = (ucs2_t) wc; + return 1; + } + } + return 0; +} + +static const unsigned char mac_turkish_page00[96] = { + 0xca, 0xc1, 0xa2, 0xa3, 0x00, 0xb4, 0x00, 0xa4, /* 0xa0-0xa7 */ + 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0x00, 0xa8, 0xf8, /* 0xa8-0xaf */ + 0xa1, 0xb1, 0x00, 0x00, 0xab, 0xb5, 0xa6, 0xe1, /* 0xb0-0xb7 */ + 0xfc, 0x00, 0xbc, 0xc8, 0x00, 0x00, 0x00, 0xc0, /* 0xb8-0xbf */ + 0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, /* 0xc0-0xc7 */ + 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, /* 0xc8-0xcf */ + 0x00, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */ + 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0x00, 0x00, 0xa7, /* 0xd8-0xdf */ + 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, /* 0xe0-0xe7 */ + 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */ + 0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */ + 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0xd8, /* 0xf8-0xff */ +}; +static const unsigned char mac_turkish_page01[128] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xdb, /* 0x18-0x1f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ + 0x00, 0x00, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xdf, /* 0x58-0x5f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ + 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ + 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ +}; +static const unsigned char mac_turkish_page02[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xff, /* 0xc0-0xc7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ + 0xf9, 0xfa, 0xfb, 0xfe, 0xf7, 0xfd, 0x00, 0x00, /* 0xd8-0xdf */ +}; +static const unsigned char mac_turkish_page20[40] = { + 0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */ + 0xa0, 0xe0, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ +}; +static const unsigned char mac_turkish_page21[8] = { + 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xbd, 0x00, /* 0x20-0x27 */ +}; +static const unsigned char mac_turkish_page22[104] = { + 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, /* 0x08-0x0f */ + 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ + 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ + 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ + 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ + 0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */ +}; + +static int +char_ucs2_to_mac_turkish (unsigned char *r, ucs2_t wc) +{ + unsigned char c = 0; + if (wc < 0x0080) { + *r = wc; + return 1; + } + else if (wc >= 0x00a0 && wc < 0x0100) + c = mac_turkish_page00[wc-0x00a0]; + else if (wc >= 0x0118 && wc < 0x0198) + c = mac_turkish_page01[wc-0x0118]; + else if (wc >= 0x02c0 && wc < 0x02e0) + c = mac_turkish_page02[wc-0x02c0]; + else if (wc == 0x03c0) + c = 0xb9; + else if (wc >= 0x2010 && wc < 0x2038) + c = mac_turkish_page20[wc-0x2010]; + else if (wc >= 0x2120 && wc < 0x2128) + c = mac_turkish_page21[wc-0x2120]; + else if (wc >= 0x2200 && wc < 0x2268) + c = mac_turkish_page22[wc-0x2200]; + else if (wc == 0x25ca) + c = 0xd7; + else if (wc == 0xf8ff) /* Apple Logo */ + c = 0xf0; + else if (wc == 0xf8a0) /* undefinded1, roundtrip only */ + c = 0xf5; + if (c != 0) { + *r = c; + return 1; + } + return 0; +} diff --git a/libatalk/unicode/iconv.c b/libatalk/unicode/iconv.c new file mode 100644 index 0000000..c44df31 --- /dev/null +++ b/libatalk/unicode/iconv.c @@ -0,0 +1,437 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_USABLE_ICONV +#include +#endif +#include + +#include +#include +#include + + +/** + * @file + * + * @brief Samba wrapper/stub for iconv character set conversion. + * + * iconv is the XPG2 interface for converting between character + * encodings. This file provides a Samba wrapper around it, and also + * a simple reimplementation that is used if the system does not + * implement iconv. + * + * Samba only works with encodings that are supersets of ASCII: ascii + * characters like whitespace can be tested for directly, multibyte + * sequences start with a byte with the high bit set, and strings are + * terminated by a nul byte. + * + * Note that the only function provided by iconv is conversion between + * characters. It doesn't directly support operations like + * uppercasing or comparison. We have to convert to UCS-2 and compare + * there. + * + * @sa Samba Developers Guide + **/ +#define CHARSET_WIDECHAR 32 + +#ifdef HAVE_USABLE_ICONV +#ifdef HAVE_UCS2INTERNAL +#define UCS2ICONV "UCS-2-INTERNAL" +#else /* !HAVE_UCS2INTERNAL */ +#if BYTE_ORDER==LITTLE_ENDIAN +#define UCS2ICONV "UCS-2LE" +#else /* !LITTLE_ENDIAN */ +#define UCS2ICONV "UCS-2BE" +#endif /* BYTE_ORDER */ +#endif /* HAVE_UCS2INTERNAL */ +#else /* !HAVE_USABLE_ICONV */ +#define UCS2ICONV "UCS-2" +#endif /* HAVE_USABLE_ICONV */ + +static size_t ascii_pull(void *,char **, size_t *, char **, size_t *); +static size_t ascii_push(void *,char **, size_t *, char **, size_t *); +static size_t iconv_copy(void *,char **, size_t *, char **, size_t *); + +extern struct charset_functions charset_mac_roman; +extern struct charset_functions charset_mac_hebrew; +extern struct charset_functions charset_mac_centraleurope; +extern struct charset_functions charset_mac_cyrillic; +extern struct charset_functions charset_mac_greek; +extern struct charset_functions charset_mac_turkish; +extern struct charset_functions charset_utf8; +extern struct charset_functions charset_utf8_mac; +#ifdef HAVE_USABLE_ICONV +extern struct charset_functions charset_mac_japanese; +extern struct charset_functions charset_mac_chinese_trad; +extern struct charset_functions charset_mac_korean; +extern struct charset_functions charset_mac_chinese_simp; +#endif + + +static struct charset_functions builtin_functions[] = { + {"UCS-2", 0, iconv_copy, iconv_copy, CHARSET_WIDECHAR | CHARSET_PRECOMPOSED, NULL, NULL, NULL}, + {"ASCII", 0, ascii_pull, ascii_push, CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED, NULL, NULL, NULL}, + {NULL, 0, NULL, NULL, 0, NULL, NULL, NULL} +}; + + +#define DLIST_ADD(list, p) \ +{ \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} + +static struct charset_functions *charsets = NULL; + +struct charset_functions *find_charset_functions(const char *name) +{ + struct charset_functions *c = charsets; + + while(c) { + if (strcasecmp(name, c->name) == 0) { + return c; + } + c = c->next; + } + + return NULL; +} + +int atalk_register_charset(struct charset_functions *funcs) +{ + if (!funcs) { + return -1; + } + + /* Check whether we already have this charset... */ + if (find_charset_functions(funcs->name)) { + LOG (log_debug, logtype_default, "Duplicate charset %s, not registering", funcs->name); + return -2; + } + + funcs->next = funcs->prev = NULL; + DLIST_ADD(charsets, funcs); + return 0; +} + +static void lazy_initialize_iconv(void) +{ + static int initialized = 0; + int i; + + if (!initialized) { + initialized = 1; + for(i = 0; builtin_functions[i].name; i++) + atalk_register_charset(&builtin_functions[i]); + + /* register additional charsets */ + atalk_register_charset(&charset_utf8); + atalk_register_charset(&charset_utf8_mac); + atalk_register_charset(&charset_mac_roman); + atalk_register_charset(&charset_mac_hebrew); + atalk_register_charset(&charset_mac_greek); + atalk_register_charset(&charset_mac_turkish); + atalk_register_charset(&charset_mac_centraleurope); + atalk_register_charset(&charset_mac_cyrillic); +#ifdef HAVE_USABLE_ICONV + atalk_register_charset(&charset_mac_japanese); + atalk_register_charset(&charset_mac_chinese_trad); + atalk_register_charset(&charset_mac_korean); + atalk_register_charset(&charset_mac_chinese_simp); +#endif + } +} + +/* if there was an error then reset the internal state, + this ensures that we don't have a shift state remaining for + character sets like SJIS */ +static size_t sys_iconv(void *cd, + char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ +#ifdef HAVE_USABLE_ICONV + size_t ret = iconv((iconv_t)cd, + (ICONV_CONST char**)inbuf, inbytesleft, + outbuf, outbytesleft); + if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); + return ret; +#else + errno = EINVAL; + return -1; +#endif +} + +/** + * This is a simple portable iconv() implementaion. + * + * It only knows about a very small number of character sets - just + * enough that netatalk works on systems that don't have iconv. + **/ +size_t atalk_iconv(atalk_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + char cvtbuf[2048]; + char *bufp = cvtbuf; + size_t bufsize; + + /* in many cases we can go direct */ + if (cd->direct) { + return cd->direct(cd->cd_direct, + (char **)inbuf, inbytesleft, outbuf, outbytesleft); + } + + + /* otherwise we have to do it chunks at a time */ + while (*inbytesleft > 0) { + bufp = cvtbuf; + bufsize = sizeof(cvtbuf); + + if (cd->pull(cd->cd_pull, (char **)inbuf, inbytesleft, &bufp, &bufsize) == (size_t)-1 + && errno != E2BIG) { + return -1; + } + + bufp = cvtbuf; + bufsize = sizeof(cvtbuf) - bufsize; + + if (cd->push(cd->cd_push, &bufp, &bufsize, outbuf, outbytesleft) == (size_t)-1) { + return -1; + } + } + + return 0; +} + + +/* + simple iconv_open() wrapper + */ +atalk_iconv_t atalk_iconv_open(const char *tocode, const char *fromcode) +{ + atalk_iconv_t ret; + struct charset_functions *from, *to; + + + lazy_initialize_iconv(); + from = charsets; + to = charsets; + + ret = (atalk_iconv_t)malloc(sizeof(*ret)); + if (!ret) { + errno = ENOMEM; + return (atalk_iconv_t)-1; + } + memset(ret, 0, sizeof(*ret)); + + ret->from_name = strdup(fromcode); + ret->to_name = strdup(tocode); + + /* check for the simplest null conversion */ + if (strcasecmp(fromcode, tocode) == 0) { + ret->direct = iconv_copy; + return ret; + } + + /* check if we have a builtin function for this conversion */ + from = find_charset_functions(fromcode); + if (from) ret->pull = from->pull; + + to = find_charset_functions(tocode); + if (to) ret->push = to->push; + + /* check if we can use iconv for this conversion */ +#ifdef HAVE_USABLE_ICONV + if (!from || (from->flags & CHARSET_ICONV)) { + ret->cd_pull = iconv_open(UCS2ICONV, from && from->iname ? from->iname : fromcode); + if (ret->cd_pull != (iconv_t)-1) { + if (!ret->pull) ret->pull = sys_iconv; + } else ret->pull = NULL; + } + if (ret->pull) { + if (!to || (to->flags & CHARSET_ICONV)) { + ret->cd_push = iconv_open(to && to->iname ? to->iname : tocode, UCS2ICONV); + if (ret->cd_push != (iconv_t)-1) { + if (!ret->push) ret->push = sys_iconv; + } else ret->push = NULL; + } + if (!ret->push && ret->cd_pull) iconv_close((iconv_t)ret->cd_pull); + } +#endif + + if (!ret->push || !ret->pull) { + SAFE_FREE(ret->from_name); + SAFE_FREE(ret->to_name); + SAFE_FREE(ret); + errno = EINVAL; + return (atalk_iconv_t)-1; + } + + /* check for conversion to/from ucs2 */ + if (strcasecmp(fromcode, "UCS-2") == 0) { + ret->direct = ret->push; + ret->cd_direct = ret->cd_push; + ret->cd_push = NULL; + } + if (strcasecmp(tocode, "UCS-2") == 0) { + ret->direct = ret->pull; + ret->cd_direct = ret->cd_pull; + ret->cd_pull = NULL; + } + + return ret; +} + +/* + simple iconv_close() wrapper +*/ +int atalk_iconv_close (atalk_iconv_t cd) +{ +#ifdef HAVE_USABLE_ICONV + if (cd->cd_direct) iconv_close((iconv_t)cd->cd_direct); + if (cd->cd_pull) iconv_close((iconv_t)cd->cd_pull); + if (cd->cd_push) iconv_close((iconv_t)cd->cd_push); +#endif + + SAFE_FREE(cd->from_name); + SAFE_FREE(cd->to_name); + + memset(cd, 0, sizeof(*cd)); + SAFE_FREE(cd); + return 0; +} + + +/************************************************************************ + the following functions implement the builtin character sets in Netatalk +*************************************************************************/ + +static size_t ascii_pull(void *cd _U_, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + ucs2_t curchar; + + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + if ((unsigned char)(*inbuf)[0] < 0x80) { + curchar = (ucs2_t) (*inbuf)[0]; + SSVAL((*outbuf),0,curchar); + } + else { + errno = EILSEQ; + return -1; + } + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t ascii_push(void *cd _U_, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + ucs2_t curchar; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + curchar = SVAL((*inbuf), 0); + if (curchar < 0x0080) { + (*outbuf)[0] = curchar; + } + else { + errno = EILSEQ; + return -1; + } + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} + + +static size_t iconv_copy(void *cd _U_, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + memmove(*outbuf, *inbuf, n); + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +/* ------------------------ */ diff --git a/libatalk/unicode/precompose.h b/libatalk/unicode/precompose.h new file mode 100644 index 0000000..cbf1a39 --- /dev/null +++ b/libatalk/unicode/precompose.h @@ -0,0 +1,2156 @@ +/* DO NOT EDIT BY HAND!!! */ +/* This file is generated by */ +/* contrib/shell_utils/make-precompose.h.pl UnicodeData.txt */ + +/* UnicodeData.txt is got from */ +/* http://www.unicode.org/Public/UNIDATA/UnicodeData.txt */ + +#define SBASE 0xAC00 +#define LBASE 0x1100 +#define VBASE 0x1161 +#define TBASE 0x11A7 +#define LCOUNT 19 +#define VCOUNT 21 +#define TCOUNT 28 +#define NCOUNT 588 /* (VCOUNT * TCOUNT) */ +#define SCOUNT 11172 /* (LCOUNT * NCOUNT) */ + +#define PRECOMP_COUNT 955 +#define DECOMP_COUNT 955 +#define MAXCOMBLEN 3 + +#define PRECOMP_SP_COUNT 25 +#define DECOMP_SP_COUNT 25 +#define MAXCOMBSPLEN 4 + +#define COMBBUFLEN 4 /* max(MAXCOMBLEN,MAXCOMBSPLEN) */ + +static const struct { + unsigned int replacement; + unsigned int base; + unsigned int comb; +} precompositions[] = { +/*{ 0x0000226E, 0x0000003C, 0x00000338 },*/ /* NOT LESS-THAN */ +/*{ 0x00002260, 0x0000003D, 0x00000338 },*/ /* NOT EQUAL TO */ +/*{ 0x0000226F, 0x0000003E, 0x00000338 },*/ /* NOT GREATER-THAN */ + { 0x000000C0, 0x00000041, 0x00000300 }, /* LATIN CAPITAL LETTER A WITH GRAVE */ + { 0x000000C1, 0x00000041, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH ACUTE */ + { 0x000000C2, 0x00000041, 0x00000302 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ + { 0x000000C3, 0x00000041, 0x00000303 }, /* LATIN CAPITAL LETTER A WITH TILDE */ + { 0x00000100, 0x00000041, 0x00000304 }, /* LATIN CAPITAL LETTER A WITH MACRON */ + { 0x00000102, 0x00000041, 0x00000306 }, /* LATIN CAPITAL LETTER A WITH BREVE */ + { 0x00000226, 0x00000041, 0x00000307 }, /* LATIN CAPITAL LETTER A WITH DOT ABOVE */ + { 0x000000C4, 0x00000041, 0x00000308 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */ + { 0x00001EA2, 0x00000041, 0x00000309 }, /* LATIN CAPITAL LETTER A WITH HOOK ABOVE */ + { 0x000000C5, 0x00000041, 0x0000030A }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */ + { 0x000001CD, 0x00000041, 0x0000030C }, /* LATIN CAPITAL LETTER A WITH CARON */ + { 0x00000200, 0x00000041, 0x0000030F }, /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE */ + { 0x00000202, 0x00000041, 0x00000311 }, /* LATIN CAPITAL LETTER A WITH INVERTED BREVE */ + { 0x00001EA0, 0x00000041, 0x00000323 }, /* LATIN CAPITAL LETTER A WITH DOT BELOW */ + { 0x00001E00, 0x00000041, 0x00000325 }, /* LATIN CAPITAL LETTER A WITH RING BELOW */ + { 0x00000104, 0x00000041, 0x00000328 }, /* LATIN CAPITAL LETTER A WITH OGONEK */ + { 0x00001E02, 0x00000042, 0x00000307 }, /* LATIN CAPITAL LETTER B WITH DOT ABOVE */ + { 0x00001E04, 0x00000042, 0x00000323 }, /* LATIN CAPITAL LETTER B WITH DOT BELOW */ + { 0x00001E06, 0x00000042, 0x00000331 }, /* LATIN CAPITAL LETTER B WITH LINE BELOW */ + { 0x00000106, 0x00000043, 0x00000301 }, /* LATIN CAPITAL LETTER C WITH ACUTE */ + { 0x00000108, 0x00000043, 0x00000302 }, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + { 0x0000010A, 0x00000043, 0x00000307 }, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */ + { 0x0000010C, 0x00000043, 0x0000030C }, /* LATIN CAPITAL LETTER C WITH CARON */ + { 0x000000C7, 0x00000043, 0x00000327 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */ + { 0x00001E0A, 0x00000044, 0x00000307 }, /* LATIN CAPITAL LETTER D WITH DOT ABOVE */ + { 0x0000010E, 0x00000044, 0x0000030C }, /* LATIN CAPITAL LETTER D WITH CARON */ + { 0x00001E0C, 0x00000044, 0x00000323 }, /* LATIN CAPITAL LETTER D WITH DOT BELOW */ + { 0x00001E10, 0x00000044, 0x00000327 }, /* LATIN CAPITAL LETTER D WITH CEDILLA */ + { 0x00001E12, 0x00000044, 0x0000032D }, /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW */ + { 0x00001E0E, 0x00000044, 0x00000331 }, /* LATIN CAPITAL LETTER D WITH LINE BELOW */ + { 0x000000C8, 0x00000045, 0x00000300 }, /* LATIN CAPITAL LETTER E WITH GRAVE */ + { 0x000000C9, 0x00000045, 0x00000301 }, /* LATIN CAPITAL LETTER E WITH ACUTE */ + { 0x000000CA, 0x00000045, 0x00000302 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ + { 0x00001EBC, 0x00000045, 0x00000303 }, /* LATIN CAPITAL LETTER E WITH TILDE */ + { 0x00000112, 0x00000045, 0x00000304 }, /* LATIN CAPITAL LETTER E WITH MACRON */ + { 0x00000114, 0x00000045, 0x00000306 }, /* LATIN CAPITAL LETTER E WITH BREVE */ + { 0x00000116, 0x00000045, 0x00000307 }, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ + { 0x000000CB, 0x00000045, 0x00000308 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */ + { 0x00001EBA, 0x00000045, 0x00000309 }, /* LATIN CAPITAL LETTER E WITH HOOK ABOVE */ + { 0x0000011A, 0x00000045, 0x0000030C }, /* LATIN CAPITAL LETTER E WITH CARON */ + { 0x00000204, 0x00000045, 0x0000030F }, /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE */ + { 0x00000206, 0x00000045, 0x00000311 }, /* LATIN CAPITAL LETTER E WITH INVERTED BREVE */ + { 0x00001EB8, 0x00000045, 0x00000323 }, /* LATIN CAPITAL LETTER E WITH DOT BELOW */ + { 0x00000228, 0x00000045, 0x00000327 }, /* LATIN CAPITAL LETTER E WITH CEDILLA */ + { 0x00000118, 0x00000045, 0x00000328 }, /* LATIN CAPITAL LETTER E WITH OGONEK */ + { 0x00001E18, 0x00000045, 0x0000032D }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW */ + { 0x00001E1A, 0x00000045, 0x00000330 }, /* LATIN CAPITAL LETTER E WITH TILDE BELOW */ + { 0x00001E1E, 0x00000046, 0x00000307 }, /* LATIN CAPITAL LETTER F WITH DOT ABOVE */ + { 0x000001F4, 0x00000047, 0x00000301 }, /* LATIN CAPITAL LETTER G WITH ACUTE */ + { 0x0000011C, 0x00000047, 0x00000302 }, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + { 0x00001E20, 0x00000047, 0x00000304 }, /* LATIN CAPITAL LETTER G WITH MACRON */ + { 0x0000011E, 0x00000047, 0x00000306 }, /* LATIN CAPITAL LETTER G WITH BREVE */ + { 0x00000120, 0x00000047, 0x00000307 }, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */ + { 0x000001E6, 0x00000047, 0x0000030C }, /* LATIN CAPITAL LETTER G WITH CARON */ + { 0x00000122, 0x00000047, 0x00000327 }, /* LATIN CAPITAL LETTER G WITH CEDILLA */ + { 0x00000124, 0x00000048, 0x00000302 }, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + { 0x00001E22, 0x00000048, 0x00000307 }, /* LATIN CAPITAL LETTER H WITH DOT ABOVE */ + { 0x00001E26, 0x00000048, 0x00000308 }, /* LATIN CAPITAL LETTER H WITH DIAERESIS */ + { 0x0000021E, 0x00000048, 0x0000030C }, /* LATIN CAPITAL LETTER H WITH CARON */ + { 0x00001E24, 0x00000048, 0x00000323 }, /* LATIN CAPITAL LETTER H WITH DOT BELOW */ + { 0x00001E28, 0x00000048, 0x00000327 }, /* LATIN CAPITAL LETTER H WITH CEDILLA */ + { 0x00001E2A, 0x00000048, 0x0000032E }, /* LATIN CAPITAL LETTER H WITH BREVE BELOW */ + { 0x000000CC, 0x00000049, 0x00000300 }, /* LATIN CAPITAL LETTER I WITH GRAVE */ + { 0x000000CD, 0x00000049, 0x00000301 }, /* LATIN CAPITAL LETTER I WITH ACUTE */ + { 0x000000CE, 0x00000049, 0x00000302 }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ + { 0x00000128, 0x00000049, 0x00000303 }, /* LATIN CAPITAL LETTER I WITH TILDE */ + { 0x0000012A, 0x00000049, 0x00000304 }, /* LATIN CAPITAL LETTER I WITH MACRON */ + { 0x0000012C, 0x00000049, 0x00000306 }, /* LATIN CAPITAL LETTER I WITH BREVE */ + { 0x00000130, 0x00000049, 0x00000307 }, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ + { 0x000000CF, 0x00000049, 0x00000308 }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */ + { 0x00001EC8, 0x00000049, 0x00000309 }, /* LATIN CAPITAL LETTER I WITH HOOK ABOVE */ + { 0x000001CF, 0x00000049, 0x0000030C }, /* LATIN CAPITAL LETTER I WITH CARON */ + { 0x00000208, 0x00000049, 0x0000030F }, /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE */ + { 0x0000020A, 0x00000049, 0x00000311 }, /* LATIN CAPITAL LETTER I WITH INVERTED BREVE */ + { 0x00001ECA, 0x00000049, 0x00000323 }, /* LATIN CAPITAL LETTER I WITH DOT BELOW */ + { 0x0000012E, 0x00000049, 0x00000328 }, /* LATIN CAPITAL LETTER I WITH OGONEK */ + { 0x00001E2C, 0x00000049, 0x00000330 }, /* LATIN CAPITAL LETTER I WITH TILDE BELOW */ + { 0x00000134, 0x0000004A, 0x00000302 }, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + { 0x00001E30, 0x0000004B, 0x00000301 }, /* LATIN CAPITAL LETTER K WITH ACUTE */ + { 0x000001E8, 0x0000004B, 0x0000030C }, /* LATIN CAPITAL LETTER K WITH CARON */ + { 0x00001E32, 0x0000004B, 0x00000323 }, /* LATIN CAPITAL LETTER K WITH DOT BELOW */ + { 0x00000136, 0x0000004B, 0x00000327 }, /* LATIN CAPITAL LETTER K WITH CEDILLA */ + { 0x00001E34, 0x0000004B, 0x00000331 }, /* LATIN CAPITAL LETTER K WITH LINE BELOW */ + { 0x00000139, 0x0000004C, 0x00000301 }, /* LATIN CAPITAL LETTER L WITH ACUTE */ + { 0x0000013D, 0x0000004C, 0x0000030C }, /* LATIN CAPITAL LETTER L WITH CARON */ + { 0x00001E36, 0x0000004C, 0x00000323 }, /* LATIN CAPITAL LETTER L WITH DOT BELOW */ + { 0x0000013B, 0x0000004C, 0x00000327 }, /* LATIN CAPITAL LETTER L WITH CEDILLA */ + { 0x00001E3C, 0x0000004C, 0x0000032D }, /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW */ + { 0x00001E3A, 0x0000004C, 0x00000331 }, /* LATIN CAPITAL LETTER L WITH LINE BELOW */ + { 0x00001E3E, 0x0000004D, 0x00000301 }, /* LATIN CAPITAL LETTER M WITH ACUTE */ + { 0x00001E40, 0x0000004D, 0x00000307 }, /* LATIN CAPITAL LETTER M WITH DOT ABOVE */ + { 0x00001E42, 0x0000004D, 0x00000323 }, /* LATIN CAPITAL LETTER M WITH DOT BELOW */ + { 0x000001F8, 0x0000004E, 0x00000300 }, /* LATIN CAPITAL LETTER N WITH GRAVE */ + { 0x00000143, 0x0000004E, 0x00000301 }, /* LATIN CAPITAL LETTER N WITH ACUTE */ + { 0x000000D1, 0x0000004E, 0x00000303 }, /* LATIN CAPITAL LETTER N WITH TILDE */ + { 0x00001E44, 0x0000004E, 0x00000307 }, /* LATIN CAPITAL LETTER N WITH DOT ABOVE */ + { 0x00000147, 0x0000004E, 0x0000030C }, /* LATIN CAPITAL LETTER N WITH CARON */ + { 0x00001E46, 0x0000004E, 0x00000323 }, /* LATIN CAPITAL LETTER N WITH DOT BELOW */ + { 0x00000145, 0x0000004E, 0x00000327 }, /* LATIN CAPITAL LETTER N WITH CEDILLA */ + { 0x00001E4A, 0x0000004E, 0x0000032D }, /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW */ + { 0x00001E48, 0x0000004E, 0x00000331 }, /* LATIN CAPITAL LETTER N WITH LINE BELOW */ + { 0x000000D2, 0x0000004F, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH GRAVE */ + { 0x000000D3, 0x0000004F, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH ACUTE */ + { 0x000000D4, 0x0000004F, 0x00000302 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ + { 0x000000D5, 0x0000004F, 0x00000303 }, /* LATIN CAPITAL LETTER O WITH TILDE */ + { 0x0000014C, 0x0000004F, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH MACRON */ + { 0x0000014E, 0x0000004F, 0x00000306 }, /* LATIN CAPITAL LETTER O WITH BREVE */ + { 0x0000022E, 0x0000004F, 0x00000307 }, /* LATIN CAPITAL LETTER O WITH DOT ABOVE */ + { 0x000000D6, 0x0000004F, 0x00000308 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */ + { 0x00001ECE, 0x0000004F, 0x00000309 }, /* LATIN CAPITAL LETTER O WITH HOOK ABOVE */ + { 0x00000150, 0x0000004F, 0x0000030B }, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + { 0x000001D1, 0x0000004F, 0x0000030C }, /* LATIN CAPITAL LETTER O WITH CARON */ + { 0x0000020C, 0x0000004F, 0x0000030F }, /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE */ + { 0x0000020E, 0x0000004F, 0x00000311 }, /* LATIN CAPITAL LETTER O WITH INVERTED BREVE */ + { 0x000001A0, 0x0000004F, 0x0000031B }, /* LATIN CAPITAL LETTER O WITH HORN */ + { 0x00001ECC, 0x0000004F, 0x00000323 }, /* LATIN CAPITAL LETTER O WITH DOT BELOW */ + { 0x000001EA, 0x0000004F, 0x00000328 }, /* LATIN CAPITAL LETTER O WITH OGONEK */ + { 0x00001E54, 0x00000050, 0x00000301 }, /* LATIN CAPITAL LETTER P WITH ACUTE */ + { 0x00001E56, 0x00000050, 0x00000307 }, /* LATIN CAPITAL LETTER P WITH DOT ABOVE */ + { 0x00000154, 0x00000052, 0x00000301 }, /* LATIN CAPITAL LETTER R WITH ACUTE */ + { 0x00001E58, 0x00000052, 0x00000307 }, /* LATIN CAPITAL LETTER R WITH DOT ABOVE */ + { 0x00000158, 0x00000052, 0x0000030C }, /* LATIN CAPITAL LETTER R WITH CARON */ + { 0x00000210, 0x00000052, 0x0000030F }, /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE */ + { 0x00000212, 0x00000052, 0x00000311 }, /* LATIN CAPITAL LETTER R WITH INVERTED BREVE */ + { 0x00001E5A, 0x00000052, 0x00000323 }, /* LATIN CAPITAL LETTER R WITH DOT BELOW */ + { 0x00000156, 0x00000052, 0x00000327 }, /* LATIN CAPITAL LETTER R WITH CEDILLA */ + { 0x00001E5E, 0x00000052, 0x00000331 }, /* LATIN CAPITAL LETTER R WITH LINE BELOW */ + { 0x0000015A, 0x00000053, 0x00000301 }, /* LATIN CAPITAL LETTER S WITH ACUTE */ + { 0x0000015C, 0x00000053, 0x00000302 }, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + { 0x00001E60, 0x00000053, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH DOT ABOVE */ + { 0x00000160, 0x00000053, 0x0000030C }, /* LATIN CAPITAL LETTER S WITH CARON */ + { 0x00001E62, 0x00000053, 0x00000323 }, /* LATIN CAPITAL LETTER S WITH DOT BELOW */ + { 0x00000218, 0x00000053, 0x00000326 }, /* LATIN CAPITAL LETTER S WITH COMMA BELOW */ + { 0x0000015E, 0x00000053, 0x00000327 }, /* LATIN CAPITAL LETTER S WITH CEDILLA */ + { 0x00001E6A, 0x00000054, 0x00000307 }, /* LATIN CAPITAL LETTER T WITH DOT ABOVE */ + { 0x00000164, 0x00000054, 0x0000030C }, /* LATIN CAPITAL LETTER T WITH CARON */ + { 0x00001E6C, 0x00000054, 0x00000323 }, /* LATIN CAPITAL LETTER T WITH DOT BELOW */ + { 0x0000021A, 0x00000054, 0x00000326 }, /* LATIN CAPITAL LETTER T WITH COMMA BELOW */ + { 0x00000162, 0x00000054, 0x00000327 }, /* LATIN CAPITAL LETTER T WITH CEDILLA */ + { 0x00001E70, 0x00000054, 0x0000032D }, /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW */ + { 0x00001E6E, 0x00000054, 0x00000331 }, /* LATIN CAPITAL LETTER T WITH LINE BELOW */ + { 0x000000D9, 0x00000055, 0x00000300 }, /* LATIN CAPITAL LETTER U WITH GRAVE */ + { 0x000000DA, 0x00000055, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH ACUTE */ + { 0x000000DB, 0x00000055, 0x00000302 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ + { 0x00000168, 0x00000055, 0x00000303 }, /* LATIN CAPITAL LETTER U WITH TILDE */ + { 0x0000016A, 0x00000055, 0x00000304 }, /* LATIN CAPITAL LETTER U WITH MACRON */ + { 0x0000016C, 0x00000055, 0x00000306 }, /* LATIN CAPITAL LETTER U WITH BREVE */ + { 0x000000DC, 0x00000055, 0x00000308 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */ + { 0x00001EE6, 0x00000055, 0x00000309 }, /* LATIN CAPITAL LETTER U WITH HOOK ABOVE */ + { 0x0000016E, 0x00000055, 0x0000030A }, /* LATIN CAPITAL LETTER U WITH RING ABOVE */ + { 0x00000170, 0x00000055, 0x0000030B }, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x000001D3, 0x00000055, 0x0000030C }, /* LATIN CAPITAL LETTER U WITH CARON */ + { 0x00000214, 0x00000055, 0x0000030F }, /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE */ + { 0x00000216, 0x00000055, 0x00000311 }, /* LATIN CAPITAL LETTER U WITH INVERTED BREVE */ + { 0x000001AF, 0x00000055, 0x0000031B }, /* LATIN CAPITAL LETTER U WITH HORN */ + { 0x00001EE4, 0x00000055, 0x00000323 }, /* LATIN CAPITAL LETTER U WITH DOT BELOW */ + { 0x00001E72, 0x00000055, 0x00000324 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW */ + { 0x00000172, 0x00000055, 0x00000328 }, /* LATIN CAPITAL LETTER U WITH OGONEK */ + { 0x00001E76, 0x00000055, 0x0000032D }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW */ + { 0x00001E74, 0x00000055, 0x00000330 }, /* LATIN CAPITAL LETTER U WITH TILDE BELOW */ + { 0x00001E7C, 0x00000056, 0x00000303 }, /* LATIN CAPITAL LETTER V WITH TILDE */ + { 0x00001E7E, 0x00000056, 0x00000323 }, /* LATIN CAPITAL LETTER V WITH DOT BELOW */ + { 0x00001E80, 0x00000057, 0x00000300 }, /* LATIN CAPITAL LETTER W WITH GRAVE */ + { 0x00001E82, 0x00000057, 0x00000301 }, /* LATIN CAPITAL LETTER W WITH ACUTE */ + { 0x00000174, 0x00000057, 0x00000302 }, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ + { 0x00001E86, 0x00000057, 0x00000307 }, /* LATIN CAPITAL LETTER W WITH DOT ABOVE */ + { 0x00001E84, 0x00000057, 0x00000308 }, /* LATIN CAPITAL LETTER W WITH DIAERESIS */ + { 0x00001E88, 0x00000057, 0x00000323 }, /* LATIN CAPITAL LETTER W WITH DOT BELOW */ + { 0x00001E8A, 0x00000058, 0x00000307 }, /* LATIN CAPITAL LETTER X WITH DOT ABOVE */ + { 0x00001E8C, 0x00000058, 0x00000308 }, /* LATIN CAPITAL LETTER X WITH DIAERESIS */ + { 0x00001EF2, 0x00000059, 0x00000300 }, /* LATIN CAPITAL LETTER Y WITH GRAVE */ + { 0x000000DD, 0x00000059, 0x00000301 }, /* LATIN CAPITAL LETTER Y WITH ACUTE */ + { 0x00000176, 0x00000059, 0x00000302 }, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ + { 0x00001EF8, 0x00000059, 0x00000303 }, /* LATIN CAPITAL LETTER Y WITH TILDE */ + { 0x00000232, 0x00000059, 0x00000304 }, /* LATIN CAPITAL LETTER Y WITH MACRON */ + { 0x00001E8E, 0x00000059, 0x00000307 }, /* LATIN CAPITAL LETTER Y WITH DOT ABOVE */ + { 0x00000178, 0x00000059, 0x00000308 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ + { 0x00001EF6, 0x00000059, 0x00000309 }, /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ + { 0x00001EF4, 0x00000059, 0x00000323 }, /* LATIN CAPITAL LETTER Y WITH DOT BELOW */ + { 0x00000179, 0x0000005A, 0x00000301 }, /* LATIN CAPITAL LETTER Z WITH ACUTE */ + { 0x00001E90, 0x0000005A, 0x00000302 }, /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX */ + { 0x0000017B, 0x0000005A, 0x00000307 }, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + { 0x0000017D, 0x0000005A, 0x0000030C }, /* LATIN CAPITAL LETTER Z WITH CARON */ + { 0x00001E92, 0x0000005A, 0x00000323 }, /* LATIN CAPITAL LETTER Z WITH DOT BELOW */ + { 0x00001E94, 0x0000005A, 0x00000331 }, /* LATIN CAPITAL LETTER Z WITH LINE BELOW */ + { 0x000000E0, 0x00000061, 0x00000300 }, /* LATIN SMALL LETTER A WITH GRAVE */ + { 0x000000E1, 0x00000061, 0x00000301 }, /* LATIN SMALL LETTER A WITH ACUTE */ + { 0x000000E2, 0x00000061, 0x00000302 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */ + { 0x000000E3, 0x00000061, 0x00000303 }, /* LATIN SMALL LETTER A WITH TILDE */ + { 0x00000101, 0x00000061, 0x00000304 }, /* LATIN SMALL LETTER A WITH MACRON */ + { 0x00000103, 0x00000061, 0x00000306 }, /* LATIN SMALL LETTER A WITH BREVE */ + { 0x00000227, 0x00000061, 0x00000307 }, /* LATIN SMALL LETTER A WITH DOT ABOVE */ + { 0x000000E4, 0x00000061, 0x00000308 }, /* LATIN SMALL LETTER A WITH DIAERESIS */ + { 0x00001EA3, 0x00000061, 0x00000309 }, /* LATIN SMALL LETTER A WITH HOOK ABOVE */ + { 0x000000E5, 0x00000061, 0x0000030A }, /* LATIN SMALL LETTER A WITH RING ABOVE */ + { 0x000001CE, 0x00000061, 0x0000030C }, /* LATIN SMALL LETTER A WITH CARON */ + { 0x00000201, 0x00000061, 0x0000030F }, /* LATIN SMALL LETTER A WITH DOUBLE GRAVE */ + { 0x00000203, 0x00000061, 0x00000311 }, /* LATIN SMALL LETTER A WITH INVERTED BREVE */ + { 0x00001EA1, 0x00000061, 0x00000323 }, /* LATIN SMALL LETTER A WITH DOT BELOW */ + { 0x00001E01, 0x00000061, 0x00000325 }, /* LATIN SMALL LETTER A WITH RING BELOW */ + { 0x00000105, 0x00000061, 0x00000328 }, /* LATIN SMALL LETTER A WITH OGONEK */ + { 0x00001E03, 0x00000062, 0x00000307 }, /* LATIN SMALL LETTER B WITH DOT ABOVE */ + { 0x00001E05, 0x00000062, 0x00000323 }, /* LATIN SMALL LETTER B WITH DOT BELOW */ + { 0x00001E07, 0x00000062, 0x00000331 }, /* LATIN SMALL LETTER B WITH LINE BELOW */ + { 0x00000107, 0x00000063, 0x00000301 }, /* LATIN SMALL LETTER C WITH ACUTE */ + { 0x00000109, 0x00000063, 0x00000302 }, /* LATIN SMALL LETTER C WITH CIRCUMFLEX */ + { 0x0000010B, 0x00000063, 0x00000307 }, /* LATIN SMALL LETTER C WITH DOT ABOVE */ + { 0x0000010D, 0x00000063, 0x0000030C }, /* LATIN SMALL LETTER C WITH CARON */ + { 0x000000E7, 0x00000063, 0x00000327 }, /* LATIN SMALL LETTER C WITH CEDILLA */ + { 0x00001E0B, 0x00000064, 0x00000307 }, /* LATIN SMALL LETTER D WITH DOT ABOVE */ + { 0x0000010F, 0x00000064, 0x0000030C }, /* LATIN SMALL LETTER D WITH CARON */ + { 0x00001E0D, 0x00000064, 0x00000323 }, /* LATIN SMALL LETTER D WITH DOT BELOW */ + { 0x00001E11, 0x00000064, 0x00000327 }, /* LATIN SMALL LETTER D WITH CEDILLA */ + { 0x00001E13, 0x00000064, 0x0000032D }, /* LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW */ + { 0x00001E0F, 0x00000064, 0x00000331 }, /* LATIN SMALL LETTER D WITH LINE BELOW */ + { 0x000000E8, 0x00000065, 0x00000300 }, /* LATIN SMALL LETTER E WITH GRAVE */ + { 0x000000E9, 0x00000065, 0x00000301 }, /* LATIN SMALL LETTER E WITH ACUTE */ + { 0x000000EA, 0x00000065, 0x00000302 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */ + { 0x00001EBD, 0x00000065, 0x00000303 }, /* LATIN SMALL LETTER E WITH TILDE */ + { 0x00000113, 0x00000065, 0x00000304 }, /* LATIN SMALL LETTER E WITH MACRON */ + { 0x00000115, 0x00000065, 0x00000306 }, /* LATIN SMALL LETTER E WITH BREVE */ + { 0x00000117, 0x00000065, 0x00000307 }, /* LATIN SMALL LETTER E WITH DOT ABOVE */ + { 0x000000EB, 0x00000065, 0x00000308 }, /* LATIN SMALL LETTER E WITH DIAERESIS */ + { 0x00001EBB, 0x00000065, 0x00000309 }, /* LATIN SMALL LETTER E WITH HOOK ABOVE */ + { 0x0000011B, 0x00000065, 0x0000030C }, /* LATIN SMALL LETTER E WITH CARON */ + { 0x00000205, 0x00000065, 0x0000030F }, /* LATIN SMALL LETTER E WITH DOUBLE GRAVE */ + { 0x00000207, 0x00000065, 0x00000311 }, /* LATIN SMALL LETTER E WITH INVERTED BREVE */ + { 0x00001EB9, 0x00000065, 0x00000323 }, /* LATIN SMALL LETTER E WITH DOT BELOW */ + { 0x00000229, 0x00000065, 0x00000327 }, /* LATIN SMALL LETTER E WITH CEDILLA */ + { 0x00000119, 0x00000065, 0x00000328 }, /* LATIN SMALL LETTER E WITH OGONEK */ + { 0x00001E19, 0x00000065, 0x0000032D }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW */ + { 0x00001E1B, 0x00000065, 0x00000330 }, /* LATIN SMALL LETTER E WITH TILDE BELOW */ + { 0x00001E1F, 0x00000066, 0x00000307 }, /* LATIN SMALL LETTER F WITH DOT ABOVE */ + { 0x000001F5, 0x00000067, 0x00000301 }, /* LATIN SMALL LETTER G WITH ACUTE */ + { 0x0000011D, 0x00000067, 0x00000302 }, /* LATIN SMALL LETTER G WITH CIRCUMFLEX */ + { 0x00001E21, 0x00000067, 0x00000304 }, /* LATIN SMALL LETTER G WITH MACRON */ + { 0x0000011F, 0x00000067, 0x00000306 }, /* LATIN SMALL LETTER G WITH BREVE */ + { 0x00000121, 0x00000067, 0x00000307 }, /* LATIN SMALL LETTER G WITH DOT ABOVE */ + { 0x000001E7, 0x00000067, 0x0000030C }, /* LATIN SMALL LETTER G WITH CARON */ + { 0x00000123, 0x00000067, 0x00000327 }, /* LATIN SMALL LETTER G WITH CEDILLA */ + { 0x00000125, 0x00000068, 0x00000302 }, /* LATIN SMALL LETTER H WITH CIRCUMFLEX */ + { 0x00001E23, 0x00000068, 0x00000307 }, /* LATIN SMALL LETTER H WITH DOT ABOVE */ + { 0x00001E27, 0x00000068, 0x00000308 }, /* LATIN SMALL LETTER H WITH DIAERESIS */ + { 0x0000021F, 0x00000068, 0x0000030C }, /* LATIN SMALL LETTER H WITH CARON */ + { 0x00001E25, 0x00000068, 0x00000323 }, /* LATIN SMALL LETTER H WITH DOT BELOW */ + { 0x00001E29, 0x00000068, 0x00000327 }, /* LATIN SMALL LETTER H WITH CEDILLA */ + { 0x00001E2B, 0x00000068, 0x0000032E }, /* LATIN SMALL LETTER H WITH BREVE BELOW */ + { 0x00001E96, 0x00000068, 0x00000331 }, /* LATIN SMALL LETTER H WITH LINE BELOW */ + { 0x000000EC, 0x00000069, 0x00000300 }, /* LATIN SMALL LETTER I WITH GRAVE */ + { 0x000000ED, 0x00000069, 0x00000301 }, /* LATIN SMALL LETTER I WITH ACUTE */ + { 0x000000EE, 0x00000069, 0x00000302 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */ + { 0x00000129, 0x00000069, 0x00000303 }, /* LATIN SMALL LETTER I WITH TILDE */ + { 0x0000012B, 0x00000069, 0x00000304 }, /* LATIN SMALL LETTER I WITH MACRON */ + { 0x0000012D, 0x00000069, 0x00000306 }, /* LATIN SMALL LETTER I WITH BREVE */ + { 0x000000EF, 0x00000069, 0x00000308 }, /* LATIN SMALL LETTER I WITH DIAERESIS */ + { 0x00001EC9, 0x00000069, 0x00000309 }, /* LATIN SMALL LETTER I WITH HOOK ABOVE */ + { 0x000001D0, 0x00000069, 0x0000030C }, /* LATIN SMALL LETTER I WITH CARON */ + { 0x00000209, 0x00000069, 0x0000030F }, /* LATIN SMALL LETTER I WITH DOUBLE GRAVE */ + { 0x0000020B, 0x00000069, 0x00000311 }, /* LATIN SMALL LETTER I WITH INVERTED BREVE */ + { 0x00001ECB, 0x00000069, 0x00000323 }, /* LATIN SMALL LETTER I WITH DOT BELOW */ + { 0x0000012F, 0x00000069, 0x00000328 }, /* LATIN SMALL LETTER I WITH OGONEK */ + { 0x00001E2D, 0x00000069, 0x00000330 }, /* LATIN SMALL LETTER I WITH TILDE BELOW */ + { 0x00000135, 0x0000006A, 0x00000302 }, /* LATIN SMALL LETTER J WITH CIRCUMFLEX */ + { 0x000001F0, 0x0000006A, 0x0000030C }, /* LATIN SMALL LETTER J WITH CARON */ + { 0x00001E31, 0x0000006B, 0x00000301 }, /* LATIN SMALL LETTER K WITH ACUTE */ + { 0x000001E9, 0x0000006B, 0x0000030C }, /* LATIN SMALL LETTER K WITH CARON */ + { 0x00001E33, 0x0000006B, 0x00000323 }, /* LATIN SMALL LETTER K WITH DOT BELOW */ + { 0x00000137, 0x0000006B, 0x00000327 }, /* LATIN SMALL LETTER K WITH CEDILLA */ + { 0x00001E35, 0x0000006B, 0x00000331 }, /* LATIN SMALL LETTER K WITH LINE BELOW */ + { 0x0000013A, 0x0000006C, 0x00000301 }, /* LATIN SMALL LETTER L WITH ACUTE */ + { 0x0000013E, 0x0000006C, 0x0000030C }, /* LATIN SMALL LETTER L WITH CARON */ + { 0x00001E37, 0x0000006C, 0x00000323 }, /* LATIN SMALL LETTER L WITH DOT BELOW */ + { 0x0000013C, 0x0000006C, 0x00000327 }, /* LATIN SMALL LETTER L WITH CEDILLA */ + { 0x00001E3D, 0x0000006C, 0x0000032D }, /* LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW */ + { 0x00001E3B, 0x0000006C, 0x00000331 }, /* LATIN SMALL LETTER L WITH LINE BELOW */ + { 0x00001E3F, 0x0000006D, 0x00000301 }, /* LATIN SMALL LETTER M WITH ACUTE */ + { 0x00001E41, 0x0000006D, 0x00000307 }, /* LATIN SMALL LETTER M WITH DOT ABOVE */ + { 0x00001E43, 0x0000006D, 0x00000323 }, /* LATIN SMALL LETTER M WITH DOT BELOW */ + { 0x000001F9, 0x0000006E, 0x00000300 }, /* LATIN SMALL LETTER N WITH GRAVE */ + { 0x00000144, 0x0000006E, 0x00000301 }, /* LATIN SMALL LETTER N WITH ACUTE */ + { 0x000000F1, 0x0000006E, 0x00000303 }, /* LATIN SMALL LETTER N WITH TILDE */ + { 0x00001E45, 0x0000006E, 0x00000307 }, /* LATIN SMALL LETTER N WITH DOT ABOVE */ + { 0x00000148, 0x0000006E, 0x0000030C }, /* LATIN SMALL LETTER N WITH CARON */ + { 0x00001E47, 0x0000006E, 0x00000323 }, /* LATIN SMALL LETTER N WITH DOT BELOW */ + { 0x00000146, 0x0000006E, 0x00000327 }, /* LATIN SMALL LETTER N WITH CEDILLA */ + { 0x00001E4B, 0x0000006E, 0x0000032D }, /* LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW */ + { 0x00001E49, 0x0000006E, 0x00000331 }, /* LATIN SMALL LETTER N WITH LINE BELOW */ + { 0x000000F2, 0x0000006F, 0x00000300 }, /* LATIN SMALL LETTER O WITH GRAVE */ + { 0x000000F3, 0x0000006F, 0x00000301 }, /* LATIN SMALL LETTER O WITH ACUTE */ + { 0x000000F4, 0x0000006F, 0x00000302 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */ + { 0x000000F5, 0x0000006F, 0x00000303 }, /* LATIN SMALL LETTER O WITH TILDE */ + { 0x0000014D, 0x0000006F, 0x00000304 }, /* LATIN SMALL LETTER O WITH MACRON */ + { 0x0000014F, 0x0000006F, 0x00000306 }, /* LATIN SMALL LETTER O WITH BREVE */ + { 0x0000022F, 0x0000006F, 0x00000307 }, /* LATIN SMALL LETTER O WITH DOT ABOVE */ + { 0x000000F6, 0x0000006F, 0x00000308 }, /* LATIN SMALL LETTER O WITH DIAERESIS */ + { 0x00001ECF, 0x0000006F, 0x00000309 }, /* LATIN SMALL LETTER O WITH HOOK ABOVE */ + { 0x00000151, 0x0000006F, 0x0000030B }, /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + { 0x000001D2, 0x0000006F, 0x0000030C }, /* LATIN SMALL LETTER O WITH CARON */ + { 0x0000020D, 0x0000006F, 0x0000030F }, /* LATIN SMALL LETTER O WITH DOUBLE GRAVE */ + { 0x0000020F, 0x0000006F, 0x00000311 }, /* LATIN SMALL LETTER O WITH INVERTED BREVE */ + { 0x000001A1, 0x0000006F, 0x0000031B }, /* LATIN SMALL LETTER O WITH HORN */ + { 0x00001ECD, 0x0000006F, 0x00000323 }, /* LATIN SMALL LETTER O WITH DOT BELOW */ + { 0x000001EB, 0x0000006F, 0x00000328 }, /* LATIN SMALL LETTER O WITH OGONEK */ + { 0x00001E55, 0x00000070, 0x00000301 }, /* LATIN SMALL LETTER P WITH ACUTE */ + { 0x00001E57, 0x00000070, 0x00000307 }, /* LATIN SMALL LETTER P WITH DOT ABOVE */ + { 0x00000155, 0x00000072, 0x00000301 }, /* LATIN SMALL LETTER R WITH ACUTE */ + { 0x00001E59, 0x00000072, 0x00000307 }, /* LATIN SMALL LETTER R WITH DOT ABOVE */ + { 0x00000159, 0x00000072, 0x0000030C }, /* LATIN SMALL LETTER R WITH CARON */ + { 0x00000211, 0x00000072, 0x0000030F }, /* LATIN SMALL LETTER R WITH DOUBLE GRAVE */ + { 0x00000213, 0x00000072, 0x00000311 }, /* LATIN SMALL LETTER R WITH INVERTED BREVE */ + { 0x00001E5B, 0x00000072, 0x00000323 }, /* LATIN SMALL LETTER R WITH DOT BELOW */ + { 0x00000157, 0x00000072, 0x00000327 }, /* LATIN SMALL LETTER R WITH CEDILLA */ + { 0x00001E5F, 0x00000072, 0x00000331 }, /* LATIN SMALL LETTER R WITH LINE BELOW */ + { 0x0000015B, 0x00000073, 0x00000301 }, /* LATIN SMALL LETTER S WITH ACUTE */ + { 0x0000015D, 0x00000073, 0x00000302 }, /* LATIN SMALL LETTER S WITH CIRCUMFLEX */ + { 0x00001E61, 0x00000073, 0x00000307 }, /* LATIN SMALL LETTER S WITH DOT ABOVE */ + { 0x00000161, 0x00000073, 0x0000030C }, /* LATIN SMALL LETTER S WITH CARON */ + { 0x00001E63, 0x00000073, 0x00000323 }, /* LATIN SMALL LETTER S WITH DOT BELOW */ + { 0x00000219, 0x00000073, 0x00000326 }, /* LATIN SMALL LETTER S WITH COMMA BELOW */ + { 0x0000015F, 0x00000073, 0x00000327 }, /* LATIN SMALL LETTER S WITH CEDILLA */ + { 0x00001E6B, 0x00000074, 0x00000307 }, /* LATIN SMALL LETTER T WITH DOT ABOVE */ + { 0x00001E97, 0x00000074, 0x00000308 }, /* LATIN SMALL LETTER T WITH DIAERESIS */ + { 0x00000165, 0x00000074, 0x0000030C }, /* LATIN SMALL LETTER T WITH CARON */ + { 0x00001E6D, 0x00000074, 0x00000323 }, /* LATIN SMALL LETTER T WITH DOT BELOW */ + { 0x0000021B, 0x00000074, 0x00000326 }, /* LATIN SMALL LETTER T WITH COMMA BELOW */ + { 0x00000163, 0x00000074, 0x00000327 }, /* LATIN SMALL LETTER T WITH CEDILLA */ + { 0x00001E71, 0x00000074, 0x0000032D }, /* LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW */ + { 0x00001E6F, 0x00000074, 0x00000331 }, /* LATIN SMALL LETTER T WITH LINE BELOW */ + { 0x000000F9, 0x00000075, 0x00000300 }, /* LATIN SMALL LETTER U WITH GRAVE */ + { 0x000000FA, 0x00000075, 0x00000301 }, /* LATIN SMALL LETTER U WITH ACUTE */ + { 0x000000FB, 0x00000075, 0x00000302 }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */ + { 0x00000169, 0x00000075, 0x00000303 }, /* LATIN SMALL LETTER U WITH TILDE */ + { 0x0000016B, 0x00000075, 0x00000304 }, /* LATIN SMALL LETTER U WITH MACRON */ + { 0x0000016D, 0x00000075, 0x00000306 }, /* LATIN SMALL LETTER U WITH BREVE */ + { 0x000000FC, 0x00000075, 0x00000308 }, /* LATIN SMALL LETTER U WITH DIAERESIS */ + { 0x00001EE7, 0x00000075, 0x00000309 }, /* LATIN SMALL LETTER U WITH HOOK ABOVE */ + { 0x0000016F, 0x00000075, 0x0000030A }, /* LATIN SMALL LETTER U WITH RING ABOVE */ + { 0x00000171, 0x00000075, 0x0000030B }, /* LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x000001D4, 0x00000075, 0x0000030C }, /* LATIN SMALL LETTER U WITH CARON */ + { 0x00000215, 0x00000075, 0x0000030F }, /* LATIN SMALL LETTER U WITH DOUBLE GRAVE */ + { 0x00000217, 0x00000075, 0x00000311 }, /* LATIN SMALL LETTER U WITH INVERTED BREVE */ + { 0x000001B0, 0x00000075, 0x0000031B }, /* LATIN SMALL LETTER U WITH HORN */ + { 0x00001EE5, 0x00000075, 0x00000323 }, /* LATIN SMALL LETTER U WITH DOT BELOW */ + { 0x00001E73, 0x00000075, 0x00000324 }, /* LATIN SMALL LETTER U WITH DIAERESIS BELOW */ + { 0x00000173, 0x00000075, 0x00000328 }, /* LATIN SMALL LETTER U WITH OGONEK */ + { 0x00001E77, 0x00000075, 0x0000032D }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW */ + { 0x00001E75, 0x00000075, 0x00000330 }, /* LATIN SMALL LETTER U WITH TILDE BELOW */ + { 0x00001E7D, 0x00000076, 0x00000303 }, /* LATIN SMALL LETTER V WITH TILDE */ + { 0x00001E7F, 0x00000076, 0x00000323 }, /* LATIN SMALL LETTER V WITH DOT BELOW */ + { 0x00001E81, 0x00000077, 0x00000300 }, /* LATIN SMALL LETTER W WITH GRAVE */ + { 0x00001E83, 0x00000077, 0x00000301 }, /* LATIN SMALL LETTER W WITH ACUTE */ + { 0x00000175, 0x00000077, 0x00000302 }, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */ + { 0x00001E87, 0x00000077, 0x00000307 }, /* LATIN SMALL LETTER W WITH DOT ABOVE */ + { 0x00001E85, 0x00000077, 0x00000308 }, /* LATIN SMALL LETTER W WITH DIAERESIS */ + { 0x00001E98, 0x00000077, 0x0000030A }, /* LATIN SMALL LETTER W WITH RING ABOVE */ + { 0x00001E89, 0x00000077, 0x00000323 }, /* LATIN SMALL LETTER W WITH DOT BELOW */ + { 0x00001E8B, 0x00000078, 0x00000307 }, /* LATIN SMALL LETTER X WITH DOT ABOVE */ + { 0x00001E8D, 0x00000078, 0x00000308 }, /* LATIN SMALL LETTER X WITH DIAERESIS */ + { 0x00001EF3, 0x00000079, 0x00000300 }, /* LATIN SMALL LETTER Y WITH GRAVE */ + { 0x000000FD, 0x00000079, 0x00000301 }, /* LATIN SMALL LETTER Y WITH ACUTE */ + { 0x00000177, 0x00000079, 0x00000302 }, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */ + { 0x00001EF9, 0x00000079, 0x00000303 }, /* LATIN SMALL LETTER Y WITH TILDE */ + { 0x00000233, 0x00000079, 0x00000304 }, /* LATIN SMALL LETTER Y WITH MACRON */ + { 0x00001E8F, 0x00000079, 0x00000307 }, /* LATIN SMALL LETTER Y WITH DOT ABOVE */ + { 0x000000FF, 0x00000079, 0x00000308 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */ + { 0x00001EF7, 0x00000079, 0x00000309 }, /* LATIN SMALL LETTER Y WITH HOOK ABOVE */ + { 0x00001E99, 0x00000079, 0x0000030A }, /* LATIN SMALL LETTER Y WITH RING ABOVE */ + { 0x00001EF5, 0x00000079, 0x00000323 }, /* LATIN SMALL LETTER Y WITH DOT BELOW */ + { 0x0000017A, 0x0000007A, 0x00000301 }, /* LATIN SMALL LETTER Z WITH ACUTE */ + { 0x00001E91, 0x0000007A, 0x00000302 }, /* LATIN SMALL LETTER Z WITH CIRCUMFLEX */ + { 0x0000017C, 0x0000007A, 0x00000307 }, /* LATIN SMALL LETTER Z WITH DOT ABOVE */ + { 0x0000017E, 0x0000007A, 0x0000030C }, /* LATIN SMALL LETTER Z WITH CARON */ + { 0x00001E93, 0x0000007A, 0x00000323 }, /* LATIN SMALL LETTER Z WITH DOT BELOW */ + { 0x00001E95, 0x0000007A, 0x00000331 }, /* LATIN SMALL LETTER Z WITH LINE BELOW */ + { 0x00001FED, 0x000000A8, 0x00000300 }, /* GREEK DIALYTIKA AND VARIA */ + { 0x00000385, 0x000000A8, 0x00000301 }, /* GREEK DIALYTIKA TONOS */ + { 0x00001FC1, 0x000000A8, 0x00000342 }, /* GREEK DIALYTIKA AND PERISPOMENI */ + { 0x00001EA6, 0x000000C2, 0x00000300 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EA4, 0x000000C2, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EAA, 0x000000C2, 0x00000303 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ + { 0x00001EA8, 0x000000C2, 0x00000309 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x000001DE, 0x000000C4, 0x00000304 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON */ + { 0x000001FA, 0x000000C5, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE */ + { 0x000001FC, 0x000000C6, 0x00000301 }, /* LATIN CAPITAL LETTER AE WITH ACUTE */ + { 0x000001E2, 0x000000C6, 0x00000304 }, /* LATIN CAPITAL LETTER AE WITH MACRON */ + { 0x00001E08, 0x000000C7, 0x00000301 }, /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE */ + { 0x00001EC0, 0x000000CA, 0x00000300 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EBE, 0x000000CA, 0x00000301 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EC4, 0x000000CA, 0x00000303 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ + { 0x00001EC2, 0x000000CA, 0x00000309 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001E2E, 0x000000CF, 0x00000301 }, /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE */ + { 0x00001ED2, 0x000000D4, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ + { 0x00001ED0, 0x000000D4, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ + { 0x00001ED6, 0x000000D4, 0x00000303 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ + { 0x00001ED4, 0x000000D4, 0x00000309 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001E4C, 0x000000D5, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE */ + { 0x0000022C, 0x000000D5, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH TILDE AND MACRON */ + { 0x00001E4E, 0x000000D5, 0x00000308 }, /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS */ + { 0x0000022A, 0x000000D6, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON */ + { 0x000001FE, 0x000000D8, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE */ + { 0x000001DB, 0x000000DC, 0x00000300 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE */ + { 0x000001D7, 0x000000DC, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE */ + { 0x000001D5, 0x000000DC, 0x00000304 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON */ + { 0x000001D9, 0x000000DC, 0x0000030C }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON */ + { 0x00001EA7, 0x000000E2, 0x00000300 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EA5, 0x000000E2, 0x00000301 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EAB, 0x000000E2, 0x00000303 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */ + { 0x00001EA9, 0x000000E2, 0x00000309 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x000001DF, 0x000000E4, 0x00000304 }, /* LATIN SMALL LETTER A WITH DIAERESIS AND MACRON */ + { 0x000001FB, 0x000000E5, 0x00000301 }, /* LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE */ + { 0x000001FD, 0x000000E6, 0x00000301 }, /* LATIN SMALL LETTER AE WITH ACUTE */ + { 0x000001E3, 0x000000E6, 0x00000304 }, /* LATIN SMALL LETTER AE WITH MACRON */ + { 0x00001E09, 0x000000E7, 0x00000301 }, /* LATIN SMALL LETTER C WITH CEDILLA AND ACUTE */ + { 0x00001EC1, 0x000000EA, 0x00000300 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EBF, 0x000000EA, 0x00000301 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EC5, 0x000000EA, 0x00000303 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */ + { 0x00001EC3, 0x000000EA, 0x00000309 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001E2F, 0x000000EF, 0x00000301 }, /* LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE */ + { 0x00001ED3, 0x000000F4, 0x00000300 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */ + { 0x00001ED1, 0x000000F4, 0x00000301 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */ + { 0x00001ED7, 0x000000F4, 0x00000303 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */ + { 0x00001ED5, 0x000000F4, 0x00000309 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001E4D, 0x000000F5, 0x00000301 }, /* LATIN SMALL LETTER O WITH TILDE AND ACUTE */ + { 0x0000022D, 0x000000F5, 0x00000304 }, /* LATIN SMALL LETTER O WITH TILDE AND MACRON */ + { 0x00001E4F, 0x000000F5, 0x00000308 }, /* LATIN SMALL LETTER O WITH TILDE AND DIAERESIS */ + { 0x0000022B, 0x000000F6, 0x00000304 }, /* LATIN SMALL LETTER O WITH DIAERESIS AND MACRON */ + { 0x000001FF, 0x000000F8, 0x00000301 }, /* LATIN SMALL LETTER O WITH STROKE AND ACUTE */ + { 0x000001DC, 0x000000FC, 0x00000300 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE */ + { 0x000001D8, 0x000000FC, 0x00000301 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE */ + { 0x000001D6, 0x000000FC, 0x00000304 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND MACRON */ + { 0x000001DA, 0x000000FC, 0x0000030C }, /* LATIN SMALL LETTER U WITH DIAERESIS AND CARON */ + { 0x00001EB0, 0x00000102, 0x00000300 }, /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ + { 0x00001EAE, 0x00000102, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ + { 0x00001EB4, 0x00000102, 0x00000303 }, /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ + { 0x00001EB2, 0x00000102, 0x00000309 }, /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ + { 0x00001EB1, 0x00000103, 0x00000300 }, /* LATIN SMALL LETTER A WITH BREVE AND GRAVE */ + { 0x00001EAF, 0x00000103, 0x00000301 }, /* LATIN SMALL LETTER A WITH BREVE AND ACUTE */ + { 0x00001EB5, 0x00000103, 0x00000303 }, /* LATIN SMALL LETTER A WITH BREVE AND TILDE */ + { 0x00001EB3, 0x00000103, 0x00000309 }, /* LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */ + { 0x00001E14, 0x00000112, 0x00000300 }, /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE */ + { 0x00001E16, 0x00000112, 0x00000301 }, /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE */ + { 0x00001E15, 0x00000113, 0x00000300 }, /* LATIN SMALL LETTER E WITH MACRON AND GRAVE */ + { 0x00001E17, 0x00000113, 0x00000301 }, /* LATIN SMALL LETTER E WITH MACRON AND ACUTE */ + { 0x00001E50, 0x0000014C, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE */ + { 0x00001E52, 0x0000014C, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE */ + { 0x00001E51, 0x0000014D, 0x00000300 }, /* LATIN SMALL LETTER O WITH MACRON AND GRAVE */ + { 0x00001E53, 0x0000014D, 0x00000301 }, /* LATIN SMALL LETTER O WITH MACRON AND ACUTE */ + { 0x00001E64, 0x0000015A, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE */ + { 0x00001E65, 0x0000015B, 0x00000307 }, /* LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE */ + { 0x00001E66, 0x00000160, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE */ + { 0x00001E67, 0x00000161, 0x00000307 }, /* LATIN SMALL LETTER S WITH CARON AND DOT ABOVE */ + { 0x00001E78, 0x00000168, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE */ + { 0x00001E79, 0x00000169, 0x00000301 }, /* LATIN SMALL LETTER U WITH TILDE AND ACUTE */ + { 0x00001E7A, 0x0000016A, 0x00000308 }, /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS */ + { 0x00001E7B, 0x0000016B, 0x00000308 }, /* LATIN SMALL LETTER U WITH MACRON AND DIAERESIS */ + { 0x00001E9B, 0x0000017F, 0x00000307 }, /* LATIN SMALL LETTER LONG S WITH DOT ABOVE */ + { 0x00001EDC, 0x000001A0, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ + { 0x00001EDA, 0x000001A0, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ + { 0x00001EE0, 0x000001A0, 0x00000303 }, /* LATIN CAPITAL LETTER O WITH HORN AND TILDE */ + { 0x00001EDE, 0x000001A0, 0x00000309 }, /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ + { 0x00001EE2, 0x000001A0, 0x00000323 }, /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ + { 0x00001EDD, 0x000001A1, 0x00000300 }, /* LATIN SMALL LETTER O WITH HORN AND GRAVE */ + { 0x00001EDB, 0x000001A1, 0x00000301 }, /* LATIN SMALL LETTER O WITH HORN AND ACUTE */ + { 0x00001EE1, 0x000001A1, 0x00000303 }, /* LATIN SMALL LETTER O WITH HORN AND TILDE */ + { 0x00001EDF, 0x000001A1, 0x00000309 }, /* LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */ + { 0x00001EE3, 0x000001A1, 0x00000323 }, /* LATIN SMALL LETTER O WITH HORN AND DOT BELOW */ + { 0x00001EEA, 0x000001AF, 0x00000300 }, /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ + { 0x00001EE8, 0x000001AF, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ + { 0x00001EEE, 0x000001AF, 0x00000303 }, /* LATIN CAPITAL LETTER U WITH HORN AND TILDE */ + { 0x00001EEC, 0x000001AF, 0x00000309 }, /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ + { 0x00001EF0, 0x000001AF, 0x00000323 }, /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ + { 0x00001EEB, 0x000001B0, 0x00000300 }, /* LATIN SMALL LETTER U WITH HORN AND GRAVE */ + { 0x00001EE9, 0x000001B0, 0x00000301 }, /* LATIN SMALL LETTER U WITH HORN AND ACUTE */ + { 0x00001EEF, 0x000001B0, 0x00000303 }, /* LATIN SMALL LETTER U WITH HORN AND TILDE */ + { 0x00001EED, 0x000001B0, 0x00000309 }, /* LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */ + { 0x00001EF1, 0x000001B0, 0x00000323 }, /* LATIN SMALL LETTER U WITH HORN AND DOT BELOW */ + { 0x000001EE, 0x000001B7, 0x0000030C }, /* LATIN CAPITAL LETTER EZH WITH CARON */ + { 0x000001EC, 0x000001EA, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON */ + { 0x000001ED, 0x000001EB, 0x00000304 }, /* LATIN SMALL LETTER O WITH OGONEK AND MACRON */ + { 0x000001E0, 0x00000226, 0x00000304 }, /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON */ + { 0x000001E1, 0x00000227, 0x00000304 }, /* LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON */ + { 0x00001E1C, 0x00000228, 0x00000306 }, /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE */ + { 0x00001E1D, 0x00000229, 0x00000306 }, /* LATIN SMALL LETTER E WITH CEDILLA AND BREVE */ + { 0x00000230, 0x0000022E, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON */ + { 0x00000231, 0x0000022F, 0x00000304 }, /* LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON */ + { 0x000001EF, 0x00000292, 0x0000030C }, /* LATIN SMALL LETTER EZH WITH CARON */ + { 0x00000344, 0x00000308, 0x00000301 }, /* COMBINING GREEK DIALYTIKA TONOS */ + { 0x00001FBA, 0x00000391, 0x00000300 }, /* GREEK CAPITAL LETTER ALPHA WITH VARIA */ + { 0x00000386, 0x00000391, 0x00000301 }, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */ + { 0x00001FB9, 0x00000391, 0x00000304 }, /* GREEK CAPITAL LETTER ALPHA WITH MACRON */ + { 0x00001FB8, 0x00000391, 0x00000306 }, /* GREEK CAPITAL LETTER ALPHA WITH VRACHY */ + { 0x00001F08, 0x00000391, 0x00000313 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI */ + { 0x00001F09, 0x00000391, 0x00000314 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA */ + { 0x00001FBC, 0x00000391, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */ + { 0x00001FC8, 0x00000395, 0x00000300 }, /* GREEK CAPITAL LETTER EPSILON WITH VARIA */ + { 0x00000388, 0x00000395, 0x00000301 }, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ + { 0x00001F18, 0x00000395, 0x00000313 }, /* GREEK CAPITAL LETTER EPSILON WITH PSILI */ + { 0x00001F19, 0x00000395, 0x00000314 }, /* GREEK CAPITAL LETTER EPSILON WITH DASIA */ + { 0x00001FCA, 0x00000397, 0x00000300 }, /* GREEK CAPITAL LETTER ETA WITH VARIA */ + { 0x00000389, 0x00000397, 0x00000301 }, /* GREEK CAPITAL LETTER ETA WITH TONOS */ + { 0x00001F28, 0x00000397, 0x00000313 }, /* GREEK CAPITAL LETTER ETA WITH PSILI */ + { 0x00001F29, 0x00000397, 0x00000314 }, /* GREEK CAPITAL LETTER ETA WITH DASIA */ + { 0x00001FCC, 0x00000397, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */ + { 0x00001FDA, 0x00000399, 0x00000300 }, /* GREEK CAPITAL LETTER IOTA WITH VARIA */ + { 0x0000038A, 0x00000399, 0x00000301 }, /* GREEK CAPITAL LETTER IOTA WITH TONOS */ + { 0x00001FD9, 0x00000399, 0x00000304 }, /* GREEK CAPITAL LETTER IOTA WITH MACRON */ + { 0x00001FD8, 0x00000399, 0x00000306 }, /* GREEK CAPITAL LETTER IOTA WITH VRACHY */ + { 0x000003AA, 0x00000399, 0x00000308 }, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + { 0x00001F38, 0x00000399, 0x00000313 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI */ + { 0x00001F39, 0x00000399, 0x00000314 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA */ + { 0x00001FF8, 0x0000039F, 0x00000300 }, /* GREEK CAPITAL LETTER OMICRON WITH VARIA */ + { 0x0000038C, 0x0000039F, 0x00000301 }, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */ + { 0x00001F48, 0x0000039F, 0x00000313 }, /* GREEK CAPITAL LETTER OMICRON WITH PSILI */ + { 0x00001F49, 0x0000039F, 0x00000314 }, /* GREEK CAPITAL LETTER OMICRON WITH DASIA */ + { 0x00001FEC, 0x000003A1, 0x00000314 }, /* GREEK CAPITAL LETTER RHO WITH DASIA */ + { 0x00001FEA, 0x000003A5, 0x00000300 }, /* GREEK CAPITAL LETTER UPSILON WITH VARIA */ + { 0x0000038E, 0x000003A5, 0x00000301 }, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */ + { 0x00001FE9, 0x000003A5, 0x00000304 }, /* GREEK CAPITAL LETTER UPSILON WITH MACRON */ + { 0x00001FE8, 0x000003A5, 0x00000306 }, /* GREEK CAPITAL LETTER UPSILON WITH VRACHY */ + { 0x000003AB, 0x000003A5, 0x00000308 }, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + { 0x00001F59, 0x000003A5, 0x00000314 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA */ + { 0x00001FFA, 0x000003A9, 0x00000300 }, /* GREEK CAPITAL LETTER OMEGA WITH VARIA */ + { 0x0000038F, 0x000003A9, 0x00000301 }, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */ + { 0x00001F68, 0x000003A9, 0x00000313 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI */ + { 0x00001F69, 0x000003A9, 0x00000314 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA */ + { 0x00001FFC, 0x000003A9, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */ + { 0x00001FB4, 0x000003AC, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI */ + { 0x00001FC4, 0x000003AE, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI */ + { 0x00001F70, 0x000003B1, 0x00000300 }, /* GREEK SMALL LETTER ALPHA WITH VARIA */ + { 0x000003AC, 0x000003B1, 0x00000301 }, /* GREEK SMALL LETTER ALPHA WITH TONOS */ + { 0x00001FB1, 0x000003B1, 0x00000304 }, /* GREEK SMALL LETTER ALPHA WITH MACRON */ + { 0x00001FB0, 0x000003B1, 0x00000306 }, /* GREEK SMALL LETTER ALPHA WITH VRACHY */ + { 0x00001F00, 0x000003B1, 0x00000313 }, /* GREEK SMALL LETTER ALPHA WITH PSILI */ + { 0x00001F01, 0x000003B1, 0x00000314 }, /* GREEK SMALL LETTER ALPHA WITH DASIA */ + { 0x00001FB6, 0x000003B1, 0x00000342 }, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI */ + { 0x00001FB3, 0x000003B1, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI */ + { 0x00001F72, 0x000003B5, 0x00000300 }, /* GREEK SMALL LETTER EPSILON WITH VARIA */ + { 0x000003AD, 0x000003B5, 0x00000301 }, /* GREEK SMALL LETTER EPSILON WITH TONOS */ + { 0x00001F10, 0x000003B5, 0x00000313 }, /* GREEK SMALL LETTER EPSILON WITH PSILI */ + { 0x00001F11, 0x000003B5, 0x00000314 }, /* GREEK SMALL LETTER EPSILON WITH DASIA */ + { 0x00001F74, 0x000003B7, 0x00000300 }, /* GREEK SMALL LETTER ETA WITH VARIA */ + { 0x000003AE, 0x000003B7, 0x00000301 }, /* GREEK SMALL LETTER ETA WITH TONOS */ + { 0x00001F20, 0x000003B7, 0x00000313 }, /* GREEK SMALL LETTER ETA WITH PSILI */ + { 0x00001F21, 0x000003B7, 0x00000314 }, /* GREEK SMALL LETTER ETA WITH DASIA */ + { 0x00001FC6, 0x000003B7, 0x00000342 }, /* GREEK SMALL LETTER ETA WITH PERISPOMENI */ + { 0x00001FC3, 0x000003B7, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI */ + { 0x00001F76, 0x000003B9, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH VARIA */ + { 0x000003AF, 0x000003B9, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH TONOS */ + { 0x00001FD1, 0x000003B9, 0x00000304 }, /* GREEK SMALL LETTER IOTA WITH MACRON */ + { 0x00001FD0, 0x000003B9, 0x00000306 }, /* GREEK SMALL LETTER IOTA WITH VRACHY */ + { 0x000003CA, 0x000003B9, 0x00000308 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + { 0x00001F30, 0x000003B9, 0x00000313 }, /* GREEK SMALL LETTER IOTA WITH PSILI */ + { 0x00001F31, 0x000003B9, 0x00000314 }, /* GREEK SMALL LETTER IOTA WITH DASIA */ + { 0x00001FD6, 0x000003B9, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH PERISPOMENI */ + { 0x00001F78, 0x000003BF, 0x00000300 }, /* GREEK SMALL LETTER OMICRON WITH VARIA */ + { 0x000003CC, 0x000003BF, 0x00000301 }, /* GREEK SMALL LETTER OMICRON WITH TONOS */ + { 0x00001F40, 0x000003BF, 0x00000313 }, /* GREEK SMALL LETTER OMICRON WITH PSILI */ + { 0x00001F41, 0x000003BF, 0x00000314 }, /* GREEK SMALL LETTER OMICRON WITH DASIA */ + { 0x00001FE4, 0x000003C1, 0x00000313 }, /* GREEK SMALL LETTER RHO WITH PSILI */ + { 0x00001FE5, 0x000003C1, 0x00000314 }, /* GREEK SMALL LETTER RHO WITH DASIA */ + { 0x00001F7A, 0x000003C5, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH VARIA */ + { 0x000003CD, 0x000003C5, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH TONOS */ + { 0x00001FE1, 0x000003C5, 0x00000304 }, /* GREEK SMALL LETTER UPSILON WITH MACRON */ + { 0x00001FE0, 0x000003C5, 0x00000306 }, /* GREEK SMALL LETTER UPSILON WITH VRACHY */ + { 0x000003CB, 0x000003C5, 0x00000308 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + { 0x00001F50, 0x000003C5, 0x00000313 }, /* GREEK SMALL LETTER UPSILON WITH PSILI */ + { 0x00001F51, 0x000003C5, 0x00000314 }, /* GREEK SMALL LETTER UPSILON WITH DASIA */ + { 0x00001FE6, 0x000003C5, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH PERISPOMENI */ + { 0x00001F7C, 0x000003C9, 0x00000300 }, /* GREEK SMALL LETTER OMEGA WITH VARIA */ + { 0x000003CE, 0x000003C9, 0x00000301 }, /* GREEK SMALL LETTER OMEGA WITH TONOS */ + { 0x00001F60, 0x000003C9, 0x00000313 }, /* GREEK SMALL LETTER OMEGA WITH PSILI */ + { 0x00001F61, 0x000003C9, 0x00000314 }, /* GREEK SMALL LETTER OMEGA WITH DASIA */ + { 0x00001FF6, 0x000003C9, 0x00000342 }, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI */ + { 0x00001FF3, 0x000003C9, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI */ + { 0x00001FD2, 0x000003CA, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA */ + { 0x00000390, 0x000003CA, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + { 0x00001FD7, 0x000003CA, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI */ + { 0x00001FE2, 0x000003CB, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA */ + { 0x000003B0, 0x000003CB, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + { 0x00001FE7, 0x000003CB, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI */ + { 0x00001FF4, 0x000003CE, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI */ + { 0x000003D3, 0x000003D2, 0x00000301 }, /* GREEK UPSILON WITH ACUTE AND HOOK SYMBOL */ + { 0x000003D4, 0x000003D2, 0x00000308 }, /* GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL */ + { 0x00000407, 0x00000406, 0x00000308 }, /* CYRILLIC CAPITAL LETTER YI */ + { 0x000004D0, 0x00000410, 0x00000306 }, /* CYRILLIC CAPITAL LETTER A WITH BREVE */ + { 0x000004D2, 0x00000410, 0x00000308 }, /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS */ + { 0x00000403, 0x00000413, 0x00000301 }, /* CYRILLIC CAPITAL LETTER GJE */ + { 0x00000400, 0x00000415, 0x00000300 }, /* CYRILLIC CAPITAL LETTER IE WITH GRAVE */ + { 0x000004D6, 0x00000415, 0x00000306 }, /* CYRILLIC CAPITAL LETTER IE WITH BREVE */ + { 0x00000401, 0x00000415, 0x00000308 }, /* CYRILLIC CAPITAL LETTER IO */ + { 0x000004C1, 0x00000416, 0x00000306 }, /* CYRILLIC CAPITAL LETTER ZHE WITH BREVE */ + { 0x000004DC, 0x00000416, 0x00000308 }, /* CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS */ + { 0x000004DE, 0x00000417, 0x00000308 }, /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS */ + { 0x0000040D, 0x00000418, 0x00000300 }, /* CYRILLIC CAPITAL LETTER I WITH GRAVE */ + { 0x000004E2, 0x00000418, 0x00000304 }, /* CYRILLIC CAPITAL LETTER I WITH MACRON */ + { 0x00000419, 0x00000418, 0x00000306 }, /* CYRILLIC CAPITAL LETTER SHORT I */ + { 0x000004E4, 0x00000418, 0x00000308 }, /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS */ + { 0x0000040C, 0x0000041A, 0x00000301 }, /* CYRILLIC CAPITAL LETTER KJE */ + { 0x000004E6, 0x0000041E, 0x00000308 }, /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS */ + { 0x000004EE, 0x00000423, 0x00000304 }, /* CYRILLIC CAPITAL LETTER U WITH MACRON */ + { 0x0000040E, 0x00000423, 0x00000306 }, /* CYRILLIC CAPITAL LETTER SHORT U */ + { 0x000004F0, 0x00000423, 0x00000308 }, /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS */ + { 0x000004F2, 0x00000423, 0x0000030B }, /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x000004F4, 0x00000427, 0x00000308 }, /* CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS */ + { 0x000004F8, 0x0000042B, 0x00000308 }, /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS */ + { 0x000004EC, 0x0000042D, 0x00000308 }, /* CYRILLIC CAPITAL LETTER E WITH DIAERESIS */ + { 0x000004D1, 0x00000430, 0x00000306 }, /* CYRILLIC SMALL LETTER A WITH BREVE */ + { 0x000004D3, 0x00000430, 0x00000308 }, /* CYRILLIC SMALL LETTER A WITH DIAERESIS */ + { 0x00000453, 0x00000433, 0x00000301 }, /* CYRILLIC SMALL LETTER GJE */ + { 0x00000450, 0x00000435, 0x00000300 }, /* CYRILLIC SMALL LETTER IE WITH GRAVE */ + { 0x000004D7, 0x00000435, 0x00000306 }, /* CYRILLIC SMALL LETTER IE WITH BREVE */ + { 0x00000451, 0x00000435, 0x00000308 }, /* CYRILLIC SMALL LETTER IO */ + { 0x000004C2, 0x00000436, 0x00000306 }, /* CYRILLIC SMALL LETTER ZHE WITH BREVE */ + { 0x000004DD, 0x00000436, 0x00000308 }, /* CYRILLIC SMALL LETTER ZHE WITH DIAERESIS */ + { 0x000004DF, 0x00000437, 0x00000308 }, /* CYRILLIC SMALL LETTER ZE WITH DIAERESIS */ + { 0x0000045D, 0x00000438, 0x00000300 }, /* CYRILLIC SMALL LETTER I WITH GRAVE */ + { 0x000004E3, 0x00000438, 0x00000304 }, /* CYRILLIC SMALL LETTER I WITH MACRON */ + { 0x00000439, 0x00000438, 0x00000306 }, /* CYRILLIC SMALL LETTER SHORT I */ + { 0x000004E5, 0x00000438, 0x00000308 }, /* CYRILLIC SMALL LETTER I WITH DIAERESIS */ + { 0x0000045C, 0x0000043A, 0x00000301 }, /* CYRILLIC SMALL LETTER KJE */ + { 0x000004E7, 0x0000043E, 0x00000308 }, /* CYRILLIC SMALL LETTER O WITH DIAERESIS */ + { 0x000004EF, 0x00000443, 0x00000304 }, /* CYRILLIC SMALL LETTER U WITH MACRON */ + { 0x0000045E, 0x00000443, 0x00000306 }, /* CYRILLIC SMALL LETTER SHORT U */ + { 0x000004F1, 0x00000443, 0x00000308 }, /* CYRILLIC SMALL LETTER U WITH DIAERESIS */ + { 0x000004F3, 0x00000443, 0x0000030B }, /* CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x000004F5, 0x00000447, 0x00000308 }, /* CYRILLIC SMALL LETTER CHE WITH DIAERESIS */ + { 0x000004F9, 0x0000044B, 0x00000308 }, /* CYRILLIC SMALL LETTER YERU WITH DIAERESIS */ + { 0x000004ED, 0x0000044D, 0x00000308 }, /* CYRILLIC SMALL LETTER E WITH DIAERESIS */ + { 0x00000457, 0x00000456, 0x00000308 }, /* CYRILLIC SMALL LETTER YI */ + { 0x00000476, 0x00000474, 0x0000030F }, /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ + { 0x00000477, 0x00000475, 0x0000030F }, /* CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ + { 0x000004DA, 0x000004D8, 0x00000308 }, /* CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS */ + { 0x000004DB, 0x000004D9, 0x00000308 }, /* CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS */ + { 0x000004EA, 0x000004E8, 0x00000308 }, /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS */ + { 0x000004EB, 0x000004E9, 0x00000308 }, /* CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS */ + { 0x0000FB2E, 0x000005D0, 0x000005B7 }, /* HEBREW LETTER ALEF WITH PATAH */ + { 0x0000FB2F, 0x000005D0, 0x000005B8 }, /* HEBREW LETTER ALEF WITH QAMATS */ + { 0x0000FB30, 0x000005D0, 0x000005BC }, /* HEBREW LETTER ALEF WITH MAPIQ */ + { 0x0000FB31, 0x000005D1, 0x000005BC }, /* HEBREW LETTER BET WITH DAGESH */ + { 0x0000FB4C, 0x000005D1, 0x000005BF }, /* HEBREW LETTER BET WITH RAFE */ + { 0x0000FB32, 0x000005D2, 0x000005BC }, /* HEBREW LETTER GIMEL WITH DAGESH */ + { 0x0000FB33, 0x000005D3, 0x000005BC }, /* HEBREW LETTER DALET WITH DAGESH */ + { 0x0000FB34, 0x000005D4, 0x000005BC }, /* HEBREW LETTER HE WITH MAPIQ */ + { 0x0000FB4B, 0x000005D5, 0x000005B9 }, /* HEBREW LETTER VAV WITH HOLAM */ + { 0x0000FB35, 0x000005D5, 0x000005BC }, /* HEBREW LETTER VAV WITH DAGESH */ + { 0x0000FB36, 0x000005D6, 0x000005BC }, /* HEBREW LETTER ZAYIN WITH DAGESH */ + { 0x0000FB38, 0x000005D8, 0x000005BC }, /* HEBREW LETTER TET WITH DAGESH */ + { 0x0000FB1D, 0x000005D9, 0x000005B4 }, /* HEBREW LETTER YOD WITH HIRIQ */ + { 0x0000FB39, 0x000005D9, 0x000005BC }, /* HEBREW LETTER YOD WITH DAGESH */ + { 0x0000FB3A, 0x000005DA, 0x000005BC }, /* HEBREW LETTER FINAL KAF WITH DAGESH */ + { 0x0000FB3B, 0x000005DB, 0x000005BC }, /* HEBREW LETTER KAF WITH DAGESH */ + { 0x0000FB4D, 0x000005DB, 0x000005BF }, /* HEBREW LETTER KAF WITH RAFE */ + { 0x0000FB3C, 0x000005DC, 0x000005BC }, /* HEBREW LETTER LAMED WITH DAGESH */ + { 0x0000FB3E, 0x000005DE, 0x000005BC }, /* HEBREW LETTER MEM WITH DAGESH */ + { 0x0000FB40, 0x000005E0, 0x000005BC }, /* HEBREW LETTER NUN WITH DAGESH */ + { 0x0000FB41, 0x000005E1, 0x000005BC }, /* HEBREW LETTER SAMEKH WITH DAGESH */ + { 0x0000FB43, 0x000005E3, 0x000005BC }, /* HEBREW LETTER FINAL PE WITH DAGESH */ + { 0x0000FB44, 0x000005E4, 0x000005BC }, /* HEBREW LETTER PE WITH DAGESH */ + { 0x0000FB4E, 0x000005E4, 0x000005BF }, /* HEBREW LETTER PE WITH RAFE */ + { 0x0000FB46, 0x000005E6, 0x000005BC }, /* HEBREW LETTER TSADI WITH DAGESH */ + { 0x0000FB47, 0x000005E7, 0x000005BC }, /* HEBREW LETTER QOF WITH DAGESH */ + { 0x0000FB48, 0x000005E8, 0x000005BC }, /* HEBREW LETTER RESH WITH DAGESH */ + { 0x0000FB49, 0x000005E9, 0x000005BC }, /* HEBREW LETTER SHIN WITH DAGESH */ + { 0x0000FB2A, 0x000005E9, 0x000005C1 }, /* HEBREW LETTER SHIN WITH SHIN DOT */ + { 0x0000FB2B, 0x000005E9, 0x000005C2 }, /* HEBREW LETTER SHIN WITH SIN DOT */ + { 0x0000FB4A, 0x000005EA, 0x000005BC }, /* HEBREW LETTER TAV WITH DAGESH */ + { 0x0000FB1F, 0x000005F2, 0x000005B7 }, /* HEBREW LIGATURE YIDDISH YOD YOD PATAH */ + { 0x00000622, 0x00000627, 0x00000653 }, /* ARABIC LETTER ALEF WITH MADDA ABOVE */ + { 0x00000623, 0x00000627, 0x00000654 }, /* ARABIC LETTER ALEF WITH HAMZA ABOVE */ + { 0x00000625, 0x00000627, 0x00000655 }, /* ARABIC LETTER ALEF WITH HAMZA BELOW */ + { 0x00000624, 0x00000648, 0x00000654 }, /* ARABIC LETTER WAW WITH HAMZA ABOVE */ + { 0x00000626, 0x0000064A, 0x00000654 }, /* ARABIC LETTER YEH WITH HAMZA ABOVE */ + { 0x000006C2, 0x000006C1, 0x00000654 }, /* ARABIC LETTER HEH GOAL WITH HAMZA ABOVE */ + { 0x000006D3, 0x000006D2, 0x00000654 }, /* ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */ + { 0x000006C0, 0x000006D5, 0x00000654 }, /* ARABIC LETTER HEH WITH YEH ABOVE */ + { 0x00000958, 0x00000915, 0x0000093C }, /* DEVANAGARI LETTER QA */ + { 0x00000959, 0x00000916, 0x0000093C }, /* DEVANAGARI LETTER KHHA */ + { 0x0000095A, 0x00000917, 0x0000093C }, /* DEVANAGARI LETTER GHHA */ + { 0x0000095B, 0x0000091C, 0x0000093C }, /* DEVANAGARI LETTER ZA */ + { 0x0000095C, 0x00000921, 0x0000093C }, /* DEVANAGARI LETTER DDDHA */ + { 0x0000095D, 0x00000922, 0x0000093C }, /* DEVANAGARI LETTER RHA */ + { 0x00000929, 0x00000928, 0x0000093C }, /* DEVANAGARI LETTER NNNA */ + { 0x0000095E, 0x0000092B, 0x0000093C }, /* DEVANAGARI LETTER FA */ + { 0x0000095F, 0x0000092F, 0x0000093C }, /* DEVANAGARI LETTER YYA */ + { 0x00000931, 0x00000930, 0x0000093C }, /* DEVANAGARI LETTER RRA */ + { 0x00000934, 0x00000933, 0x0000093C }, /* DEVANAGARI LETTER LLLA */ + { 0x000009DC, 0x000009A1, 0x000009BC }, /* BENGALI LETTER RRA */ + { 0x000009DD, 0x000009A2, 0x000009BC }, /* BENGALI LETTER RHA */ + { 0x000009DF, 0x000009AF, 0x000009BC }, /* BENGALI LETTER YYA */ + { 0x000009CB, 0x000009C7, 0x000009BE }, /* BENGALI VOWEL SIGN O */ + { 0x000009CC, 0x000009C7, 0x000009D7 }, /* BENGALI VOWEL SIGN AU */ + { 0x00000A59, 0x00000A16, 0x00000A3C }, /* GURMUKHI LETTER KHHA */ + { 0x00000A5A, 0x00000A17, 0x00000A3C }, /* GURMUKHI LETTER GHHA */ + { 0x00000A5B, 0x00000A1C, 0x00000A3C }, /* GURMUKHI LETTER ZA */ + { 0x00000A5E, 0x00000A2B, 0x00000A3C }, /* GURMUKHI LETTER FA */ + { 0x00000A33, 0x00000A32, 0x00000A3C }, /* GURMUKHI LETTER LLA */ + { 0x00000A36, 0x00000A38, 0x00000A3C }, /* GURMUKHI LETTER SHA */ + { 0x00000B5C, 0x00000B21, 0x00000B3C }, /* ORIYA LETTER RRA */ + { 0x00000B5D, 0x00000B22, 0x00000B3C }, /* ORIYA LETTER RHA */ + { 0x00000B4B, 0x00000B47, 0x00000B3E }, /* ORIYA VOWEL SIGN O */ + { 0x00000B48, 0x00000B47, 0x00000B56 }, /* ORIYA VOWEL SIGN AI */ + { 0x00000B4C, 0x00000B47, 0x00000B57 }, /* ORIYA VOWEL SIGN AU */ + { 0x00000B94, 0x00000B92, 0x00000BD7 }, /* TAMIL LETTER AU */ + { 0x00000BCA, 0x00000BC6, 0x00000BBE }, /* TAMIL VOWEL SIGN O */ + { 0x00000BCC, 0x00000BC6, 0x00000BD7 }, /* TAMIL VOWEL SIGN AU */ + { 0x00000BCB, 0x00000BC7, 0x00000BBE }, /* TAMIL VOWEL SIGN OO */ + { 0x00000C48, 0x00000C46, 0x00000C56 }, /* TELUGU VOWEL SIGN AI */ + { 0x00000CC0, 0x00000CBF, 0x00000CD5 }, /* KANNADA VOWEL SIGN II */ + { 0x00000CCA, 0x00000CC6, 0x00000CC2 }, /* KANNADA VOWEL SIGN O */ + { 0x00000CC7, 0x00000CC6, 0x00000CD5 }, /* KANNADA VOWEL SIGN EE */ + { 0x00000CC8, 0x00000CC6, 0x00000CD6 }, /* KANNADA VOWEL SIGN AI */ + { 0x00000CCB, 0x00000CCA, 0x00000CD5 }, /* KANNADA VOWEL SIGN OO */ + { 0x00000D4A, 0x00000D46, 0x00000D3E }, /* MALAYALAM VOWEL SIGN O */ + { 0x00000D4C, 0x00000D46, 0x00000D57 }, /* MALAYALAM VOWEL SIGN AU */ + { 0x00000D4B, 0x00000D47, 0x00000D3E }, /* MALAYALAM VOWEL SIGN OO */ + { 0x00000DDA, 0x00000DD9, 0x00000DCA }, /* SINHALA VOWEL SIGN DIGA KOMBUVA */ + { 0x00000DDC, 0x00000DD9, 0x00000DCF }, /* SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA */ + { 0x00000DDE, 0x00000DD9, 0x00000DDF }, /* SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA */ + { 0x00000DDD, 0x00000DDC, 0x00000DCA }, /* SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA */ + { 0x00000F69, 0x00000F40, 0x00000FB5 }, /* TIBETAN LETTER KSSA */ + { 0x00000F43, 0x00000F42, 0x00000FB7 }, /* TIBETAN LETTER GHA */ + { 0x00000F4D, 0x00000F4C, 0x00000FB7 }, /* TIBETAN LETTER DDHA */ + { 0x00000F52, 0x00000F51, 0x00000FB7 }, /* TIBETAN LETTER DHA */ + { 0x00000F57, 0x00000F56, 0x00000FB7 }, /* TIBETAN LETTER BHA */ + { 0x00000F5C, 0x00000F5B, 0x00000FB7 }, /* TIBETAN LETTER DZHA */ + { 0x00000F73, 0x00000F71, 0x00000F72 }, /* TIBETAN VOWEL SIGN II */ + { 0x00000F75, 0x00000F71, 0x00000F74 }, /* TIBETAN VOWEL SIGN UU */ + { 0x00000F81, 0x00000F71, 0x00000F80 }, /* TIBETAN VOWEL SIGN REVERSED II */ + { 0x00000FB9, 0x00000F90, 0x00000FB5 }, /* TIBETAN SUBJOINED LETTER KSSA */ + { 0x00000F93, 0x00000F92, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER GHA */ + { 0x00000F9D, 0x00000F9C, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER DDHA */ + { 0x00000FA2, 0x00000FA1, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER DHA */ + { 0x00000FA7, 0x00000FA6, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER BHA */ + { 0x00000FAC, 0x00000FAB, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER DZHA */ + { 0x00000F76, 0x00000FB2, 0x00000F80 }, /* TIBETAN VOWEL SIGN VOCALIC R */ + { 0x00000F78, 0x00000FB3, 0x00000F80 }, /* TIBETAN VOWEL SIGN VOCALIC L */ + { 0x00001026, 0x00001025, 0x0000102E }, /* MYANMAR LETTER UU */ + { 0x00001B06, 0x00001B05, 0x00001B35 }, /* BALINESE LETTER AKARA TEDUNG */ + { 0x00001B08, 0x00001B07, 0x00001B35 }, /* BALINESE LETTER IKARA TEDUNG */ + { 0x00001B0A, 0x00001B09, 0x00001B35 }, /* BALINESE LETTER UKARA TEDUNG */ + { 0x00001B0C, 0x00001B0B, 0x00001B35 }, /* BALINESE LETTER RA REPA TEDUNG */ + { 0x00001B0E, 0x00001B0D, 0x00001B35 }, /* BALINESE LETTER LA LENGA TEDUNG */ + { 0x00001B12, 0x00001B11, 0x00001B35 }, /* BALINESE LETTER OKARA TEDUNG */ + { 0x00001B3B, 0x00001B3A, 0x00001B35 }, /* BALINESE VOWEL SIGN RA REPA TEDUNG */ + { 0x00001B3D, 0x00001B3C, 0x00001B35 }, /* BALINESE VOWEL SIGN LA LENGA TEDUNG */ + { 0x00001B40, 0x00001B3E, 0x00001B35 }, /* BALINESE VOWEL SIGN TALING TEDUNG */ + { 0x00001B41, 0x00001B3F, 0x00001B35 }, /* BALINESE VOWEL SIGN TALING REPA TEDUNG */ + { 0x00001B43, 0x00001B42, 0x00001B35 }, /* BALINESE VOWEL SIGN PEPET TEDUNG */ + { 0x00001E38, 0x00001E36, 0x00000304 }, /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON */ + { 0x00001E39, 0x00001E37, 0x00000304 }, /* LATIN SMALL LETTER L WITH DOT BELOW AND MACRON */ + { 0x00001E5C, 0x00001E5A, 0x00000304 }, /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON */ + { 0x00001E5D, 0x00001E5B, 0x00000304 }, /* LATIN SMALL LETTER R WITH DOT BELOW AND MACRON */ + { 0x00001E68, 0x00001E62, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE */ + { 0x00001E69, 0x00001E63, 0x00000307 }, /* LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE */ + { 0x00001EAC, 0x00001EA0, 0x00000302 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EB6, 0x00001EA0, 0x00000306 }, /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ + { 0x00001EAD, 0x00001EA1, 0x00000302 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EB7, 0x00001EA1, 0x00000306 }, /* LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */ + { 0x00001EC6, 0x00001EB8, 0x00000302 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EC7, 0x00001EB9, 0x00000302 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001ED8, 0x00001ECC, 0x00000302 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001ED9, 0x00001ECD, 0x00000302 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001F02, 0x00001F00, 0x00000300 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA */ + { 0x00001F04, 0x00001F00, 0x00000301 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA */ + { 0x00001F06, 0x00001F00, 0x00000342 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI */ + { 0x00001F80, 0x00001F00, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI */ + { 0x00001F03, 0x00001F01, 0x00000300 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA */ + { 0x00001F05, 0x00001F01, 0x00000301 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA */ + { 0x00001F07, 0x00001F01, 0x00000342 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI */ + { 0x00001F81, 0x00001F01, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI */ + { 0x00001F82, 0x00001F02, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F83, 0x00001F03, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F84, 0x00001F04, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F85, 0x00001F05, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F86, 0x00001F06, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F87, 0x00001F07, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F0A, 0x00001F08, 0x00000300 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA */ + { 0x00001F0C, 0x00001F08, 0x00000301 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA */ + { 0x00001F0E, 0x00001F08, 0x00000342 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI */ + { 0x00001F88, 0x00001F08, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */ + { 0x00001F0B, 0x00001F09, 0x00000300 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA */ + { 0x00001F0D, 0x00001F09, 0x00000301 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA */ + { 0x00001F0F, 0x00001F09, 0x00000342 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI */ + { 0x00001F89, 0x00001F09, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */ + { 0x00001F8A, 0x00001F0A, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F8B, 0x00001F0B, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F8C, 0x00001F0C, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F8D, 0x00001F0D, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F8E, 0x00001F0E, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001F8F, 0x00001F0F, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001F12, 0x00001F10, 0x00000300 }, /* GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA */ + { 0x00001F14, 0x00001F10, 0x00000301 }, /* GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA */ + { 0x00001F13, 0x00001F11, 0x00000300 }, /* GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA */ + { 0x00001F15, 0x00001F11, 0x00000301 }, /* GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA */ + { 0x00001F1A, 0x00001F18, 0x00000300 }, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA */ + { 0x00001F1C, 0x00001F18, 0x00000301 }, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA */ + { 0x00001F1B, 0x00001F19, 0x00000300 }, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA */ + { 0x00001F1D, 0x00001F19, 0x00000301 }, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA */ + { 0x00001F22, 0x00001F20, 0x00000300 }, /* GREEK SMALL LETTER ETA WITH PSILI AND VARIA */ + { 0x00001F24, 0x00001F20, 0x00000301 }, /* GREEK SMALL LETTER ETA WITH PSILI AND OXIA */ + { 0x00001F26, 0x00001F20, 0x00000342 }, /* GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI */ + { 0x00001F90, 0x00001F20, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI */ + { 0x00001F23, 0x00001F21, 0x00000300 }, /* GREEK SMALL LETTER ETA WITH DASIA AND VARIA */ + { 0x00001F25, 0x00001F21, 0x00000301 }, /* GREEK SMALL LETTER ETA WITH DASIA AND OXIA */ + { 0x00001F27, 0x00001F21, 0x00000342 }, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI */ + { 0x00001F91, 0x00001F21, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI */ + { 0x00001F92, 0x00001F22, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F93, 0x00001F23, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F94, 0x00001F24, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F95, 0x00001F25, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F96, 0x00001F26, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F97, 0x00001F27, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F2A, 0x00001F28, 0x00000300 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA */ + { 0x00001F2C, 0x00001F28, 0x00000301 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA */ + { 0x00001F2E, 0x00001F28, 0x00000342 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI */ + { 0x00001F98, 0x00001F28, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */ + { 0x00001F2B, 0x00001F29, 0x00000300 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA */ + { 0x00001F2D, 0x00001F29, 0x00000301 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA */ + { 0x00001F2F, 0x00001F29, 0x00000342 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI */ + { 0x00001F99, 0x00001F29, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */ + { 0x00001F9A, 0x00001F2A, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F9B, 0x00001F2B, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F9C, 0x00001F2C, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F9D, 0x00001F2D, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F9E, 0x00001F2E, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001F9F, 0x00001F2F, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001F32, 0x00001F30, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH PSILI AND VARIA */ + { 0x00001F34, 0x00001F30, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH PSILI AND OXIA */ + { 0x00001F36, 0x00001F30, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI */ + { 0x00001F33, 0x00001F31, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH DASIA AND VARIA */ + { 0x00001F35, 0x00001F31, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH DASIA AND OXIA */ + { 0x00001F37, 0x00001F31, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI */ + { 0x00001F3A, 0x00001F38, 0x00000300 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA */ + { 0x00001F3C, 0x00001F38, 0x00000301 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA */ + { 0x00001F3E, 0x00001F38, 0x00000342 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI */ + { 0x00001F3B, 0x00001F39, 0x00000300 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA */ + { 0x00001F3D, 0x00001F39, 0x00000301 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA */ + { 0x00001F3F, 0x00001F39, 0x00000342 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI */ + { 0x00001F42, 0x00001F40, 0x00000300 }, /* GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA */ + { 0x00001F44, 0x00001F40, 0x00000301 }, /* GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA */ + { 0x00001F43, 0x00001F41, 0x00000300 }, /* GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA */ + { 0x00001F45, 0x00001F41, 0x00000301 }, /* GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA */ + { 0x00001F4A, 0x00001F48, 0x00000300 }, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA */ + { 0x00001F4C, 0x00001F48, 0x00000301 }, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA */ + { 0x00001F4B, 0x00001F49, 0x00000300 }, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA */ + { 0x00001F4D, 0x00001F49, 0x00000301 }, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA */ + { 0x00001F52, 0x00001F50, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA */ + { 0x00001F54, 0x00001F50, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA */ + { 0x00001F56, 0x00001F50, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI */ + { 0x00001F53, 0x00001F51, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA */ + { 0x00001F55, 0x00001F51, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA */ + { 0x00001F57, 0x00001F51, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI */ + { 0x00001F5B, 0x00001F59, 0x00000300 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA */ + { 0x00001F5D, 0x00001F59, 0x00000301 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA */ + { 0x00001F5F, 0x00001F59, 0x00000342 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI */ + { 0x00001F62, 0x00001F60, 0x00000300 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA */ + { 0x00001F64, 0x00001F60, 0x00000301 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA */ + { 0x00001F66, 0x00001F60, 0x00000342 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI */ + { 0x00001FA0, 0x00001F60, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI */ + { 0x00001F63, 0x00001F61, 0x00000300 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA */ + { 0x00001F65, 0x00001F61, 0x00000301 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA */ + { 0x00001F67, 0x00001F61, 0x00000342 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI */ + { 0x00001FA1, 0x00001F61, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI */ + { 0x00001FA2, 0x00001F62, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + { 0x00001FA3, 0x00001F63, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + { 0x00001FA4, 0x00001F64, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + { 0x00001FA5, 0x00001F65, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + { 0x00001FA6, 0x00001F66, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FA7, 0x00001F67, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F6A, 0x00001F68, 0x00000300 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA */ + { 0x00001F6C, 0x00001F68, 0x00000301 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA */ + { 0x00001F6E, 0x00001F68, 0x00000342 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI */ + { 0x00001FA8, 0x00001F68, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */ + { 0x00001F6B, 0x00001F69, 0x00000300 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA */ + { 0x00001F6D, 0x00001F69, 0x00000301 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA */ + { 0x00001F6F, 0x00001F69, 0x00000342 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI */ + { 0x00001FA9, 0x00001F69, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */ + { 0x00001FAA, 0x00001F6A, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + { 0x00001FAB, 0x00001F6B, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + { 0x00001FAC, 0x00001F6C, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + { 0x00001FAD, 0x00001F6D, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + { 0x00001FAE, 0x00001F6E, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001FAF, 0x00001F6F, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001FB2, 0x00001F70, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI */ + { 0x00001FC2, 0x00001F74, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI */ + { 0x00001FF2, 0x00001F7C, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI */ + { 0x00001FB7, 0x00001FB6, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FCD, 0x00001FBF, 0x00000300 }, /* GREEK PSILI AND VARIA */ + { 0x00001FCE, 0x00001FBF, 0x00000301 }, /* GREEK PSILI AND OXIA */ + { 0x00001FCF, 0x00001FBF, 0x00000342 }, /* GREEK PSILI AND PERISPOMENI */ + { 0x00001FC7, 0x00001FC6, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FF7, 0x00001FF6, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FDD, 0x00001FFE, 0x00000300 }, /* GREEK DASIA AND VARIA */ + { 0x00001FDE, 0x00001FFE, 0x00000301 }, /* GREEK DASIA AND OXIA */ + { 0x00001FDF, 0x00001FFE, 0x00000342 }, /* GREEK DASIA AND PERISPOMENI */ +/*{ 0x0000219A, 0x00002190, 0x00000338 },*/ /* LEFTWARDS ARROW WITH STROKE */ +/*{ 0x0000219B, 0x00002192, 0x00000338 },*/ /* RIGHTWARDS ARROW WITH STROKE */ +/*{ 0x000021AE, 0x00002194, 0x00000338 },*/ /* LEFT RIGHT ARROW WITH STROKE */ +/*{ 0x000021CD, 0x000021D0, 0x00000338 },*/ /* LEFTWARDS DOUBLE ARROW WITH STROKE */ +/*{ 0x000021CF, 0x000021D2, 0x00000338 },*/ /* RIGHTWARDS DOUBLE ARROW WITH STROKE */ +/*{ 0x000021CE, 0x000021D4, 0x00000338 },*/ /* LEFT RIGHT DOUBLE ARROW WITH STROKE */ +/*{ 0x00002204, 0x00002203, 0x00000338 },*/ /* THERE DOES NOT EXIST */ +/*{ 0x00002209, 0x00002208, 0x00000338 },*/ /* NOT AN ELEMENT OF */ +/*{ 0x0000220C, 0x0000220B, 0x00000338 },*/ /* DOES NOT CONTAIN AS MEMBER */ +/*{ 0x00002224, 0x00002223, 0x00000338 },*/ /* DOES NOT DIVIDE */ +/*{ 0x00002226, 0x00002225, 0x00000338 },*/ /* NOT PARALLEL TO */ +/*{ 0x00002241, 0x0000223C, 0x00000338 },*/ /* NOT TILDE */ +/*{ 0x00002244, 0x00002243, 0x00000338 },*/ /* NOT ASYMPTOTICALLY EQUAL TO */ +/*{ 0x00002247, 0x00002245, 0x00000338 },*/ /* NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO */ +/*{ 0x00002249, 0x00002248, 0x00000338 },*/ /* NOT ALMOST EQUAL TO */ +/*{ 0x0000226D, 0x0000224D, 0x00000338 },*/ /* NOT EQUIVALENT TO */ +/*{ 0x00002262, 0x00002261, 0x00000338 },*/ /* NOT IDENTICAL TO */ +/*{ 0x00002270, 0x00002264, 0x00000338 },*/ /* NEITHER LESS-THAN NOR EQUAL TO */ +/*{ 0x00002271, 0x00002265, 0x00000338 },*/ /* NEITHER GREATER-THAN NOR EQUAL TO */ +/*{ 0x00002274, 0x00002272, 0x00000338 },*/ /* NEITHER LESS-THAN NOR EQUIVALENT TO */ +/*{ 0x00002275, 0x00002273, 0x00000338 },*/ /* NEITHER GREATER-THAN NOR EQUIVALENT TO */ +/*{ 0x00002278, 0x00002276, 0x00000338 },*/ /* NEITHER LESS-THAN NOR GREATER-THAN */ +/*{ 0x00002279, 0x00002277, 0x00000338 },*/ /* NEITHER GREATER-THAN NOR LESS-THAN */ +/*{ 0x00002280, 0x0000227A, 0x00000338 },*/ /* DOES NOT PRECEDE */ +/*{ 0x00002281, 0x0000227B, 0x00000338 },*/ /* DOES NOT SUCCEED */ +/*{ 0x000022E0, 0x0000227C, 0x00000338 },*/ /* DOES NOT PRECEDE OR EQUAL */ +/*{ 0x000022E1, 0x0000227D, 0x00000338 },*/ /* DOES NOT SUCCEED OR EQUAL */ +/*{ 0x00002284, 0x00002282, 0x00000338 },*/ /* NOT A SUBSET OF */ +/*{ 0x00002285, 0x00002283, 0x00000338 },*/ /* NOT A SUPERSET OF */ +/*{ 0x00002288, 0x00002286, 0x00000338 },*/ /* NEITHER A SUBSET OF NOR EQUAL TO */ +/*{ 0x00002289, 0x00002287, 0x00000338 },*/ /* NEITHER A SUPERSET OF NOR EQUAL TO */ +/*{ 0x000022E2, 0x00002291, 0x00000338 },*/ /* NOT SQUARE IMAGE OF OR EQUAL TO */ +/*{ 0x000022E3, 0x00002292, 0x00000338 },*/ /* NOT SQUARE ORIGINAL OF OR EQUAL TO */ +/*{ 0x000022AC, 0x000022A2, 0x00000338 },*/ /* DOES NOT PROVE */ +/*{ 0x000022AD, 0x000022A8, 0x00000338 },*/ /* NOT TRUE */ +/*{ 0x000022AE, 0x000022A9, 0x00000338 },*/ /* DOES NOT FORCE */ +/*{ 0x000022AF, 0x000022AB, 0x00000338 },*/ /* NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE */ +/*{ 0x000022EA, 0x000022B2, 0x00000338 },*/ /* NOT NORMAL SUBGROUP OF */ +/*{ 0x000022EB, 0x000022B3, 0x00000338 },*/ /* DOES NOT CONTAIN AS NORMAL SUBGROUP */ +/*{ 0x000022EC, 0x000022B4, 0x00000338 },*/ /* NOT NORMAL SUBGROUP OF OR EQUAL TO */ +/*{ 0x000022ED, 0x000022B5, 0x00000338 },*/ /* DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL */ +/*{ 0x00002ADC, 0x00002ADD, 0x00000338 },*/ /* FORKING */ + { 0x00003094, 0x00003046, 0x00003099 }, /* HIRAGANA LETTER VU */ + { 0x0000304C, 0x0000304B, 0x00003099 }, /* HIRAGANA LETTER GA */ + { 0x0000304E, 0x0000304D, 0x00003099 }, /* HIRAGANA LETTER GI */ + { 0x00003050, 0x0000304F, 0x00003099 }, /* HIRAGANA LETTER GU */ + { 0x00003052, 0x00003051, 0x00003099 }, /* HIRAGANA LETTER GE */ + { 0x00003054, 0x00003053, 0x00003099 }, /* HIRAGANA LETTER GO */ + { 0x00003056, 0x00003055, 0x00003099 }, /* HIRAGANA LETTER ZA */ + { 0x00003058, 0x00003057, 0x00003099 }, /* HIRAGANA LETTER ZI */ + { 0x0000305A, 0x00003059, 0x00003099 }, /* HIRAGANA LETTER ZU */ + { 0x0000305C, 0x0000305B, 0x00003099 }, /* HIRAGANA LETTER ZE */ + { 0x0000305E, 0x0000305D, 0x00003099 }, /* HIRAGANA LETTER ZO */ + { 0x00003060, 0x0000305F, 0x00003099 }, /* HIRAGANA LETTER DA */ + { 0x00003062, 0x00003061, 0x00003099 }, /* HIRAGANA LETTER DI */ + { 0x00003065, 0x00003064, 0x00003099 }, /* HIRAGANA LETTER DU */ + { 0x00003067, 0x00003066, 0x00003099 }, /* HIRAGANA LETTER DE */ + { 0x00003069, 0x00003068, 0x00003099 }, /* HIRAGANA LETTER DO */ + { 0x00003070, 0x0000306F, 0x00003099 }, /* HIRAGANA LETTER BA */ + { 0x00003071, 0x0000306F, 0x0000309A }, /* HIRAGANA LETTER PA */ + { 0x00003073, 0x00003072, 0x00003099 }, /* HIRAGANA LETTER BI */ + { 0x00003074, 0x00003072, 0x0000309A }, /* HIRAGANA LETTER PI */ + { 0x00003076, 0x00003075, 0x00003099 }, /* HIRAGANA LETTER BU */ + { 0x00003077, 0x00003075, 0x0000309A }, /* HIRAGANA LETTER PU */ + { 0x00003079, 0x00003078, 0x00003099 }, /* HIRAGANA LETTER BE */ + { 0x0000307A, 0x00003078, 0x0000309A }, /* HIRAGANA LETTER PE */ + { 0x0000307C, 0x0000307B, 0x00003099 }, /* HIRAGANA LETTER BO */ + { 0x0000307D, 0x0000307B, 0x0000309A }, /* HIRAGANA LETTER PO */ + { 0x0000309E, 0x0000309D, 0x00003099 }, /* HIRAGANA VOICED ITERATION MARK */ + { 0x000030F4, 0x000030A6, 0x00003099 }, /* KATAKANA LETTER VU */ + { 0x000030AC, 0x000030AB, 0x00003099 }, /* KATAKANA LETTER GA */ + { 0x000030AE, 0x000030AD, 0x00003099 }, /* KATAKANA LETTER GI */ + { 0x000030B0, 0x000030AF, 0x00003099 }, /* KATAKANA LETTER GU */ + { 0x000030B2, 0x000030B1, 0x00003099 }, /* KATAKANA LETTER GE */ + { 0x000030B4, 0x000030B3, 0x00003099 }, /* KATAKANA LETTER GO */ + { 0x000030B6, 0x000030B5, 0x00003099 }, /* KATAKANA LETTER ZA */ + { 0x000030B8, 0x000030B7, 0x00003099 }, /* KATAKANA LETTER ZI */ + { 0x000030BA, 0x000030B9, 0x00003099 }, /* KATAKANA LETTER ZU */ + { 0x000030BC, 0x000030BB, 0x00003099 }, /* KATAKANA LETTER ZE */ + { 0x000030BE, 0x000030BD, 0x00003099 }, /* KATAKANA LETTER ZO */ + { 0x000030C0, 0x000030BF, 0x00003099 }, /* KATAKANA LETTER DA */ + { 0x000030C2, 0x000030C1, 0x00003099 }, /* KATAKANA LETTER DI */ + { 0x000030C5, 0x000030C4, 0x00003099 }, /* KATAKANA LETTER DU */ + { 0x000030C7, 0x000030C6, 0x00003099 }, /* KATAKANA LETTER DE */ + { 0x000030C9, 0x000030C8, 0x00003099 }, /* KATAKANA LETTER DO */ + { 0x000030D0, 0x000030CF, 0x00003099 }, /* KATAKANA LETTER BA */ + { 0x000030D1, 0x000030CF, 0x0000309A }, /* KATAKANA LETTER PA */ + { 0x000030D3, 0x000030D2, 0x00003099 }, /* KATAKANA LETTER BI */ + { 0x000030D4, 0x000030D2, 0x0000309A }, /* KATAKANA LETTER PI */ + { 0x000030D6, 0x000030D5, 0x00003099 }, /* KATAKANA LETTER BU */ + { 0x000030D7, 0x000030D5, 0x0000309A }, /* KATAKANA LETTER PU */ + { 0x000030D9, 0x000030D8, 0x00003099 }, /* KATAKANA LETTER BE */ + { 0x000030DA, 0x000030D8, 0x0000309A }, /* KATAKANA LETTER PE */ + { 0x000030DC, 0x000030DB, 0x00003099 }, /* KATAKANA LETTER BO */ + { 0x000030DD, 0x000030DB, 0x0000309A }, /* KATAKANA LETTER PO */ + { 0x000030F7, 0x000030EF, 0x00003099 }, /* KATAKANA LETTER VA */ + { 0x000030F8, 0x000030F0, 0x00003099 }, /* KATAKANA LETTER VI */ + { 0x000030F9, 0x000030F1, 0x00003099 }, /* KATAKANA LETTER VE */ + { 0x000030FA, 0x000030F2, 0x00003099 }, /* KATAKANA LETTER VO */ + { 0x000030FE, 0x000030FD, 0x00003099 }, /* KATAKANA VOICED ITERATION MARK */ + { 0x0000FB2C, 0x0000FB49, 0x000005C1 }, /* HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT */ + { 0x0000FB2D, 0x0000FB49, 0x000005C2 }, /* HEBREW LETTER SHIN WITH DAGESH AND SIN DOT */ +/*{ 0x0001109A, 0x00011099, 0x000110BA },*/ /* KAITHI LETTER DDDHA */ +/*{ 0x0001109C, 0x0001109B, 0x000110BA },*/ /* KAITHI LETTER RHA */ +/*{ 0x000110AB, 0x000110A5, 0x000110BA },*/ /* KAITHI LETTER VA */ +/*{ 0x0001112E, 0x00011131, 0x00011127 },*/ /* CHAKMA VOWEL SIGN O */ +/*{ 0x0001112F, 0x00011132, 0x00011127 },*/ /* CHAKMA VOWEL SIGN AU */ +/*{ 0x0001134B, 0x00011347, 0x0001133E },*/ /* GRANTHA VOWEL SIGN OO */ +/*{ 0x0001134C, 0x00011347, 0x00011357 },*/ /* GRANTHA VOWEL SIGN AU */ +/*{ 0x000114BC, 0x000114B9, 0x000114B0 },*/ /* TIRHUTA VOWEL SIGN O */ +/*{ 0x000114BB, 0x000114B9, 0x000114BA },*/ /* TIRHUTA VOWEL SIGN AI */ +/*{ 0x000114BE, 0x000114B9, 0x000114BD },*/ /* TIRHUTA VOWEL SIGN AU */ +/*{ 0x000115BA, 0x000115B8, 0x000115AF },*/ /* SIDDHAM VOWEL SIGN O */ +/*{ 0x000115BB, 0x000115B9, 0x000115AF },*/ /* SIDDHAM VOWEL SIGN AU */ +/*{ 0x0001D15E, 0x0001D157, 0x0001D165 },*/ /* MUSICAL SYMBOL HALF NOTE */ +/*{ 0x0001D15F, 0x0001D158, 0x0001D165 },*/ /* MUSICAL SYMBOL QUARTER NOTE */ +/*{ 0x0001D160, 0x0001D15F, 0x0001D16E },*/ /* MUSICAL SYMBOL EIGHTH NOTE */ +/*{ 0x0001D161, 0x0001D15F, 0x0001D16F },*/ /* MUSICAL SYMBOL SIXTEENTH NOTE */ +/*{ 0x0001D162, 0x0001D15F, 0x0001D170 },*/ /* MUSICAL SYMBOL THIRTY-SECOND NOTE */ +/*{ 0x0001D163, 0x0001D15F, 0x0001D171 },*/ /* MUSICAL SYMBOL SIXTY-FOURTH NOTE */ +/*{ 0x0001D164, 0x0001D15F, 0x0001D172 },*/ /* MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE */ +/*{ 0x0001D1BB, 0x0001D1B9, 0x0001D165 },*/ /* MUSICAL SYMBOL MINIMA */ +/*{ 0x0001D1BC, 0x0001D1BA, 0x0001D165 },*/ /* MUSICAL SYMBOL MINIMA BLACK */ +/*{ 0x0001D1BD, 0x0001D1BB, 0x0001D16E },*/ /* MUSICAL SYMBOL SEMIMINIMA WHITE */ +/*{ 0x0001D1BF, 0x0001D1BB, 0x0001D16F },*/ /* MUSICAL SYMBOL FUSA WHITE */ +/*{ 0x0001D1BE, 0x0001D1BC, 0x0001D16E },*/ /* MUSICAL SYMBOL SEMIMINIMA BLACK */ +/*{ 0x0001D1C0, 0x0001D1BC, 0x0001D16F },*/ /* MUSICAL SYMBOL FUSA BLACK */ +}; + +static const struct { + unsigned int replacement; + unsigned int base; + unsigned int comb; +} decompositions[] = { + { 0x000000C0, 0x00000041, 0x00000300 }, /* LATIN CAPITAL LETTER A WITH GRAVE */ + { 0x000000C1, 0x00000041, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH ACUTE */ + { 0x000000C2, 0x00000041, 0x00000302 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ + { 0x000000C3, 0x00000041, 0x00000303 }, /* LATIN CAPITAL LETTER A WITH TILDE */ + { 0x000000C4, 0x00000041, 0x00000308 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */ + { 0x000000C5, 0x00000041, 0x0000030A }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */ + { 0x000000C7, 0x00000043, 0x00000327 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */ + { 0x000000C8, 0x00000045, 0x00000300 }, /* LATIN CAPITAL LETTER E WITH GRAVE */ + { 0x000000C9, 0x00000045, 0x00000301 }, /* LATIN CAPITAL LETTER E WITH ACUTE */ + { 0x000000CA, 0x00000045, 0x00000302 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ + { 0x000000CB, 0x00000045, 0x00000308 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */ + { 0x000000CC, 0x00000049, 0x00000300 }, /* LATIN CAPITAL LETTER I WITH GRAVE */ + { 0x000000CD, 0x00000049, 0x00000301 }, /* LATIN CAPITAL LETTER I WITH ACUTE */ + { 0x000000CE, 0x00000049, 0x00000302 }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ + { 0x000000CF, 0x00000049, 0x00000308 }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */ + { 0x000000D1, 0x0000004E, 0x00000303 }, /* LATIN CAPITAL LETTER N WITH TILDE */ + { 0x000000D2, 0x0000004F, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH GRAVE */ + { 0x000000D3, 0x0000004F, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH ACUTE */ + { 0x000000D4, 0x0000004F, 0x00000302 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ + { 0x000000D5, 0x0000004F, 0x00000303 }, /* LATIN CAPITAL LETTER O WITH TILDE */ + { 0x000000D6, 0x0000004F, 0x00000308 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */ + { 0x000000D9, 0x00000055, 0x00000300 }, /* LATIN CAPITAL LETTER U WITH GRAVE */ + { 0x000000DA, 0x00000055, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH ACUTE */ + { 0x000000DB, 0x00000055, 0x00000302 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ + { 0x000000DC, 0x00000055, 0x00000308 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */ + { 0x000000DD, 0x00000059, 0x00000301 }, /* LATIN CAPITAL LETTER Y WITH ACUTE */ + { 0x000000E0, 0x00000061, 0x00000300 }, /* LATIN SMALL LETTER A WITH GRAVE */ + { 0x000000E1, 0x00000061, 0x00000301 }, /* LATIN SMALL LETTER A WITH ACUTE */ + { 0x000000E2, 0x00000061, 0x00000302 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */ + { 0x000000E3, 0x00000061, 0x00000303 }, /* LATIN SMALL LETTER A WITH TILDE */ + { 0x000000E4, 0x00000061, 0x00000308 }, /* LATIN SMALL LETTER A WITH DIAERESIS */ + { 0x000000E5, 0x00000061, 0x0000030A }, /* LATIN SMALL LETTER A WITH RING ABOVE */ + { 0x000000E7, 0x00000063, 0x00000327 }, /* LATIN SMALL LETTER C WITH CEDILLA */ + { 0x000000E8, 0x00000065, 0x00000300 }, /* LATIN SMALL LETTER E WITH GRAVE */ + { 0x000000E9, 0x00000065, 0x00000301 }, /* LATIN SMALL LETTER E WITH ACUTE */ + { 0x000000EA, 0x00000065, 0x00000302 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */ + { 0x000000EB, 0x00000065, 0x00000308 }, /* LATIN SMALL LETTER E WITH DIAERESIS */ + { 0x000000EC, 0x00000069, 0x00000300 }, /* LATIN SMALL LETTER I WITH GRAVE */ + { 0x000000ED, 0x00000069, 0x00000301 }, /* LATIN SMALL LETTER I WITH ACUTE */ + { 0x000000EE, 0x00000069, 0x00000302 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */ + { 0x000000EF, 0x00000069, 0x00000308 }, /* LATIN SMALL LETTER I WITH DIAERESIS */ + { 0x000000F1, 0x0000006E, 0x00000303 }, /* LATIN SMALL LETTER N WITH TILDE */ + { 0x000000F2, 0x0000006F, 0x00000300 }, /* LATIN SMALL LETTER O WITH GRAVE */ + { 0x000000F3, 0x0000006F, 0x00000301 }, /* LATIN SMALL LETTER O WITH ACUTE */ + { 0x000000F4, 0x0000006F, 0x00000302 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */ + { 0x000000F5, 0x0000006F, 0x00000303 }, /* LATIN SMALL LETTER O WITH TILDE */ + { 0x000000F6, 0x0000006F, 0x00000308 }, /* LATIN SMALL LETTER O WITH DIAERESIS */ + { 0x000000F9, 0x00000075, 0x00000300 }, /* LATIN SMALL LETTER U WITH GRAVE */ + { 0x000000FA, 0x00000075, 0x00000301 }, /* LATIN SMALL LETTER U WITH ACUTE */ + { 0x000000FB, 0x00000075, 0x00000302 }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */ + { 0x000000FC, 0x00000075, 0x00000308 }, /* LATIN SMALL LETTER U WITH DIAERESIS */ + { 0x000000FD, 0x00000079, 0x00000301 }, /* LATIN SMALL LETTER Y WITH ACUTE */ + { 0x000000FF, 0x00000079, 0x00000308 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */ + { 0x00000100, 0x00000041, 0x00000304 }, /* LATIN CAPITAL LETTER A WITH MACRON */ + { 0x00000101, 0x00000061, 0x00000304 }, /* LATIN SMALL LETTER A WITH MACRON */ + { 0x00000102, 0x00000041, 0x00000306 }, /* LATIN CAPITAL LETTER A WITH BREVE */ + { 0x00000103, 0x00000061, 0x00000306 }, /* LATIN SMALL LETTER A WITH BREVE */ + { 0x00000104, 0x00000041, 0x00000328 }, /* LATIN CAPITAL LETTER A WITH OGONEK */ + { 0x00000105, 0x00000061, 0x00000328 }, /* LATIN SMALL LETTER A WITH OGONEK */ + { 0x00000106, 0x00000043, 0x00000301 }, /* LATIN CAPITAL LETTER C WITH ACUTE */ + { 0x00000107, 0x00000063, 0x00000301 }, /* LATIN SMALL LETTER C WITH ACUTE */ + { 0x00000108, 0x00000043, 0x00000302 }, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + { 0x00000109, 0x00000063, 0x00000302 }, /* LATIN SMALL LETTER C WITH CIRCUMFLEX */ + { 0x0000010A, 0x00000043, 0x00000307 }, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */ + { 0x0000010B, 0x00000063, 0x00000307 }, /* LATIN SMALL LETTER C WITH DOT ABOVE */ + { 0x0000010C, 0x00000043, 0x0000030C }, /* LATIN CAPITAL LETTER C WITH CARON */ + { 0x0000010D, 0x00000063, 0x0000030C }, /* LATIN SMALL LETTER C WITH CARON */ + { 0x0000010E, 0x00000044, 0x0000030C }, /* LATIN CAPITAL LETTER D WITH CARON */ + { 0x0000010F, 0x00000064, 0x0000030C }, /* LATIN SMALL LETTER D WITH CARON */ + { 0x00000112, 0x00000045, 0x00000304 }, /* LATIN CAPITAL LETTER E WITH MACRON */ + { 0x00000113, 0x00000065, 0x00000304 }, /* LATIN SMALL LETTER E WITH MACRON */ + { 0x00000114, 0x00000045, 0x00000306 }, /* LATIN CAPITAL LETTER E WITH BREVE */ + { 0x00000115, 0x00000065, 0x00000306 }, /* LATIN SMALL LETTER E WITH BREVE */ + { 0x00000116, 0x00000045, 0x00000307 }, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ + { 0x00000117, 0x00000065, 0x00000307 }, /* LATIN SMALL LETTER E WITH DOT ABOVE */ + { 0x00000118, 0x00000045, 0x00000328 }, /* LATIN CAPITAL LETTER E WITH OGONEK */ + { 0x00000119, 0x00000065, 0x00000328 }, /* LATIN SMALL LETTER E WITH OGONEK */ + { 0x0000011A, 0x00000045, 0x0000030C }, /* LATIN CAPITAL LETTER E WITH CARON */ + { 0x0000011B, 0x00000065, 0x0000030C }, /* LATIN SMALL LETTER E WITH CARON */ + { 0x0000011C, 0x00000047, 0x00000302 }, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + { 0x0000011D, 0x00000067, 0x00000302 }, /* LATIN SMALL LETTER G WITH CIRCUMFLEX */ + { 0x0000011E, 0x00000047, 0x00000306 }, /* LATIN CAPITAL LETTER G WITH BREVE */ + { 0x0000011F, 0x00000067, 0x00000306 }, /* LATIN SMALL LETTER G WITH BREVE */ + { 0x00000120, 0x00000047, 0x00000307 }, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */ + { 0x00000121, 0x00000067, 0x00000307 }, /* LATIN SMALL LETTER G WITH DOT ABOVE */ + { 0x00000122, 0x00000047, 0x00000327 }, /* LATIN CAPITAL LETTER G WITH CEDILLA */ + { 0x00000123, 0x00000067, 0x00000327 }, /* LATIN SMALL LETTER G WITH CEDILLA */ + { 0x00000124, 0x00000048, 0x00000302 }, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + { 0x00000125, 0x00000068, 0x00000302 }, /* LATIN SMALL LETTER H WITH CIRCUMFLEX */ + { 0x00000128, 0x00000049, 0x00000303 }, /* LATIN CAPITAL LETTER I WITH TILDE */ + { 0x00000129, 0x00000069, 0x00000303 }, /* LATIN SMALL LETTER I WITH TILDE */ + { 0x0000012A, 0x00000049, 0x00000304 }, /* LATIN CAPITAL LETTER I WITH MACRON */ + { 0x0000012B, 0x00000069, 0x00000304 }, /* LATIN SMALL LETTER I WITH MACRON */ + { 0x0000012C, 0x00000049, 0x00000306 }, /* LATIN CAPITAL LETTER I WITH BREVE */ + { 0x0000012D, 0x00000069, 0x00000306 }, /* LATIN SMALL LETTER I WITH BREVE */ + { 0x0000012E, 0x00000049, 0x00000328 }, /* LATIN CAPITAL LETTER I WITH OGONEK */ + { 0x0000012F, 0x00000069, 0x00000328 }, /* LATIN SMALL LETTER I WITH OGONEK */ + { 0x00000130, 0x00000049, 0x00000307 }, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ + { 0x00000134, 0x0000004A, 0x00000302 }, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + { 0x00000135, 0x0000006A, 0x00000302 }, /* LATIN SMALL LETTER J WITH CIRCUMFLEX */ + { 0x00000136, 0x0000004B, 0x00000327 }, /* LATIN CAPITAL LETTER K WITH CEDILLA */ + { 0x00000137, 0x0000006B, 0x00000327 }, /* LATIN SMALL LETTER K WITH CEDILLA */ + { 0x00000139, 0x0000004C, 0x00000301 }, /* LATIN CAPITAL LETTER L WITH ACUTE */ + { 0x0000013A, 0x0000006C, 0x00000301 }, /* LATIN SMALL LETTER L WITH ACUTE */ + { 0x0000013B, 0x0000004C, 0x00000327 }, /* LATIN CAPITAL LETTER L WITH CEDILLA */ + { 0x0000013C, 0x0000006C, 0x00000327 }, /* LATIN SMALL LETTER L WITH CEDILLA */ + { 0x0000013D, 0x0000004C, 0x0000030C }, /* LATIN CAPITAL LETTER L WITH CARON */ + { 0x0000013E, 0x0000006C, 0x0000030C }, /* LATIN SMALL LETTER L WITH CARON */ + { 0x00000143, 0x0000004E, 0x00000301 }, /* LATIN CAPITAL LETTER N WITH ACUTE */ + { 0x00000144, 0x0000006E, 0x00000301 }, /* LATIN SMALL LETTER N WITH ACUTE */ + { 0x00000145, 0x0000004E, 0x00000327 }, /* LATIN CAPITAL LETTER N WITH CEDILLA */ + { 0x00000146, 0x0000006E, 0x00000327 }, /* LATIN SMALL LETTER N WITH CEDILLA */ + { 0x00000147, 0x0000004E, 0x0000030C }, /* LATIN CAPITAL LETTER N WITH CARON */ + { 0x00000148, 0x0000006E, 0x0000030C }, /* LATIN SMALL LETTER N WITH CARON */ + { 0x0000014C, 0x0000004F, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH MACRON */ + { 0x0000014D, 0x0000006F, 0x00000304 }, /* LATIN SMALL LETTER O WITH MACRON */ + { 0x0000014E, 0x0000004F, 0x00000306 }, /* LATIN CAPITAL LETTER O WITH BREVE */ + { 0x0000014F, 0x0000006F, 0x00000306 }, /* LATIN SMALL LETTER O WITH BREVE */ + { 0x00000150, 0x0000004F, 0x0000030B }, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + { 0x00000151, 0x0000006F, 0x0000030B }, /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + { 0x00000154, 0x00000052, 0x00000301 }, /* LATIN CAPITAL LETTER R WITH ACUTE */ + { 0x00000155, 0x00000072, 0x00000301 }, /* LATIN SMALL LETTER R WITH ACUTE */ + { 0x00000156, 0x00000052, 0x00000327 }, /* LATIN CAPITAL LETTER R WITH CEDILLA */ + { 0x00000157, 0x00000072, 0x00000327 }, /* LATIN SMALL LETTER R WITH CEDILLA */ + { 0x00000158, 0x00000052, 0x0000030C }, /* LATIN CAPITAL LETTER R WITH CARON */ + { 0x00000159, 0x00000072, 0x0000030C }, /* LATIN SMALL LETTER R WITH CARON */ + { 0x0000015A, 0x00000053, 0x00000301 }, /* LATIN CAPITAL LETTER S WITH ACUTE */ + { 0x0000015B, 0x00000073, 0x00000301 }, /* LATIN SMALL LETTER S WITH ACUTE */ + { 0x0000015C, 0x00000053, 0x00000302 }, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + { 0x0000015D, 0x00000073, 0x00000302 }, /* LATIN SMALL LETTER S WITH CIRCUMFLEX */ + { 0x0000015E, 0x00000053, 0x00000327 }, /* LATIN CAPITAL LETTER S WITH CEDILLA */ + { 0x0000015F, 0x00000073, 0x00000327 }, /* LATIN SMALL LETTER S WITH CEDILLA */ + { 0x00000160, 0x00000053, 0x0000030C }, /* LATIN CAPITAL LETTER S WITH CARON */ + { 0x00000161, 0x00000073, 0x0000030C }, /* LATIN SMALL LETTER S WITH CARON */ + { 0x00000162, 0x00000054, 0x00000327 }, /* LATIN CAPITAL LETTER T WITH CEDILLA */ + { 0x00000163, 0x00000074, 0x00000327 }, /* LATIN SMALL LETTER T WITH CEDILLA */ + { 0x00000164, 0x00000054, 0x0000030C }, /* LATIN CAPITAL LETTER T WITH CARON */ + { 0x00000165, 0x00000074, 0x0000030C }, /* LATIN SMALL LETTER T WITH CARON */ + { 0x00000168, 0x00000055, 0x00000303 }, /* LATIN CAPITAL LETTER U WITH TILDE */ + { 0x00000169, 0x00000075, 0x00000303 }, /* LATIN SMALL LETTER U WITH TILDE */ + { 0x0000016A, 0x00000055, 0x00000304 }, /* LATIN CAPITAL LETTER U WITH MACRON */ + { 0x0000016B, 0x00000075, 0x00000304 }, /* LATIN SMALL LETTER U WITH MACRON */ + { 0x0000016C, 0x00000055, 0x00000306 }, /* LATIN CAPITAL LETTER U WITH BREVE */ + { 0x0000016D, 0x00000075, 0x00000306 }, /* LATIN SMALL LETTER U WITH BREVE */ + { 0x0000016E, 0x00000055, 0x0000030A }, /* LATIN CAPITAL LETTER U WITH RING ABOVE */ + { 0x0000016F, 0x00000075, 0x0000030A }, /* LATIN SMALL LETTER U WITH RING ABOVE */ + { 0x00000170, 0x00000055, 0x0000030B }, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x00000171, 0x00000075, 0x0000030B }, /* LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x00000172, 0x00000055, 0x00000328 }, /* LATIN CAPITAL LETTER U WITH OGONEK */ + { 0x00000173, 0x00000075, 0x00000328 }, /* LATIN SMALL LETTER U WITH OGONEK */ + { 0x00000174, 0x00000057, 0x00000302 }, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ + { 0x00000175, 0x00000077, 0x00000302 }, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */ + { 0x00000176, 0x00000059, 0x00000302 }, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ + { 0x00000177, 0x00000079, 0x00000302 }, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */ + { 0x00000178, 0x00000059, 0x00000308 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ + { 0x00000179, 0x0000005A, 0x00000301 }, /* LATIN CAPITAL LETTER Z WITH ACUTE */ + { 0x0000017A, 0x0000007A, 0x00000301 }, /* LATIN SMALL LETTER Z WITH ACUTE */ + { 0x0000017B, 0x0000005A, 0x00000307 }, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + { 0x0000017C, 0x0000007A, 0x00000307 }, /* LATIN SMALL LETTER Z WITH DOT ABOVE */ + { 0x0000017D, 0x0000005A, 0x0000030C }, /* LATIN CAPITAL LETTER Z WITH CARON */ + { 0x0000017E, 0x0000007A, 0x0000030C }, /* LATIN SMALL LETTER Z WITH CARON */ + { 0x000001A0, 0x0000004F, 0x0000031B }, /* LATIN CAPITAL LETTER O WITH HORN */ + { 0x000001A1, 0x0000006F, 0x0000031B }, /* LATIN SMALL LETTER O WITH HORN */ + { 0x000001AF, 0x00000055, 0x0000031B }, /* LATIN CAPITAL LETTER U WITH HORN */ + { 0x000001B0, 0x00000075, 0x0000031B }, /* LATIN SMALL LETTER U WITH HORN */ + { 0x000001CD, 0x00000041, 0x0000030C }, /* LATIN CAPITAL LETTER A WITH CARON */ + { 0x000001CE, 0x00000061, 0x0000030C }, /* LATIN SMALL LETTER A WITH CARON */ + { 0x000001CF, 0x00000049, 0x0000030C }, /* LATIN CAPITAL LETTER I WITH CARON */ + { 0x000001D0, 0x00000069, 0x0000030C }, /* LATIN SMALL LETTER I WITH CARON */ + { 0x000001D1, 0x0000004F, 0x0000030C }, /* LATIN CAPITAL LETTER O WITH CARON */ + { 0x000001D2, 0x0000006F, 0x0000030C }, /* LATIN SMALL LETTER O WITH CARON */ + { 0x000001D3, 0x00000055, 0x0000030C }, /* LATIN CAPITAL LETTER U WITH CARON */ + { 0x000001D4, 0x00000075, 0x0000030C }, /* LATIN SMALL LETTER U WITH CARON */ + { 0x000001D5, 0x000000DC, 0x00000304 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON */ + { 0x000001D6, 0x000000FC, 0x00000304 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND MACRON */ + { 0x000001D7, 0x000000DC, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE */ + { 0x000001D8, 0x000000FC, 0x00000301 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE */ + { 0x000001D9, 0x000000DC, 0x0000030C }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON */ + { 0x000001DA, 0x000000FC, 0x0000030C }, /* LATIN SMALL LETTER U WITH DIAERESIS AND CARON */ + { 0x000001DB, 0x000000DC, 0x00000300 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE */ + { 0x000001DC, 0x000000FC, 0x00000300 }, /* LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE */ + { 0x000001DE, 0x000000C4, 0x00000304 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON */ + { 0x000001DF, 0x000000E4, 0x00000304 }, /* LATIN SMALL LETTER A WITH DIAERESIS AND MACRON */ + { 0x000001E0, 0x00000226, 0x00000304 }, /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON */ + { 0x000001E1, 0x00000227, 0x00000304 }, /* LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON */ + { 0x000001E2, 0x000000C6, 0x00000304 }, /* LATIN CAPITAL LETTER AE WITH MACRON */ + { 0x000001E3, 0x000000E6, 0x00000304 }, /* LATIN SMALL LETTER AE WITH MACRON */ + { 0x000001E6, 0x00000047, 0x0000030C }, /* LATIN CAPITAL LETTER G WITH CARON */ + { 0x000001E7, 0x00000067, 0x0000030C }, /* LATIN SMALL LETTER G WITH CARON */ + { 0x000001E8, 0x0000004B, 0x0000030C }, /* LATIN CAPITAL LETTER K WITH CARON */ + { 0x000001E9, 0x0000006B, 0x0000030C }, /* LATIN SMALL LETTER K WITH CARON */ + { 0x000001EA, 0x0000004F, 0x00000328 }, /* LATIN CAPITAL LETTER O WITH OGONEK */ + { 0x000001EB, 0x0000006F, 0x00000328 }, /* LATIN SMALL LETTER O WITH OGONEK */ + { 0x000001EC, 0x000001EA, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON */ + { 0x000001ED, 0x000001EB, 0x00000304 }, /* LATIN SMALL LETTER O WITH OGONEK AND MACRON */ + { 0x000001EE, 0x000001B7, 0x0000030C }, /* LATIN CAPITAL LETTER EZH WITH CARON */ + { 0x000001EF, 0x00000292, 0x0000030C }, /* LATIN SMALL LETTER EZH WITH CARON */ + { 0x000001F0, 0x0000006A, 0x0000030C }, /* LATIN SMALL LETTER J WITH CARON */ + { 0x000001F4, 0x00000047, 0x00000301 }, /* LATIN CAPITAL LETTER G WITH ACUTE */ + { 0x000001F5, 0x00000067, 0x00000301 }, /* LATIN SMALL LETTER G WITH ACUTE */ + { 0x000001F8, 0x0000004E, 0x00000300 }, /* LATIN CAPITAL LETTER N WITH GRAVE */ + { 0x000001F9, 0x0000006E, 0x00000300 }, /* LATIN SMALL LETTER N WITH GRAVE */ + { 0x000001FA, 0x000000C5, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE */ + { 0x000001FB, 0x000000E5, 0x00000301 }, /* LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE */ + { 0x000001FC, 0x000000C6, 0x00000301 }, /* LATIN CAPITAL LETTER AE WITH ACUTE */ + { 0x000001FD, 0x000000E6, 0x00000301 }, /* LATIN SMALL LETTER AE WITH ACUTE */ + { 0x000001FE, 0x000000D8, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE */ + { 0x000001FF, 0x000000F8, 0x00000301 }, /* LATIN SMALL LETTER O WITH STROKE AND ACUTE */ + { 0x00000200, 0x00000041, 0x0000030F }, /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE */ + { 0x00000201, 0x00000061, 0x0000030F }, /* LATIN SMALL LETTER A WITH DOUBLE GRAVE */ + { 0x00000202, 0x00000041, 0x00000311 }, /* LATIN CAPITAL LETTER A WITH INVERTED BREVE */ + { 0x00000203, 0x00000061, 0x00000311 }, /* LATIN SMALL LETTER A WITH INVERTED BREVE */ + { 0x00000204, 0x00000045, 0x0000030F }, /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE */ + { 0x00000205, 0x00000065, 0x0000030F }, /* LATIN SMALL LETTER E WITH DOUBLE GRAVE */ + { 0x00000206, 0x00000045, 0x00000311 }, /* LATIN CAPITAL LETTER E WITH INVERTED BREVE */ + { 0x00000207, 0x00000065, 0x00000311 }, /* LATIN SMALL LETTER E WITH INVERTED BREVE */ + { 0x00000208, 0x00000049, 0x0000030F }, /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE */ + { 0x00000209, 0x00000069, 0x0000030F }, /* LATIN SMALL LETTER I WITH DOUBLE GRAVE */ + { 0x0000020A, 0x00000049, 0x00000311 }, /* LATIN CAPITAL LETTER I WITH INVERTED BREVE */ + { 0x0000020B, 0x00000069, 0x00000311 }, /* LATIN SMALL LETTER I WITH INVERTED BREVE */ + { 0x0000020C, 0x0000004F, 0x0000030F }, /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE */ + { 0x0000020D, 0x0000006F, 0x0000030F }, /* LATIN SMALL LETTER O WITH DOUBLE GRAVE */ + { 0x0000020E, 0x0000004F, 0x00000311 }, /* LATIN CAPITAL LETTER O WITH INVERTED BREVE */ + { 0x0000020F, 0x0000006F, 0x00000311 }, /* LATIN SMALL LETTER O WITH INVERTED BREVE */ + { 0x00000210, 0x00000052, 0x0000030F }, /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE */ + { 0x00000211, 0x00000072, 0x0000030F }, /* LATIN SMALL LETTER R WITH DOUBLE GRAVE */ + { 0x00000212, 0x00000052, 0x00000311 }, /* LATIN CAPITAL LETTER R WITH INVERTED BREVE */ + { 0x00000213, 0x00000072, 0x00000311 }, /* LATIN SMALL LETTER R WITH INVERTED BREVE */ + { 0x00000214, 0x00000055, 0x0000030F }, /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE */ + { 0x00000215, 0x00000075, 0x0000030F }, /* LATIN SMALL LETTER U WITH DOUBLE GRAVE */ + { 0x00000216, 0x00000055, 0x00000311 }, /* LATIN CAPITAL LETTER U WITH INVERTED BREVE */ + { 0x00000217, 0x00000075, 0x00000311 }, /* LATIN SMALL LETTER U WITH INVERTED BREVE */ + { 0x00000218, 0x00000053, 0x00000326 }, /* LATIN CAPITAL LETTER S WITH COMMA BELOW */ + { 0x00000219, 0x00000073, 0x00000326 }, /* LATIN SMALL LETTER S WITH COMMA BELOW */ + { 0x0000021A, 0x00000054, 0x00000326 }, /* LATIN CAPITAL LETTER T WITH COMMA BELOW */ + { 0x0000021B, 0x00000074, 0x00000326 }, /* LATIN SMALL LETTER T WITH COMMA BELOW */ + { 0x0000021E, 0x00000048, 0x0000030C }, /* LATIN CAPITAL LETTER H WITH CARON */ + { 0x0000021F, 0x00000068, 0x0000030C }, /* LATIN SMALL LETTER H WITH CARON */ + { 0x00000226, 0x00000041, 0x00000307 }, /* LATIN CAPITAL LETTER A WITH DOT ABOVE */ + { 0x00000227, 0x00000061, 0x00000307 }, /* LATIN SMALL LETTER A WITH DOT ABOVE */ + { 0x00000228, 0x00000045, 0x00000327 }, /* LATIN CAPITAL LETTER E WITH CEDILLA */ + { 0x00000229, 0x00000065, 0x00000327 }, /* LATIN SMALL LETTER E WITH CEDILLA */ + { 0x0000022A, 0x000000D6, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON */ + { 0x0000022B, 0x000000F6, 0x00000304 }, /* LATIN SMALL LETTER O WITH DIAERESIS AND MACRON */ + { 0x0000022C, 0x000000D5, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH TILDE AND MACRON */ + { 0x0000022D, 0x000000F5, 0x00000304 }, /* LATIN SMALL LETTER O WITH TILDE AND MACRON */ + { 0x0000022E, 0x0000004F, 0x00000307 }, /* LATIN CAPITAL LETTER O WITH DOT ABOVE */ + { 0x0000022F, 0x0000006F, 0x00000307 }, /* LATIN SMALL LETTER O WITH DOT ABOVE */ + { 0x00000230, 0x0000022E, 0x00000304 }, /* LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON */ + { 0x00000231, 0x0000022F, 0x00000304 }, /* LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON */ + { 0x00000232, 0x00000059, 0x00000304 }, /* LATIN CAPITAL LETTER Y WITH MACRON */ + { 0x00000233, 0x00000079, 0x00000304 }, /* LATIN SMALL LETTER Y WITH MACRON */ + { 0x00000344, 0x00000308, 0x00000301 }, /* COMBINING GREEK DIALYTIKA TONOS */ + { 0x00000385, 0x000000A8, 0x00000301 }, /* GREEK DIALYTIKA TONOS */ + { 0x00000386, 0x00000391, 0x00000301 }, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */ + { 0x00000388, 0x00000395, 0x00000301 }, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ + { 0x00000389, 0x00000397, 0x00000301 }, /* GREEK CAPITAL LETTER ETA WITH TONOS */ + { 0x0000038A, 0x00000399, 0x00000301 }, /* GREEK CAPITAL LETTER IOTA WITH TONOS */ + { 0x0000038C, 0x0000039F, 0x00000301 }, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */ + { 0x0000038E, 0x000003A5, 0x00000301 }, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */ + { 0x0000038F, 0x000003A9, 0x00000301 }, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */ + { 0x00000390, 0x000003CA, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + { 0x000003AA, 0x00000399, 0x00000308 }, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + { 0x000003AB, 0x000003A5, 0x00000308 }, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + { 0x000003AC, 0x000003B1, 0x00000301 }, /* GREEK SMALL LETTER ALPHA WITH TONOS */ + { 0x000003AD, 0x000003B5, 0x00000301 }, /* GREEK SMALL LETTER EPSILON WITH TONOS */ + { 0x000003AE, 0x000003B7, 0x00000301 }, /* GREEK SMALL LETTER ETA WITH TONOS */ + { 0x000003AF, 0x000003B9, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH TONOS */ + { 0x000003B0, 0x000003CB, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + { 0x000003CA, 0x000003B9, 0x00000308 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + { 0x000003CB, 0x000003C5, 0x00000308 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + { 0x000003CC, 0x000003BF, 0x00000301 }, /* GREEK SMALL LETTER OMICRON WITH TONOS */ + { 0x000003CD, 0x000003C5, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH TONOS */ + { 0x000003CE, 0x000003C9, 0x00000301 }, /* GREEK SMALL LETTER OMEGA WITH TONOS */ + { 0x000003D3, 0x000003D2, 0x00000301 }, /* GREEK UPSILON WITH ACUTE AND HOOK SYMBOL */ + { 0x000003D4, 0x000003D2, 0x00000308 }, /* GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL */ + { 0x00000400, 0x00000415, 0x00000300 }, /* CYRILLIC CAPITAL LETTER IE WITH GRAVE */ + { 0x00000401, 0x00000415, 0x00000308 }, /* CYRILLIC CAPITAL LETTER IO */ + { 0x00000403, 0x00000413, 0x00000301 }, /* CYRILLIC CAPITAL LETTER GJE */ + { 0x00000407, 0x00000406, 0x00000308 }, /* CYRILLIC CAPITAL LETTER YI */ + { 0x0000040C, 0x0000041A, 0x00000301 }, /* CYRILLIC CAPITAL LETTER KJE */ + { 0x0000040D, 0x00000418, 0x00000300 }, /* CYRILLIC CAPITAL LETTER I WITH GRAVE */ + { 0x0000040E, 0x00000423, 0x00000306 }, /* CYRILLIC CAPITAL LETTER SHORT U */ + { 0x00000419, 0x00000418, 0x00000306 }, /* CYRILLIC CAPITAL LETTER SHORT I */ + { 0x00000439, 0x00000438, 0x00000306 }, /* CYRILLIC SMALL LETTER SHORT I */ + { 0x00000450, 0x00000435, 0x00000300 }, /* CYRILLIC SMALL LETTER IE WITH GRAVE */ + { 0x00000451, 0x00000435, 0x00000308 }, /* CYRILLIC SMALL LETTER IO */ + { 0x00000453, 0x00000433, 0x00000301 }, /* CYRILLIC SMALL LETTER GJE */ + { 0x00000457, 0x00000456, 0x00000308 }, /* CYRILLIC SMALL LETTER YI */ + { 0x0000045C, 0x0000043A, 0x00000301 }, /* CYRILLIC SMALL LETTER KJE */ + { 0x0000045D, 0x00000438, 0x00000300 }, /* CYRILLIC SMALL LETTER I WITH GRAVE */ + { 0x0000045E, 0x00000443, 0x00000306 }, /* CYRILLIC SMALL LETTER SHORT U */ + { 0x00000476, 0x00000474, 0x0000030F }, /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ + { 0x00000477, 0x00000475, 0x0000030F }, /* CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ + { 0x000004C1, 0x00000416, 0x00000306 }, /* CYRILLIC CAPITAL LETTER ZHE WITH BREVE */ + { 0x000004C2, 0x00000436, 0x00000306 }, /* CYRILLIC SMALL LETTER ZHE WITH BREVE */ + { 0x000004D0, 0x00000410, 0x00000306 }, /* CYRILLIC CAPITAL LETTER A WITH BREVE */ + { 0x000004D1, 0x00000430, 0x00000306 }, /* CYRILLIC SMALL LETTER A WITH BREVE */ + { 0x000004D2, 0x00000410, 0x00000308 }, /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS */ + { 0x000004D3, 0x00000430, 0x00000308 }, /* CYRILLIC SMALL LETTER A WITH DIAERESIS */ + { 0x000004D6, 0x00000415, 0x00000306 }, /* CYRILLIC CAPITAL LETTER IE WITH BREVE */ + { 0x000004D7, 0x00000435, 0x00000306 }, /* CYRILLIC SMALL LETTER IE WITH BREVE */ + { 0x000004DA, 0x000004D8, 0x00000308 }, /* CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS */ + { 0x000004DB, 0x000004D9, 0x00000308 }, /* CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS */ + { 0x000004DC, 0x00000416, 0x00000308 }, /* CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS */ + { 0x000004DD, 0x00000436, 0x00000308 }, /* CYRILLIC SMALL LETTER ZHE WITH DIAERESIS */ + { 0x000004DE, 0x00000417, 0x00000308 }, /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS */ + { 0x000004DF, 0x00000437, 0x00000308 }, /* CYRILLIC SMALL LETTER ZE WITH DIAERESIS */ + { 0x000004E2, 0x00000418, 0x00000304 }, /* CYRILLIC CAPITAL LETTER I WITH MACRON */ + { 0x000004E3, 0x00000438, 0x00000304 }, /* CYRILLIC SMALL LETTER I WITH MACRON */ + { 0x000004E4, 0x00000418, 0x00000308 }, /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS */ + { 0x000004E5, 0x00000438, 0x00000308 }, /* CYRILLIC SMALL LETTER I WITH DIAERESIS */ + { 0x000004E6, 0x0000041E, 0x00000308 }, /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS */ + { 0x000004E7, 0x0000043E, 0x00000308 }, /* CYRILLIC SMALL LETTER O WITH DIAERESIS */ + { 0x000004EA, 0x000004E8, 0x00000308 }, /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS */ + { 0x000004EB, 0x000004E9, 0x00000308 }, /* CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS */ + { 0x000004EC, 0x0000042D, 0x00000308 }, /* CYRILLIC CAPITAL LETTER E WITH DIAERESIS */ + { 0x000004ED, 0x0000044D, 0x00000308 }, /* CYRILLIC SMALL LETTER E WITH DIAERESIS */ + { 0x000004EE, 0x00000423, 0x00000304 }, /* CYRILLIC CAPITAL LETTER U WITH MACRON */ + { 0x000004EF, 0x00000443, 0x00000304 }, /* CYRILLIC SMALL LETTER U WITH MACRON */ + { 0x000004F0, 0x00000423, 0x00000308 }, /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS */ + { 0x000004F1, 0x00000443, 0x00000308 }, /* CYRILLIC SMALL LETTER U WITH DIAERESIS */ + { 0x000004F2, 0x00000423, 0x0000030B }, /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x000004F3, 0x00000443, 0x0000030B }, /* CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x000004F4, 0x00000427, 0x00000308 }, /* CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS */ + { 0x000004F5, 0x00000447, 0x00000308 }, /* CYRILLIC SMALL LETTER CHE WITH DIAERESIS */ + { 0x000004F8, 0x0000042B, 0x00000308 }, /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS */ + { 0x000004F9, 0x0000044B, 0x00000308 }, /* CYRILLIC SMALL LETTER YERU WITH DIAERESIS */ + { 0x00000622, 0x00000627, 0x00000653 }, /* ARABIC LETTER ALEF WITH MADDA ABOVE */ + { 0x00000623, 0x00000627, 0x00000654 }, /* ARABIC LETTER ALEF WITH HAMZA ABOVE */ + { 0x00000624, 0x00000648, 0x00000654 }, /* ARABIC LETTER WAW WITH HAMZA ABOVE */ + { 0x00000625, 0x00000627, 0x00000655 }, /* ARABIC LETTER ALEF WITH HAMZA BELOW */ + { 0x00000626, 0x0000064A, 0x00000654 }, /* ARABIC LETTER YEH WITH HAMZA ABOVE */ + { 0x000006C0, 0x000006D5, 0x00000654 }, /* ARABIC LETTER HEH WITH YEH ABOVE */ + { 0x000006C2, 0x000006C1, 0x00000654 }, /* ARABIC LETTER HEH GOAL WITH HAMZA ABOVE */ + { 0x000006D3, 0x000006D2, 0x00000654 }, /* ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */ + { 0x00000929, 0x00000928, 0x0000093C }, /* DEVANAGARI LETTER NNNA */ + { 0x00000931, 0x00000930, 0x0000093C }, /* DEVANAGARI LETTER RRA */ + { 0x00000934, 0x00000933, 0x0000093C }, /* DEVANAGARI LETTER LLLA */ + { 0x00000958, 0x00000915, 0x0000093C }, /* DEVANAGARI LETTER QA */ + { 0x00000959, 0x00000916, 0x0000093C }, /* DEVANAGARI LETTER KHHA */ + { 0x0000095A, 0x00000917, 0x0000093C }, /* DEVANAGARI LETTER GHHA */ + { 0x0000095B, 0x0000091C, 0x0000093C }, /* DEVANAGARI LETTER ZA */ + { 0x0000095C, 0x00000921, 0x0000093C }, /* DEVANAGARI LETTER DDDHA */ + { 0x0000095D, 0x00000922, 0x0000093C }, /* DEVANAGARI LETTER RHA */ + { 0x0000095E, 0x0000092B, 0x0000093C }, /* DEVANAGARI LETTER FA */ + { 0x0000095F, 0x0000092F, 0x0000093C }, /* DEVANAGARI LETTER YYA */ + { 0x000009CB, 0x000009C7, 0x000009BE }, /* BENGALI VOWEL SIGN O */ + { 0x000009CC, 0x000009C7, 0x000009D7 }, /* BENGALI VOWEL SIGN AU */ + { 0x000009DC, 0x000009A1, 0x000009BC }, /* BENGALI LETTER RRA */ + { 0x000009DD, 0x000009A2, 0x000009BC }, /* BENGALI LETTER RHA */ + { 0x000009DF, 0x000009AF, 0x000009BC }, /* BENGALI LETTER YYA */ + { 0x00000A33, 0x00000A32, 0x00000A3C }, /* GURMUKHI LETTER LLA */ + { 0x00000A36, 0x00000A38, 0x00000A3C }, /* GURMUKHI LETTER SHA */ + { 0x00000A59, 0x00000A16, 0x00000A3C }, /* GURMUKHI LETTER KHHA */ + { 0x00000A5A, 0x00000A17, 0x00000A3C }, /* GURMUKHI LETTER GHHA */ + { 0x00000A5B, 0x00000A1C, 0x00000A3C }, /* GURMUKHI LETTER ZA */ + { 0x00000A5E, 0x00000A2B, 0x00000A3C }, /* GURMUKHI LETTER FA */ + { 0x00000B48, 0x00000B47, 0x00000B56 }, /* ORIYA VOWEL SIGN AI */ + { 0x00000B4B, 0x00000B47, 0x00000B3E }, /* ORIYA VOWEL SIGN O */ + { 0x00000B4C, 0x00000B47, 0x00000B57 }, /* ORIYA VOWEL SIGN AU */ + { 0x00000B5C, 0x00000B21, 0x00000B3C }, /* ORIYA LETTER RRA */ + { 0x00000B5D, 0x00000B22, 0x00000B3C }, /* ORIYA LETTER RHA */ + { 0x00000B94, 0x00000B92, 0x00000BD7 }, /* TAMIL LETTER AU */ + { 0x00000BCA, 0x00000BC6, 0x00000BBE }, /* TAMIL VOWEL SIGN O */ + { 0x00000BCB, 0x00000BC7, 0x00000BBE }, /* TAMIL VOWEL SIGN OO */ + { 0x00000BCC, 0x00000BC6, 0x00000BD7 }, /* TAMIL VOWEL SIGN AU */ + { 0x00000C48, 0x00000C46, 0x00000C56 }, /* TELUGU VOWEL SIGN AI */ + { 0x00000CC0, 0x00000CBF, 0x00000CD5 }, /* KANNADA VOWEL SIGN II */ + { 0x00000CC7, 0x00000CC6, 0x00000CD5 }, /* KANNADA VOWEL SIGN EE */ + { 0x00000CC8, 0x00000CC6, 0x00000CD6 }, /* KANNADA VOWEL SIGN AI */ + { 0x00000CCA, 0x00000CC6, 0x00000CC2 }, /* KANNADA VOWEL SIGN O */ + { 0x00000CCB, 0x00000CCA, 0x00000CD5 }, /* KANNADA VOWEL SIGN OO */ + { 0x00000D4A, 0x00000D46, 0x00000D3E }, /* MALAYALAM VOWEL SIGN O */ + { 0x00000D4B, 0x00000D47, 0x00000D3E }, /* MALAYALAM VOWEL SIGN OO */ + { 0x00000D4C, 0x00000D46, 0x00000D57 }, /* MALAYALAM VOWEL SIGN AU */ + { 0x00000DDA, 0x00000DD9, 0x00000DCA }, /* SINHALA VOWEL SIGN DIGA KOMBUVA */ + { 0x00000DDC, 0x00000DD9, 0x00000DCF }, /* SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA */ + { 0x00000DDD, 0x00000DDC, 0x00000DCA }, /* SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA */ + { 0x00000DDE, 0x00000DD9, 0x00000DDF }, /* SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA */ + { 0x00000F43, 0x00000F42, 0x00000FB7 }, /* TIBETAN LETTER GHA */ + { 0x00000F4D, 0x00000F4C, 0x00000FB7 }, /* TIBETAN LETTER DDHA */ + { 0x00000F52, 0x00000F51, 0x00000FB7 }, /* TIBETAN LETTER DHA */ + { 0x00000F57, 0x00000F56, 0x00000FB7 }, /* TIBETAN LETTER BHA */ + { 0x00000F5C, 0x00000F5B, 0x00000FB7 }, /* TIBETAN LETTER DZHA */ + { 0x00000F69, 0x00000F40, 0x00000FB5 }, /* TIBETAN LETTER KSSA */ + { 0x00000F73, 0x00000F71, 0x00000F72 }, /* TIBETAN VOWEL SIGN II */ + { 0x00000F75, 0x00000F71, 0x00000F74 }, /* TIBETAN VOWEL SIGN UU */ + { 0x00000F76, 0x00000FB2, 0x00000F80 }, /* TIBETAN VOWEL SIGN VOCALIC R */ + { 0x00000F78, 0x00000FB3, 0x00000F80 }, /* TIBETAN VOWEL SIGN VOCALIC L */ + { 0x00000F81, 0x00000F71, 0x00000F80 }, /* TIBETAN VOWEL SIGN REVERSED II */ + { 0x00000F93, 0x00000F92, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER GHA */ + { 0x00000F9D, 0x00000F9C, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER DDHA */ + { 0x00000FA2, 0x00000FA1, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER DHA */ + { 0x00000FA7, 0x00000FA6, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER BHA */ + { 0x00000FAC, 0x00000FAB, 0x00000FB7 }, /* TIBETAN SUBJOINED LETTER DZHA */ + { 0x00000FB9, 0x00000F90, 0x00000FB5 }, /* TIBETAN SUBJOINED LETTER KSSA */ + { 0x00001026, 0x00001025, 0x0000102E }, /* MYANMAR LETTER UU */ + { 0x00001B06, 0x00001B05, 0x00001B35 }, /* BALINESE LETTER AKARA TEDUNG */ + { 0x00001B08, 0x00001B07, 0x00001B35 }, /* BALINESE LETTER IKARA TEDUNG */ + { 0x00001B0A, 0x00001B09, 0x00001B35 }, /* BALINESE LETTER UKARA TEDUNG */ + { 0x00001B0C, 0x00001B0B, 0x00001B35 }, /* BALINESE LETTER RA REPA TEDUNG */ + { 0x00001B0E, 0x00001B0D, 0x00001B35 }, /* BALINESE LETTER LA LENGA TEDUNG */ + { 0x00001B12, 0x00001B11, 0x00001B35 }, /* BALINESE LETTER OKARA TEDUNG */ + { 0x00001B3B, 0x00001B3A, 0x00001B35 }, /* BALINESE VOWEL SIGN RA REPA TEDUNG */ + { 0x00001B3D, 0x00001B3C, 0x00001B35 }, /* BALINESE VOWEL SIGN LA LENGA TEDUNG */ + { 0x00001B40, 0x00001B3E, 0x00001B35 }, /* BALINESE VOWEL SIGN TALING TEDUNG */ + { 0x00001B41, 0x00001B3F, 0x00001B35 }, /* BALINESE VOWEL SIGN TALING REPA TEDUNG */ + { 0x00001B43, 0x00001B42, 0x00001B35 }, /* BALINESE VOWEL SIGN PEPET TEDUNG */ + { 0x00001E00, 0x00000041, 0x00000325 }, /* LATIN CAPITAL LETTER A WITH RING BELOW */ + { 0x00001E01, 0x00000061, 0x00000325 }, /* LATIN SMALL LETTER A WITH RING BELOW */ + { 0x00001E02, 0x00000042, 0x00000307 }, /* LATIN CAPITAL LETTER B WITH DOT ABOVE */ + { 0x00001E03, 0x00000062, 0x00000307 }, /* LATIN SMALL LETTER B WITH DOT ABOVE */ + { 0x00001E04, 0x00000042, 0x00000323 }, /* LATIN CAPITAL LETTER B WITH DOT BELOW */ + { 0x00001E05, 0x00000062, 0x00000323 }, /* LATIN SMALL LETTER B WITH DOT BELOW */ + { 0x00001E06, 0x00000042, 0x00000331 }, /* LATIN CAPITAL LETTER B WITH LINE BELOW */ + { 0x00001E07, 0x00000062, 0x00000331 }, /* LATIN SMALL LETTER B WITH LINE BELOW */ + { 0x00001E08, 0x000000C7, 0x00000301 }, /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE */ + { 0x00001E09, 0x000000E7, 0x00000301 }, /* LATIN SMALL LETTER C WITH CEDILLA AND ACUTE */ + { 0x00001E0A, 0x00000044, 0x00000307 }, /* LATIN CAPITAL LETTER D WITH DOT ABOVE */ + { 0x00001E0B, 0x00000064, 0x00000307 }, /* LATIN SMALL LETTER D WITH DOT ABOVE */ + { 0x00001E0C, 0x00000044, 0x00000323 }, /* LATIN CAPITAL LETTER D WITH DOT BELOW */ + { 0x00001E0D, 0x00000064, 0x00000323 }, /* LATIN SMALL LETTER D WITH DOT BELOW */ + { 0x00001E0E, 0x00000044, 0x00000331 }, /* LATIN CAPITAL LETTER D WITH LINE BELOW */ + { 0x00001E0F, 0x00000064, 0x00000331 }, /* LATIN SMALL LETTER D WITH LINE BELOW */ + { 0x00001E10, 0x00000044, 0x00000327 }, /* LATIN CAPITAL LETTER D WITH CEDILLA */ + { 0x00001E11, 0x00000064, 0x00000327 }, /* LATIN SMALL LETTER D WITH CEDILLA */ + { 0x00001E12, 0x00000044, 0x0000032D }, /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW */ + { 0x00001E13, 0x00000064, 0x0000032D }, /* LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW */ + { 0x00001E14, 0x00000112, 0x00000300 }, /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE */ + { 0x00001E15, 0x00000113, 0x00000300 }, /* LATIN SMALL LETTER E WITH MACRON AND GRAVE */ + { 0x00001E16, 0x00000112, 0x00000301 }, /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE */ + { 0x00001E17, 0x00000113, 0x00000301 }, /* LATIN SMALL LETTER E WITH MACRON AND ACUTE */ + { 0x00001E18, 0x00000045, 0x0000032D }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW */ + { 0x00001E19, 0x00000065, 0x0000032D }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW */ + { 0x00001E1A, 0x00000045, 0x00000330 }, /* LATIN CAPITAL LETTER E WITH TILDE BELOW */ + { 0x00001E1B, 0x00000065, 0x00000330 }, /* LATIN SMALL LETTER E WITH TILDE BELOW */ + { 0x00001E1C, 0x00000228, 0x00000306 }, /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE */ + { 0x00001E1D, 0x00000229, 0x00000306 }, /* LATIN SMALL LETTER E WITH CEDILLA AND BREVE */ + { 0x00001E1E, 0x00000046, 0x00000307 }, /* LATIN CAPITAL LETTER F WITH DOT ABOVE */ + { 0x00001E1F, 0x00000066, 0x00000307 }, /* LATIN SMALL LETTER F WITH DOT ABOVE */ + { 0x00001E20, 0x00000047, 0x00000304 }, /* LATIN CAPITAL LETTER G WITH MACRON */ + { 0x00001E21, 0x00000067, 0x00000304 }, /* LATIN SMALL LETTER G WITH MACRON */ + { 0x00001E22, 0x00000048, 0x00000307 }, /* LATIN CAPITAL LETTER H WITH DOT ABOVE */ + { 0x00001E23, 0x00000068, 0x00000307 }, /* LATIN SMALL LETTER H WITH DOT ABOVE */ + { 0x00001E24, 0x00000048, 0x00000323 }, /* LATIN CAPITAL LETTER H WITH DOT BELOW */ + { 0x00001E25, 0x00000068, 0x00000323 }, /* LATIN SMALL LETTER H WITH DOT BELOW */ + { 0x00001E26, 0x00000048, 0x00000308 }, /* LATIN CAPITAL LETTER H WITH DIAERESIS */ + { 0x00001E27, 0x00000068, 0x00000308 }, /* LATIN SMALL LETTER H WITH DIAERESIS */ + { 0x00001E28, 0x00000048, 0x00000327 }, /* LATIN CAPITAL LETTER H WITH CEDILLA */ + { 0x00001E29, 0x00000068, 0x00000327 }, /* LATIN SMALL LETTER H WITH CEDILLA */ + { 0x00001E2A, 0x00000048, 0x0000032E }, /* LATIN CAPITAL LETTER H WITH BREVE BELOW */ + { 0x00001E2B, 0x00000068, 0x0000032E }, /* LATIN SMALL LETTER H WITH BREVE BELOW */ + { 0x00001E2C, 0x00000049, 0x00000330 }, /* LATIN CAPITAL LETTER I WITH TILDE BELOW */ + { 0x00001E2D, 0x00000069, 0x00000330 }, /* LATIN SMALL LETTER I WITH TILDE BELOW */ + { 0x00001E2E, 0x000000CF, 0x00000301 }, /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE */ + { 0x00001E2F, 0x000000EF, 0x00000301 }, /* LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE */ + { 0x00001E30, 0x0000004B, 0x00000301 }, /* LATIN CAPITAL LETTER K WITH ACUTE */ + { 0x00001E31, 0x0000006B, 0x00000301 }, /* LATIN SMALL LETTER K WITH ACUTE */ + { 0x00001E32, 0x0000004B, 0x00000323 }, /* LATIN CAPITAL LETTER K WITH DOT BELOW */ + { 0x00001E33, 0x0000006B, 0x00000323 }, /* LATIN SMALL LETTER K WITH DOT BELOW */ + { 0x00001E34, 0x0000004B, 0x00000331 }, /* LATIN CAPITAL LETTER K WITH LINE BELOW */ + { 0x00001E35, 0x0000006B, 0x00000331 }, /* LATIN SMALL LETTER K WITH LINE BELOW */ + { 0x00001E36, 0x0000004C, 0x00000323 }, /* LATIN CAPITAL LETTER L WITH DOT BELOW */ + { 0x00001E37, 0x0000006C, 0x00000323 }, /* LATIN SMALL LETTER L WITH DOT BELOW */ + { 0x00001E38, 0x00001E36, 0x00000304 }, /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON */ + { 0x00001E39, 0x00001E37, 0x00000304 }, /* LATIN SMALL LETTER L WITH DOT BELOW AND MACRON */ + { 0x00001E3A, 0x0000004C, 0x00000331 }, /* LATIN CAPITAL LETTER L WITH LINE BELOW */ + { 0x00001E3B, 0x0000006C, 0x00000331 }, /* LATIN SMALL LETTER L WITH LINE BELOW */ + { 0x00001E3C, 0x0000004C, 0x0000032D }, /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW */ + { 0x00001E3D, 0x0000006C, 0x0000032D }, /* LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW */ + { 0x00001E3E, 0x0000004D, 0x00000301 }, /* LATIN CAPITAL LETTER M WITH ACUTE */ + { 0x00001E3F, 0x0000006D, 0x00000301 }, /* LATIN SMALL LETTER M WITH ACUTE */ + { 0x00001E40, 0x0000004D, 0x00000307 }, /* LATIN CAPITAL LETTER M WITH DOT ABOVE */ + { 0x00001E41, 0x0000006D, 0x00000307 }, /* LATIN SMALL LETTER M WITH DOT ABOVE */ + { 0x00001E42, 0x0000004D, 0x00000323 }, /* LATIN CAPITAL LETTER M WITH DOT BELOW */ + { 0x00001E43, 0x0000006D, 0x00000323 }, /* LATIN SMALL LETTER M WITH DOT BELOW */ + { 0x00001E44, 0x0000004E, 0x00000307 }, /* LATIN CAPITAL LETTER N WITH DOT ABOVE */ + { 0x00001E45, 0x0000006E, 0x00000307 }, /* LATIN SMALL LETTER N WITH DOT ABOVE */ + { 0x00001E46, 0x0000004E, 0x00000323 }, /* LATIN CAPITAL LETTER N WITH DOT BELOW */ + { 0x00001E47, 0x0000006E, 0x00000323 }, /* LATIN SMALL LETTER N WITH DOT BELOW */ + { 0x00001E48, 0x0000004E, 0x00000331 }, /* LATIN CAPITAL LETTER N WITH LINE BELOW */ + { 0x00001E49, 0x0000006E, 0x00000331 }, /* LATIN SMALL LETTER N WITH LINE BELOW */ + { 0x00001E4A, 0x0000004E, 0x0000032D }, /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW */ + { 0x00001E4B, 0x0000006E, 0x0000032D }, /* LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW */ + { 0x00001E4C, 0x000000D5, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE */ + { 0x00001E4D, 0x000000F5, 0x00000301 }, /* LATIN SMALL LETTER O WITH TILDE AND ACUTE */ + { 0x00001E4E, 0x000000D5, 0x00000308 }, /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS */ + { 0x00001E4F, 0x000000F5, 0x00000308 }, /* LATIN SMALL LETTER O WITH TILDE AND DIAERESIS */ + { 0x00001E50, 0x0000014C, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE */ + { 0x00001E51, 0x0000014D, 0x00000300 }, /* LATIN SMALL LETTER O WITH MACRON AND GRAVE */ + { 0x00001E52, 0x0000014C, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE */ + { 0x00001E53, 0x0000014D, 0x00000301 }, /* LATIN SMALL LETTER O WITH MACRON AND ACUTE */ + { 0x00001E54, 0x00000050, 0x00000301 }, /* LATIN CAPITAL LETTER P WITH ACUTE */ + { 0x00001E55, 0x00000070, 0x00000301 }, /* LATIN SMALL LETTER P WITH ACUTE */ + { 0x00001E56, 0x00000050, 0x00000307 }, /* LATIN CAPITAL LETTER P WITH DOT ABOVE */ + { 0x00001E57, 0x00000070, 0x00000307 }, /* LATIN SMALL LETTER P WITH DOT ABOVE */ + { 0x00001E58, 0x00000052, 0x00000307 }, /* LATIN CAPITAL LETTER R WITH DOT ABOVE */ + { 0x00001E59, 0x00000072, 0x00000307 }, /* LATIN SMALL LETTER R WITH DOT ABOVE */ + { 0x00001E5A, 0x00000052, 0x00000323 }, /* LATIN CAPITAL LETTER R WITH DOT BELOW */ + { 0x00001E5B, 0x00000072, 0x00000323 }, /* LATIN SMALL LETTER R WITH DOT BELOW */ + { 0x00001E5C, 0x00001E5A, 0x00000304 }, /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON */ + { 0x00001E5D, 0x00001E5B, 0x00000304 }, /* LATIN SMALL LETTER R WITH DOT BELOW AND MACRON */ + { 0x00001E5E, 0x00000052, 0x00000331 }, /* LATIN CAPITAL LETTER R WITH LINE BELOW */ + { 0x00001E5F, 0x00000072, 0x00000331 }, /* LATIN SMALL LETTER R WITH LINE BELOW */ + { 0x00001E60, 0x00000053, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH DOT ABOVE */ + { 0x00001E61, 0x00000073, 0x00000307 }, /* LATIN SMALL LETTER S WITH DOT ABOVE */ + { 0x00001E62, 0x00000053, 0x00000323 }, /* LATIN CAPITAL LETTER S WITH DOT BELOW */ + { 0x00001E63, 0x00000073, 0x00000323 }, /* LATIN SMALL LETTER S WITH DOT BELOW */ + { 0x00001E64, 0x0000015A, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE */ + { 0x00001E65, 0x0000015B, 0x00000307 }, /* LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE */ + { 0x00001E66, 0x00000160, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE */ + { 0x00001E67, 0x00000161, 0x00000307 }, /* LATIN SMALL LETTER S WITH CARON AND DOT ABOVE */ + { 0x00001E68, 0x00001E62, 0x00000307 }, /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE */ + { 0x00001E69, 0x00001E63, 0x00000307 }, /* LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE */ + { 0x00001E6A, 0x00000054, 0x00000307 }, /* LATIN CAPITAL LETTER T WITH DOT ABOVE */ + { 0x00001E6B, 0x00000074, 0x00000307 }, /* LATIN SMALL LETTER T WITH DOT ABOVE */ + { 0x00001E6C, 0x00000054, 0x00000323 }, /* LATIN CAPITAL LETTER T WITH DOT BELOW */ + { 0x00001E6D, 0x00000074, 0x00000323 }, /* LATIN SMALL LETTER T WITH DOT BELOW */ + { 0x00001E6E, 0x00000054, 0x00000331 }, /* LATIN CAPITAL LETTER T WITH LINE BELOW */ + { 0x00001E6F, 0x00000074, 0x00000331 }, /* LATIN SMALL LETTER T WITH LINE BELOW */ + { 0x00001E70, 0x00000054, 0x0000032D }, /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW */ + { 0x00001E71, 0x00000074, 0x0000032D }, /* LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW */ + { 0x00001E72, 0x00000055, 0x00000324 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW */ + { 0x00001E73, 0x00000075, 0x00000324 }, /* LATIN SMALL LETTER U WITH DIAERESIS BELOW */ + { 0x00001E74, 0x00000055, 0x00000330 }, /* LATIN CAPITAL LETTER U WITH TILDE BELOW */ + { 0x00001E75, 0x00000075, 0x00000330 }, /* LATIN SMALL LETTER U WITH TILDE BELOW */ + { 0x00001E76, 0x00000055, 0x0000032D }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW */ + { 0x00001E77, 0x00000075, 0x0000032D }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW */ + { 0x00001E78, 0x00000168, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE */ + { 0x00001E79, 0x00000169, 0x00000301 }, /* LATIN SMALL LETTER U WITH TILDE AND ACUTE */ + { 0x00001E7A, 0x0000016A, 0x00000308 }, /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS */ + { 0x00001E7B, 0x0000016B, 0x00000308 }, /* LATIN SMALL LETTER U WITH MACRON AND DIAERESIS */ + { 0x00001E7C, 0x00000056, 0x00000303 }, /* LATIN CAPITAL LETTER V WITH TILDE */ + { 0x00001E7D, 0x00000076, 0x00000303 }, /* LATIN SMALL LETTER V WITH TILDE */ + { 0x00001E7E, 0x00000056, 0x00000323 }, /* LATIN CAPITAL LETTER V WITH DOT BELOW */ + { 0x00001E7F, 0x00000076, 0x00000323 }, /* LATIN SMALL LETTER V WITH DOT BELOW */ + { 0x00001E80, 0x00000057, 0x00000300 }, /* LATIN CAPITAL LETTER W WITH GRAVE */ + { 0x00001E81, 0x00000077, 0x00000300 }, /* LATIN SMALL LETTER W WITH GRAVE */ + { 0x00001E82, 0x00000057, 0x00000301 }, /* LATIN CAPITAL LETTER W WITH ACUTE */ + { 0x00001E83, 0x00000077, 0x00000301 }, /* LATIN SMALL LETTER W WITH ACUTE */ + { 0x00001E84, 0x00000057, 0x00000308 }, /* LATIN CAPITAL LETTER W WITH DIAERESIS */ + { 0x00001E85, 0x00000077, 0x00000308 }, /* LATIN SMALL LETTER W WITH DIAERESIS */ + { 0x00001E86, 0x00000057, 0x00000307 }, /* LATIN CAPITAL LETTER W WITH DOT ABOVE */ + { 0x00001E87, 0x00000077, 0x00000307 }, /* LATIN SMALL LETTER W WITH DOT ABOVE */ + { 0x00001E88, 0x00000057, 0x00000323 }, /* LATIN CAPITAL LETTER W WITH DOT BELOW */ + { 0x00001E89, 0x00000077, 0x00000323 }, /* LATIN SMALL LETTER W WITH DOT BELOW */ + { 0x00001E8A, 0x00000058, 0x00000307 }, /* LATIN CAPITAL LETTER X WITH DOT ABOVE */ + { 0x00001E8B, 0x00000078, 0x00000307 }, /* LATIN SMALL LETTER X WITH DOT ABOVE */ + { 0x00001E8C, 0x00000058, 0x00000308 }, /* LATIN CAPITAL LETTER X WITH DIAERESIS */ + { 0x00001E8D, 0x00000078, 0x00000308 }, /* LATIN SMALL LETTER X WITH DIAERESIS */ + { 0x00001E8E, 0x00000059, 0x00000307 }, /* LATIN CAPITAL LETTER Y WITH DOT ABOVE */ + { 0x00001E8F, 0x00000079, 0x00000307 }, /* LATIN SMALL LETTER Y WITH DOT ABOVE */ + { 0x00001E90, 0x0000005A, 0x00000302 }, /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX */ + { 0x00001E91, 0x0000007A, 0x00000302 }, /* LATIN SMALL LETTER Z WITH CIRCUMFLEX */ + { 0x00001E92, 0x0000005A, 0x00000323 }, /* LATIN CAPITAL LETTER Z WITH DOT BELOW */ + { 0x00001E93, 0x0000007A, 0x00000323 }, /* LATIN SMALL LETTER Z WITH DOT BELOW */ + { 0x00001E94, 0x0000005A, 0x00000331 }, /* LATIN CAPITAL LETTER Z WITH LINE BELOW */ + { 0x00001E95, 0x0000007A, 0x00000331 }, /* LATIN SMALL LETTER Z WITH LINE BELOW */ + { 0x00001E96, 0x00000068, 0x00000331 }, /* LATIN SMALL LETTER H WITH LINE BELOW */ + { 0x00001E97, 0x00000074, 0x00000308 }, /* LATIN SMALL LETTER T WITH DIAERESIS */ + { 0x00001E98, 0x00000077, 0x0000030A }, /* LATIN SMALL LETTER W WITH RING ABOVE */ + { 0x00001E99, 0x00000079, 0x0000030A }, /* LATIN SMALL LETTER Y WITH RING ABOVE */ + { 0x00001E9B, 0x0000017F, 0x00000307 }, /* LATIN SMALL LETTER LONG S WITH DOT ABOVE */ + { 0x00001EA0, 0x00000041, 0x00000323 }, /* LATIN CAPITAL LETTER A WITH DOT BELOW */ + { 0x00001EA1, 0x00000061, 0x00000323 }, /* LATIN SMALL LETTER A WITH DOT BELOW */ + { 0x00001EA2, 0x00000041, 0x00000309 }, /* LATIN CAPITAL LETTER A WITH HOOK ABOVE */ + { 0x00001EA3, 0x00000061, 0x00000309 }, /* LATIN SMALL LETTER A WITH HOOK ABOVE */ + { 0x00001EA4, 0x000000C2, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EA5, 0x000000E2, 0x00000301 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EA6, 0x000000C2, 0x00000300 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EA7, 0x000000E2, 0x00000300 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EA8, 0x000000C2, 0x00000309 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001EA9, 0x000000E2, 0x00000309 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001EAA, 0x000000C2, 0x00000303 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ + { 0x00001EAB, 0x000000E2, 0x00000303 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */ + { 0x00001EAC, 0x00001EA0, 0x00000302 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EAD, 0x00001EA1, 0x00000302 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EAE, 0x00000102, 0x00000301 }, /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ + { 0x00001EAF, 0x00000103, 0x00000301 }, /* LATIN SMALL LETTER A WITH BREVE AND ACUTE */ + { 0x00001EB0, 0x00000102, 0x00000300 }, /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ + { 0x00001EB1, 0x00000103, 0x00000300 }, /* LATIN SMALL LETTER A WITH BREVE AND GRAVE */ + { 0x00001EB2, 0x00000102, 0x00000309 }, /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ + { 0x00001EB3, 0x00000103, 0x00000309 }, /* LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */ + { 0x00001EB4, 0x00000102, 0x00000303 }, /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ + { 0x00001EB5, 0x00000103, 0x00000303 }, /* LATIN SMALL LETTER A WITH BREVE AND TILDE */ + { 0x00001EB6, 0x00001EA0, 0x00000306 }, /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ + { 0x00001EB7, 0x00001EA1, 0x00000306 }, /* LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */ + { 0x00001EB8, 0x00000045, 0x00000323 }, /* LATIN CAPITAL LETTER E WITH DOT BELOW */ + { 0x00001EB9, 0x00000065, 0x00000323 }, /* LATIN SMALL LETTER E WITH DOT BELOW */ + { 0x00001EBA, 0x00000045, 0x00000309 }, /* LATIN CAPITAL LETTER E WITH HOOK ABOVE */ + { 0x00001EBB, 0x00000065, 0x00000309 }, /* LATIN SMALL LETTER E WITH HOOK ABOVE */ + { 0x00001EBC, 0x00000045, 0x00000303 }, /* LATIN CAPITAL LETTER E WITH TILDE */ + { 0x00001EBD, 0x00000065, 0x00000303 }, /* LATIN SMALL LETTER E WITH TILDE */ + { 0x00001EBE, 0x000000CA, 0x00000301 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EBF, 0x000000EA, 0x00000301 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */ + { 0x00001EC0, 0x000000CA, 0x00000300 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EC1, 0x000000EA, 0x00000300 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */ + { 0x00001EC2, 0x000000CA, 0x00000309 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001EC3, 0x000000EA, 0x00000309 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001EC4, 0x000000CA, 0x00000303 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ + { 0x00001EC5, 0x000000EA, 0x00000303 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */ + { 0x00001EC6, 0x00001EB8, 0x00000302 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EC7, 0x00001EB9, 0x00000302 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EC8, 0x00000049, 0x00000309 }, /* LATIN CAPITAL LETTER I WITH HOOK ABOVE */ + { 0x00001EC9, 0x00000069, 0x00000309 }, /* LATIN SMALL LETTER I WITH HOOK ABOVE */ + { 0x00001ECA, 0x00000049, 0x00000323 }, /* LATIN CAPITAL LETTER I WITH DOT BELOW */ + { 0x00001ECB, 0x00000069, 0x00000323 }, /* LATIN SMALL LETTER I WITH DOT BELOW */ + { 0x00001ECC, 0x0000004F, 0x00000323 }, /* LATIN CAPITAL LETTER O WITH DOT BELOW */ + { 0x00001ECD, 0x0000006F, 0x00000323 }, /* LATIN SMALL LETTER O WITH DOT BELOW */ + { 0x00001ECE, 0x0000004F, 0x00000309 }, /* LATIN CAPITAL LETTER O WITH HOOK ABOVE */ + { 0x00001ECF, 0x0000006F, 0x00000309 }, /* LATIN SMALL LETTER O WITH HOOK ABOVE */ + { 0x00001ED0, 0x000000D4, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ + { 0x00001ED1, 0x000000F4, 0x00000301 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */ + { 0x00001ED2, 0x000000D4, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ + { 0x00001ED3, 0x000000F4, 0x00000300 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */ + { 0x00001ED4, 0x000000D4, 0x00000309 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001ED5, 0x000000F4, 0x00000309 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ + { 0x00001ED6, 0x000000D4, 0x00000303 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ + { 0x00001ED7, 0x000000F4, 0x00000303 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */ + { 0x00001ED8, 0x00001ECC, 0x00000302 }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001ED9, 0x00001ECD, 0x00000302 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ + { 0x00001EDA, 0x000001A0, 0x00000301 }, /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ + { 0x00001EDB, 0x000001A1, 0x00000301 }, /* LATIN SMALL LETTER O WITH HORN AND ACUTE */ + { 0x00001EDC, 0x000001A0, 0x00000300 }, /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ + { 0x00001EDD, 0x000001A1, 0x00000300 }, /* LATIN SMALL LETTER O WITH HORN AND GRAVE */ + { 0x00001EDE, 0x000001A0, 0x00000309 }, /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ + { 0x00001EDF, 0x000001A1, 0x00000309 }, /* LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */ + { 0x00001EE0, 0x000001A0, 0x00000303 }, /* LATIN CAPITAL LETTER O WITH HORN AND TILDE */ + { 0x00001EE1, 0x000001A1, 0x00000303 }, /* LATIN SMALL LETTER O WITH HORN AND TILDE */ + { 0x00001EE2, 0x000001A0, 0x00000323 }, /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ + { 0x00001EE3, 0x000001A1, 0x00000323 }, /* LATIN SMALL LETTER O WITH HORN AND DOT BELOW */ + { 0x00001EE4, 0x00000055, 0x00000323 }, /* LATIN CAPITAL LETTER U WITH DOT BELOW */ + { 0x00001EE5, 0x00000075, 0x00000323 }, /* LATIN SMALL LETTER U WITH DOT BELOW */ + { 0x00001EE6, 0x00000055, 0x00000309 }, /* LATIN CAPITAL LETTER U WITH HOOK ABOVE */ + { 0x00001EE7, 0x00000075, 0x00000309 }, /* LATIN SMALL LETTER U WITH HOOK ABOVE */ + { 0x00001EE8, 0x000001AF, 0x00000301 }, /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ + { 0x00001EE9, 0x000001B0, 0x00000301 }, /* LATIN SMALL LETTER U WITH HORN AND ACUTE */ + { 0x00001EEA, 0x000001AF, 0x00000300 }, /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ + { 0x00001EEB, 0x000001B0, 0x00000300 }, /* LATIN SMALL LETTER U WITH HORN AND GRAVE */ + { 0x00001EEC, 0x000001AF, 0x00000309 }, /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ + { 0x00001EED, 0x000001B0, 0x00000309 }, /* LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */ + { 0x00001EEE, 0x000001AF, 0x00000303 }, /* LATIN CAPITAL LETTER U WITH HORN AND TILDE */ + { 0x00001EEF, 0x000001B0, 0x00000303 }, /* LATIN SMALL LETTER U WITH HORN AND TILDE */ + { 0x00001EF0, 0x000001AF, 0x00000323 }, /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ + { 0x00001EF1, 0x000001B0, 0x00000323 }, /* LATIN SMALL LETTER U WITH HORN AND DOT BELOW */ + { 0x00001EF2, 0x00000059, 0x00000300 }, /* LATIN CAPITAL LETTER Y WITH GRAVE */ + { 0x00001EF3, 0x00000079, 0x00000300 }, /* LATIN SMALL LETTER Y WITH GRAVE */ + { 0x00001EF4, 0x00000059, 0x00000323 }, /* LATIN CAPITAL LETTER Y WITH DOT BELOW */ + { 0x00001EF5, 0x00000079, 0x00000323 }, /* LATIN SMALL LETTER Y WITH DOT BELOW */ + { 0x00001EF6, 0x00000059, 0x00000309 }, /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ + { 0x00001EF7, 0x00000079, 0x00000309 }, /* LATIN SMALL LETTER Y WITH HOOK ABOVE */ + { 0x00001EF8, 0x00000059, 0x00000303 }, /* LATIN CAPITAL LETTER Y WITH TILDE */ + { 0x00001EF9, 0x00000079, 0x00000303 }, /* LATIN SMALL LETTER Y WITH TILDE */ + { 0x00001F00, 0x000003B1, 0x00000313 }, /* GREEK SMALL LETTER ALPHA WITH PSILI */ + { 0x00001F01, 0x000003B1, 0x00000314 }, /* GREEK SMALL LETTER ALPHA WITH DASIA */ + { 0x00001F02, 0x00001F00, 0x00000300 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA */ + { 0x00001F03, 0x00001F01, 0x00000300 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA */ + { 0x00001F04, 0x00001F00, 0x00000301 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA */ + { 0x00001F05, 0x00001F01, 0x00000301 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA */ + { 0x00001F06, 0x00001F00, 0x00000342 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI */ + { 0x00001F07, 0x00001F01, 0x00000342 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI */ + { 0x00001F08, 0x00000391, 0x00000313 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI */ + { 0x00001F09, 0x00000391, 0x00000314 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA */ + { 0x00001F0A, 0x00001F08, 0x00000300 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA */ + { 0x00001F0B, 0x00001F09, 0x00000300 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA */ + { 0x00001F0C, 0x00001F08, 0x00000301 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA */ + { 0x00001F0D, 0x00001F09, 0x00000301 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA */ + { 0x00001F0E, 0x00001F08, 0x00000342 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI */ + { 0x00001F0F, 0x00001F09, 0x00000342 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI */ + { 0x00001F10, 0x000003B5, 0x00000313 }, /* GREEK SMALL LETTER EPSILON WITH PSILI */ + { 0x00001F11, 0x000003B5, 0x00000314 }, /* GREEK SMALL LETTER EPSILON WITH DASIA */ + { 0x00001F12, 0x00001F10, 0x00000300 }, /* GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA */ + { 0x00001F13, 0x00001F11, 0x00000300 }, /* GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA */ + { 0x00001F14, 0x00001F10, 0x00000301 }, /* GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA */ + { 0x00001F15, 0x00001F11, 0x00000301 }, /* GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA */ + { 0x00001F18, 0x00000395, 0x00000313 }, /* GREEK CAPITAL LETTER EPSILON WITH PSILI */ + { 0x00001F19, 0x00000395, 0x00000314 }, /* GREEK CAPITAL LETTER EPSILON WITH DASIA */ + { 0x00001F1A, 0x00001F18, 0x00000300 }, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA */ + { 0x00001F1B, 0x00001F19, 0x00000300 }, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA */ + { 0x00001F1C, 0x00001F18, 0x00000301 }, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA */ + { 0x00001F1D, 0x00001F19, 0x00000301 }, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA */ + { 0x00001F20, 0x000003B7, 0x00000313 }, /* GREEK SMALL LETTER ETA WITH PSILI */ + { 0x00001F21, 0x000003B7, 0x00000314 }, /* GREEK SMALL LETTER ETA WITH DASIA */ + { 0x00001F22, 0x00001F20, 0x00000300 }, /* GREEK SMALL LETTER ETA WITH PSILI AND VARIA */ + { 0x00001F23, 0x00001F21, 0x00000300 }, /* GREEK SMALL LETTER ETA WITH DASIA AND VARIA */ + { 0x00001F24, 0x00001F20, 0x00000301 }, /* GREEK SMALL LETTER ETA WITH PSILI AND OXIA */ + { 0x00001F25, 0x00001F21, 0x00000301 }, /* GREEK SMALL LETTER ETA WITH DASIA AND OXIA */ + { 0x00001F26, 0x00001F20, 0x00000342 }, /* GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI */ + { 0x00001F27, 0x00001F21, 0x00000342 }, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI */ + { 0x00001F28, 0x00000397, 0x00000313 }, /* GREEK CAPITAL LETTER ETA WITH PSILI */ + { 0x00001F29, 0x00000397, 0x00000314 }, /* GREEK CAPITAL LETTER ETA WITH DASIA */ + { 0x00001F2A, 0x00001F28, 0x00000300 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA */ + { 0x00001F2B, 0x00001F29, 0x00000300 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA */ + { 0x00001F2C, 0x00001F28, 0x00000301 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA */ + { 0x00001F2D, 0x00001F29, 0x00000301 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA */ + { 0x00001F2E, 0x00001F28, 0x00000342 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI */ + { 0x00001F2F, 0x00001F29, 0x00000342 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI */ + { 0x00001F30, 0x000003B9, 0x00000313 }, /* GREEK SMALL LETTER IOTA WITH PSILI */ + { 0x00001F31, 0x000003B9, 0x00000314 }, /* GREEK SMALL LETTER IOTA WITH DASIA */ + { 0x00001F32, 0x00001F30, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH PSILI AND VARIA */ + { 0x00001F33, 0x00001F31, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH DASIA AND VARIA */ + { 0x00001F34, 0x00001F30, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH PSILI AND OXIA */ + { 0x00001F35, 0x00001F31, 0x00000301 }, /* GREEK SMALL LETTER IOTA WITH DASIA AND OXIA */ + { 0x00001F36, 0x00001F30, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI */ + { 0x00001F37, 0x00001F31, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI */ + { 0x00001F38, 0x00000399, 0x00000313 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI */ + { 0x00001F39, 0x00000399, 0x00000314 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA */ + { 0x00001F3A, 0x00001F38, 0x00000300 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA */ + { 0x00001F3B, 0x00001F39, 0x00000300 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA */ + { 0x00001F3C, 0x00001F38, 0x00000301 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA */ + { 0x00001F3D, 0x00001F39, 0x00000301 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA */ + { 0x00001F3E, 0x00001F38, 0x00000342 }, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI */ + { 0x00001F3F, 0x00001F39, 0x00000342 }, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI */ + { 0x00001F40, 0x000003BF, 0x00000313 }, /* GREEK SMALL LETTER OMICRON WITH PSILI */ + { 0x00001F41, 0x000003BF, 0x00000314 }, /* GREEK SMALL LETTER OMICRON WITH DASIA */ + { 0x00001F42, 0x00001F40, 0x00000300 }, /* GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA */ + { 0x00001F43, 0x00001F41, 0x00000300 }, /* GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA */ + { 0x00001F44, 0x00001F40, 0x00000301 }, /* GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA */ + { 0x00001F45, 0x00001F41, 0x00000301 }, /* GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA */ + { 0x00001F48, 0x0000039F, 0x00000313 }, /* GREEK CAPITAL LETTER OMICRON WITH PSILI */ + { 0x00001F49, 0x0000039F, 0x00000314 }, /* GREEK CAPITAL LETTER OMICRON WITH DASIA */ + { 0x00001F4A, 0x00001F48, 0x00000300 }, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA */ + { 0x00001F4B, 0x00001F49, 0x00000300 }, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA */ + { 0x00001F4C, 0x00001F48, 0x00000301 }, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA */ + { 0x00001F4D, 0x00001F49, 0x00000301 }, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA */ + { 0x00001F50, 0x000003C5, 0x00000313 }, /* GREEK SMALL LETTER UPSILON WITH PSILI */ + { 0x00001F51, 0x000003C5, 0x00000314 }, /* GREEK SMALL LETTER UPSILON WITH DASIA */ + { 0x00001F52, 0x00001F50, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA */ + { 0x00001F53, 0x00001F51, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA */ + { 0x00001F54, 0x00001F50, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA */ + { 0x00001F55, 0x00001F51, 0x00000301 }, /* GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA */ + { 0x00001F56, 0x00001F50, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI */ + { 0x00001F57, 0x00001F51, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI */ + { 0x00001F59, 0x000003A5, 0x00000314 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA */ + { 0x00001F5B, 0x00001F59, 0x00000300 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA */ + { 0x00001F5D, 0x00001F59, 0x00000301 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA */ + { 0x00001F5F, 0x00001F59, 0x00000342 }, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI */ + { 0x00001F60, 0x000003C9, 0x00000313 }, /* GREEK SMALL LETTER OMEGA WITH PSILI */ + { 0x00001F61, 0x000003C9, 0x00000314 }, /* GREEK SMALL LETTER OMEGA WITH DASIA */ + { 0x00001F62, 0x00001F60, 0x00000300 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA */ + { 0x00001F63, 0x00001F61, 0x00000300 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA */ + { 0x00001F64, 0x00001F60, 0x00000301 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA */ + { 0x00001F65, 0x00001F61, 0x00000301 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA */ + { 0x00001F66, 0x00001F60, 0x00000342 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI */ + { 0x00001F67, 0x00001F61, 0x00000342 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI */ + { 0x00001F68, 0x000003A9, 0x00000313 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI */ + { 0x00001F69, 0x000003A9, 0x00000314 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA */ + { 0x00001F6A, 0x00001F68, 0x00000300 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA */ + { 0x00001F6B, 0x00001F69, 0x00000300 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA */ + { 0x00001F6C, 0x00001F68, 0x00000301 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA */ + { 0x00001F6D, 0x00001F69, 0x00000301 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA */ + { 0x00001F6E, 0x00001F68, 0x00000342 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI */ + { 0x00001F6F, 0x00001F69, 0x00000342 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI */ + { 0x00001F70, 0x000003B1, 0x00000300 }, /* GREEK SMALL LETTER ALPHA WITH VARIA */ + { 0x00001F72, 0x000003B5, 0x00000300 }, /* GREEK SMALL LETTER EPSILON WITH VARIA */ + { 0x00001F74, 0x000003B7, 0x00000300 }, /* GREEK SMALL LETTER ETA WITH VARIA */ + { 0x00001F76, 0x000003B9, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH VARIA */ + { 0x00001F78, 0x000003BF, 0x00000300 }, /* GREEK SMALL LETTER OMICRON WITH VARIA */ + { 0x00001F7A, 0x000003C5, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH VARIA */ + { 0x00001F7C, 0x000003C9, 0x00000300 }, /* GREEK SMALL LETTER OMEGA WITH VARIA */ + { 0x00001F80, 0x00001F00, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI */ + { 0x00001F81, 0x00001F01, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI */ + { 0x00001F82, 0x00001F02, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F83, 0x00001F03, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F84, 0x00001F04, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F85, 0x00001F05, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F86, 0x00001F06, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F87, 0x00001F07, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F88, 0x00001F08, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */ + { 0x00001F89, 0x00001F09, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */ + { 0x00001F8A, 0x00001F0A, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F8B, 0x00001F0B, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F8C, 0x00001F0C, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F8D, 0x00001F0D, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F8E, 0x00001F0E, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001F8F, 0x00001F0F, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001F90, 0x00001F20, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI */ + { 0x00001F91, 0x00001F21, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI */ + { 0x00001F92, 0x00001F22, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F93, 0x00001F23, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + { 0x00001F94, 0x00001F24, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F95, 0x00001F25, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + { 0x00001F96, 0x00001F26, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F97, 0x00001F27, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001F98, 0x00001F28, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */ + { 0x00001F99, 0x00001F29, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */ + { 0x00001F9A, 0x00001F2A, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F9B, 0x00001F2B, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + { 0x00001F9C, 0x00001F2C, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F9D, 0x00001F2D, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + { 0x00001F9E, 0x00001F2E, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001F9F, 0x00001F2F, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001FA0, 0x00001F60, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI */ + { 0x00001FA1, 0x00001F61, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI */ + { 0x00001FA2, 0x00001F62, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ + { 0x00001FA3, 0x00001F63, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ + { 0x00001FA4, 0x00001F64, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ + { 0x00001FA5, 0x00001F65, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ + { 0x00001FA6, 0x00001F66, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FA7, 0x00001F67, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FA8, 0x00001F68, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */ + { 0x00001FA9, 0x00001F69, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */ + { 0x00001FAA, 0x00001F6A, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + { 0x00001FAB, 0x00001F6B, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + { 0x00001FAC, 0x00001F6C, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + { 0x00001FAD, 0x00001F6D, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + { 0x00001FAE, 0x00001F6E, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001FAF, 0x00001F6F, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + { 0x00001FB0, 0x000003B1, 0x00000306 }, /* GREEK SMALL LETTER ALPHA WITH VRACHY */ + { 0x00001FB1, 0x000003B1, 0x00000304 }, /* GREEK SMALL LETTER ALPHA WITH MACRON */ + { 0x00001FB2, 0x00001F70, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI */ + { 0x00001FB3, 0x000003B1, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI */ + { 0x00001FB4, 0x000003AC, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI */ + { 0x00001FB6, 0x000003B1, 0x00000342 }, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI */ + { 0x00001FB7, 0x00001FB6, 0x00000345 }, /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FB8, 0x00000391, 0x00000306 }, /* GREEK CAPITAL LETTER ALPHA WITH VRACHY */ + { 0x00001FB9, 0x00000391, 0x00000304 }, /* GREEK CAPITAL LETTER ALPHA WITH MACRON */ + { 0x00001FBA, 0x00000391, 0x00000300 }, /* GREEK CAPITAL LETTER ALPHA WITH VARIA */ + { 0x00001FBC, 0x00000391, 0x00000345 }, /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */ + { 0x00001FC1, 0x000000A8, 0x00000342 }, /* GREEK DIALYTIKA AND PERISPOMENI */ + { 0x00001FC2, 0x00001F74, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI */ + { 0x00001FC3, 0x000003B7, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI */ + { 0x00001FC4, 0x000003AE, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI */ + { 0x00001FC6, 0x000003B7, 0x00000342 }, /* GREEK SMALL LETTER ETA WITH PERISPOMENI */ + { 0x00001FC7, 0x00001FC6, 0x00000345 }, /* GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FC8, 0x00000395, 0x00000300 }, /* GREEK CAPITAL LETTER EPSILON WITH VARIA */ + { 0x00001FCA, 0x00000397, 0x00000300 }, /* GREEK CAPITAL LETTER ETA WITH VARIA */ + { 0x00001FCC, 0x00000397, 0x00000345 }, /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */ + { 0x00001FCD, 0x00001FBF, 0x00000300 }, /* GREEK PSILI AND VARIA */ + { 0x00001FCE, 0x00001FBF, 0x00000301 }, /* GREEK PSILI AND OXIA */ + { 0x00001FCF, 0x00001FBF, 0x00000342 }, /* GREEK PSILI AND PERISPOMENI */ + { 0x00001FD0, 0x000003B9, 0x00000306 }, /* GREEK SMALL LETTER IOTA WITH VRACHY */ + { 0x00001FD1, 0x000003B9, 0x00000304 }, /* GREEK SMALL LETTER IOTA WITH MACRON */ + { 0x00001FD2, 0x000003CA, 0x00000300 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA */ + { 0x00001FD6, 0x000003B9, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH PERISPOMENI */ + { 0x00001FD7, 0x000003CA, 0x00000342 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI */ + { 0x00001FD8, 0x00000399, 0x00000306 }, /* GREEK CAPITAL LETTER IOTA WITH VRACHY */ + { 0x00001FD9, 0x00000399, 0x00000304 }, /* GREEK CAPITAL LETTER IOTA WITH MACRON */ + { 0x00001FDA, 0x00000399, 0x00000300 }, /* GREEK CAPITAL LETTER IOTA WITH VARIA */ + { 0x00001FDD, 0x00001FFE, 0x00000300 }, /* GREEK DASIA AND VARIA */ + { 0x00001FDE, 0x00001FFE, 0x00000301 }, /* GREEK DASIA AND OXIA */ + { 0x00001FDF, 0x00001FFE, 0x00000342 }, /* GREEK DASIA AND PERISPOMENI */ + { 0x00001FE0, 0x000003C5, 0x00000306 }, /* GREEK SMALL LETTER UPSILON WITH VRACHY */ + { 0x00001FE1, 0x000003C5, 0x00000304 }, /* GREEK SMALL LETTER UPSILON WITH MACRON */ + { 0x00001FE2, 0x000003CB, 0x00000300 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA */ + { 0x00001FE4, 0x000003C1, 0x00000313 }, /* GREEK SMALL LETTER RHO WITH PSILI */ + { 0x00001FE5, 0x000003C1, 0x00000314 }, /* GREEK SMALL LETTER RHO WITH DASIA */ + { 0x00001FE6, 0x000003C5, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH PERISPOMENI */ + { 0x00001FE7, 0x000003CB, 0x00000342 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI */ + { 0x00001FE8, 0x000003A5, 0x00000306 }, /* GREEK CAPITAL LETTER UPSILON WITH VRACHY */ + { 0x00001FE9, 0x000003A5, 0x00000304 }, /* GREEK CAPITAL LETTER UPSILON WITH MACRON */ + { 0x00001FEA, 0x000003A5, 0x00000300 }, /* GREEK CAPITAL LETTER UPSILON WITH VARIA */ + { 0x00001FEC, 0x000003A1, 0x00000314 }, /* GREEK CAPITAL LETTER RHO WITH DASIA */ + { 0x00001FED, 0x000000A8, 0x00000300 }, /* GREEK DIALYTIKA AND VARIA */ + { 0x00001FF2, 0x00001F7C, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI */ + { 0x00001FF3, 0x000003C9, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI */ + { 0x00001FF4, 0x000003CE, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI */ + { 0x00001FF6, 0x000003C9, 0x00000342 }, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI */ + { 0x00001FF7, 0x00001FF6, 0x00000345 }, /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI */ + { 0x00001FF8, 0x0000039F, 0x00000300 }, /* GREEK CAPITAL LETTER OMICRON WITH VARIA */ + { 0x00001FFA, 0x000003A9, 0x00000300 }, /* GREEK CAPITAL LETTER OMEGA WITH VARIA */ + { 0x00001FFC, 0x000003A9, 0x00000345 }, /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */ +/*{ 0x0000219A, 0x00002190, 0x00000338 },*/ /* LEFTWARDS ARROW WITH STROKE */ +/*{ 0x0000219B, 0x00002192, 0x00000338 },*/ /* RIGHTWARDS ARROW WITH STROKE */ +/*{ 0x000021AE, 0x00002194, 0x00000338 },*/ /* LEFT RIGHT ARROW WITH STROKE */ +/*{ 0x000021CD, 0x000021D0, 0x00000338 },*/ /* LEFTWARDS DOUBLE ARROW WITH STROKE */ +/*{ 0x000021CE, 0x000021D4, 0x00000338 },*/ /* LEFT RIGHT DOUBLE ARROW WITH STROKE */ +/*{ 0x000021CF, 0x000021D2, 0x00000338 },*/ /* RIGHTWARDS DOUBLE ARROW WITH STROKE */ +/*{ 0x00002204, 0x00002203, 0x00000338 },*/ /* THERE DOES NOT EXIST */ +/*{ 0x00002209, 0x00002208, 0x00000338 },*/ /* NOT AN ELEMENT OF */ +/*{ 0x0000220C, 0x0000220B, 0x00000338 },*/ /* DOES NOT CONTAIN AS MEMBER */ +/*{ 0x00002224, 0x00002223, 0x00000338 },*/ /* DOES NOT DIVIDE */ +/*{ 0x00002226, 0x00002225, 0x00000338 },*/ /* NOT PARALLEL TO */ +/*{ 0x00002241, 0x0000223C, 0x00000338 },*/ /* NOT TILDE */ +/*{ 0x00002244, 0x00002243, 0x00000338 },*/ /* NOT ASYMPTOTICALLY EQUAL TO */ +/*{ 0x00002247, 0x00002245, 0x00000338 },*/ /* NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO */ +/*{ 0x00002249, 0x00002248, 0x00000338 },*/ /* NOT ALMOST EQUAL TO */ +/*{ 0x00002260, 0x0000003D, 0x00000338 },*/ /* NOT EQUAL TO */ +/*{ 0x00002262, 0x00002261, 0x00000338 },*/ /* NOT IDENTICAL TO */ +/*{ 0x0000226D, 0x0000224D, 0x00000338 },*/ /* NOT EQUIVALENT TO */ +/*{ 0x0000226E, 0x0000003C, 0x00000338 },*/ /* NOT LESS-THAN */ +/*{ 0x0000226F, 0x0000003E, 0x00000338 },*/ /* NOT GREATER-THAN */ +/*{ 0x00002270, 0x00002264, 0x00000338 },*/ /* NEITHER LESS-THAN NOR EQUAL TO */ +/*{ 0x00002271, 0x00002265, 0x00000338 },*/ /* NEITHER GREATER-THAN NOR EQUAL TO */ +/*{ 0x00002274, 0x00002272, 0x00000338 },*/ /* NEITHER LESS-THAN NOR EQUIVALENT TO */ +/*{ 0x00002275, 0x00002273, 0x00000338 },*/ /* NEITHER GREATER-THAN NOR EQUIVALENT TO */ +/*{ 0x00002278, 0x00002276, 0x00000338 },*/ /* NEITHER LESS-THAN NOR GREATER-THAN */ +/*{ 0x00002279, 0x00002277, 0x00000338 },*/ /* NEITHER GREATER-THAN NOR LESS-THAN */ +/*{ 0x00002280, 0x0000227A, 0x00000338 },*/ /* DOES NOT PRECEDE */ +/*{ 0x00002281, 0x0000227B, 0x00000338 },*/ /* DOES NOT SUCCEED */ +/*{ 0x00002284, 0x00002282, 0x00000338 },*/ /* NOT A SUBSET OF */ +/*{ 0x00002285, 0x00002283, 0x00000338 },*/ /* NOT A SUPERSET OF */ +/*{ 0x00002288, 0x00002286, 0x00000338 },*/ /* NEITHER A SUBSET OF NOR EQUAL TO */ +/*{ 0x00002289, 0x00002287, 0x00000338 },*/ /* NEITHER A SUPERSET OF NOR EQUAL TO */ +/*{ 0x000022AC, 0x000022A2, 0x00000338 },*/ /* DOES NOT PROVE */ +/*{ 0x000022AD, 0x000022A8, 0x00000338 },*/ /* NOT TRUE */ +/*{ 0x000022AE, 0x000022A9, 0x00000338 },*/ /* DOES NOT FORCE */ +/*{ 0x000022AF, 0x000022AB, 0x00000338 },*/ /* NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE */ +/*{ 0x000022E0, 0x0000227C, 0x00000338 },*/ /* DOES NOT PRECEDE OR EQUAL */ +/*{ 0x000022E1, 0x0000227D, 0x00000338 },*/ /* DOES NOT SUCCEED OR EQUAL */ +/*{ 0x000022E2, 0x00002291, 0x00000338 },*/ /* NOT SQUARE IMAGE OF OR EQUAL TO */ +/*{ 0x000022E3, 0x00002292, 0x00000338 },*/ /* NOT SQUARE ORIGINAL OF OR EQUAL TO */ +/*{ 0x000022EA, 0x000022B2, 0x00000338 },*/ /* NOT NORMAL SUBGROUP OF */ +/*{ 0x000022EB, 0x000022B3, 0x00000338 },*/ /* DOES NOT CONTAIN AS NORMAL SUBGROUP */ +/*{ 0x000022EC, 0x000022B4, 0x00000338 },*/ /* NOT NORMAL SUBGROUP OF OR EQUAL TO */ +/*{ 0x000022ED, 0x000022B5, 0x00000338 },*/ /* DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL */ +/*{ 0x00002ADC, 0x00002ADD, 0x00000338 },*/ /* FORKING */ + { 0x0000304C, 0x0000304B, 0x00003099 }, /* HIRAGANA LETTER GA */ + { 0x0000304E, 0x0000304D, 0x00003099 }, /* HIRAGANA LETTER GI */ + { 0x00003050, 0x0000304F, 0x00003099 }, /* HIRAGANA LETTER GU */ + { 0x00003052, 0x00003051, 0x00003099 }, /* HIRAGANA LETTER GE */ + { 0x00003054, 0x00003053, 0x00003099 }, /* HIRAGANA LETTER GO */ + { 0x00003056, 0x00003055, 0x00003099 }, /* HIRAGANA LETTER ZA */ + { 0x00003058, 0x00003057, 0x00003099 }, /* HIRAGANA LETTER ZI */ + { 0x0000305A, 0x00003059, 0x00003099 }, /* HIRAGANA LETTER ZU */ + { 0x0000305C, 0x0000305B, 0x00003099 }, /* HIRAGANA LETTER ZE */ + { 0x0000305E, 0x0000305D, 0x00003099 }, /* HIRAGANA LETTER ZO */ + { 0x00003060, 0x0000305F, 0x00003099 }, /* HIRAGANA LETTER DA */ + { 0x00003062, 0x00003061, 0x00003099 }, /* HIRAGANA LETTER DI */ + { 0x00003065, 0x00003064, 0x00003099 }, /* HIRAGANA LETTER DU */ + { 0x00003067, 0x00003066, 0x00003099 }, /* HIRAGANA LETTER DE */ + { 0x00003069, 0x00003068, 0x00003099 }, /* HIRAGANA LETTER DO */ + { 0x00003070, 0x0000306F, 0x00003099 }, /* HIRAGANA LETTER BA */ + { 0x00003071, 0x0000306F, 0x0000309A }, /* HIRAGANA LETTER PA */ + { 0x00003073, 0x00003072, 0x00003099 }, /* HIRAGANA LETTER BI */ + { 0x00003074, 0x00003072, 0x0000309A }, /* HIRAGANA LETTER PI */ + { 0x00003076, 0x00003075, 0x00003099 }, /* HIRAGANA LETTER BU */ + { 0x00003077, 0x00003075, 0x0000309A }, /* HIRAGANA LETTER PU */ + { 0x00003079, 0x00003078, 0x00003099 }, /* HIRAGANA LETTER BE */ + { 0x0000307A, 0x00003078, 0x0000309A }, /* HIRAGANA LETTER PE */ + { 0x0000307C, 0x0000307B, 0x00003099 }, /* HIRAGANA LETTER BO */ + { 0x0000307D, 0x0000307B, 0x0000309A }, /* HIRAGANA LETTER PO */ + { 0x00003094, 0x00003046, 0x00003099 }, /* HIRAGANA LETTER VU */ + { 0x0000309E, 0x0000309D, 0x00003099 }, /* HIRAGANA VOICED ITERATION MARK */ + { 0x000030AC, 0x000030AB, 0x00003099 }, /* KATAKANA LETTER GA */ + { 0x000030AE, 0x000030AD, 0x00003099 }, /* KATAKANA LETTER GI */ + { 0x000030B0, 0x000030AF, 0x00003099 }, /* KATAKANA LETTER GU */ + { 0x000030B2, 0x000030B1, 0x00003099 }, /* KATAKANA LETTER GE */ + { 0x000030B4, 0x000030B3, 0x00003099 }, /* KATAKANA LETTER GO */ + { 0x000030B6, 0x000030B5, 0x00003099 }, /* KATAKANA LETTER ZA */ + { 0x000030B8, 0x000030B7, 0x00003099 }, /* KATAKANA LETTER ZI */ + { 0x000030BA, 0x000030B9, 0x00003099 }, /* KATAKANA LETTER ZU */ + { 0x000030BC, 0x000030BB, 0x00003099 }, /* KATAKANA LETTER ZE */ + { 0x000030BE, 0x000030BD, 0x00003099 }, /* KATAKANA LETTER ZO */ + { 0x000030C0, 0x000030BF, 0x00003099 }, /* KATAKANA LETTER DA */ + { 0x000030C2, 0x000030C1, 0x00003099 }, /* KATAKANA LETTER DI */ + { 0x000030C5, 0x000030C4, 0x00003099 }, /* KATAKANA LETTER DU */ + { 0x000030C7, 0x000030C6, 0x00003099 }, /* KATAKANA LETTER DE */ + { 0x000030C9, 0x000030C8, 0x00003099 }, /* KATAKANA LETTER DO */ + { 0x000030D0, 0x000030CF, 0x00003099 }, /* KATAKANA LETTER BA */ + { 0x000030D1, 0x000030CF, 0x0000309A }, /* KATAKANA LETTER PA */ + { 0x000030D3, 0x000030D2, 0x00003099 }, /* KATAKANA LETTER BI */ + { 0x000030D4, 0x000030D2, 0x0000309A }, /* KATAKANA LETTER PI */ + { 0x000030D6, 0x000030D5, 0x00003099 }, /* KATAKANA LETTER BU */ + { 0x000030D7, 0x000030D5, 0x0000309A }, /* KATAKANA LETTER PU */ + { 0x000030D9, 0x000030D8, 0x00003099 }, /* KATAKANA LETTER BE */ + { 0x000030DA, 0x000030D8, 0x0000309A }, /* KATAKANA LETTER PE */ + { 0x000030DC, 0x000030DB, 0x00003099 }, /* KATAKANA LETTER BO */ + { 0x000030DD, 0x000030DB, 0x0000309A }, /* KATAKANA LETTER PO */ + { 0x000030F4, 0x000030A6, 0x00003099 }, /* KATAKANA LETTER VU */ + { 0x000030F7, 0x000030EF, 0x00003099 }, /* KATAKANA LETTER VA */ + { 0x000030F8, 0x000030F0, 0x00003099 }, /* KATAKANA LETTER VI */ + { 0x000030F9, 0x000030F1, 0x00003099 }, /* KATAKANA LETTER VE */ + { 0x000030FA, 0x000030F2, 0x00003099 }, /* KATAKANA LETTER VO */ + { 0x000030FE, 0x000030FD, 0x00003099 }, /* KATAKANA VOICED ITERATION MARK */ + { 0x0000FB1D, 0x000005D9, 0x000005B4 }, /* HEBREW LETTER YOD WITH HIRIQ */ + { 0x0000FB1F, 0x000005F2, 0x000005B7 }, /* HEBREW LIGATURE YIDDISH YOD YOD PATAH */ + { 0x0000FB2A, 0x000005E9, 0x000005C1 }, /* HEBREW LETTER SHIN WITH SHIN DOT */ + { 0x0000FB2B, 0x000005E9, 0x000005C2 }, /* HEBREW LETTER SHIN WITH SIN DOT */ + { 0x0000FB2C, 0x0000FB49, 0x000005C1 }, /* HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT */ + { 0x0000FB2D, 0x0000FB49, 0x000005C2 }, /* HEBREW LETTER SHIN WITH DAGESH AND SIN DOT */ + { 0x0000FB2E, 0x000005D0, 0x000005B7 }, /* HEBREW LETTER ALEF WITH PATAH */ + { 0x0000FB2F, 0x000005D0, 0x000005B8 }, /* HEBREW LETTER ALEF WITH QAMATS */ + { 0x0000FB30, 0x000005D0, 0x000005BC }, /* HEBREW LETTER ALEF WITH MAPIQ */ + { 0x0000FB31, 0x000005D1, 0x000005BC }, /* HEBREW LETTER BET WITH DAGESH */ + { 0x0000FB32, 0x000005D2, 0x000005BC }, /* HEBREW LETTER GIMEL WITH DAGESH */ + { 0x0000FB33, 0x000005D3, 0x000005BC }, /* HEBREW LETTER DALET WITH DAGESH */ + { 0x0000FB34, 0x000005D4, 0x000005BC }, /* HEBREW LETTER HE WITH MAPIQ */ + { 0x0000FB35, 0x000005D5, 0x000005BC }, /* HEBREW LETTER VAV WITH DAGESH */ + { 0x0000FB36, 0x000005D6, 0x000005BC }, /* HEBREW LETTER ZAYIN WITH DAGESH */ + { 0x0000FB38, 0x000005D8, 0x000005BC }, /* HEBREW LETTER TET WITH DAGESH */ + { 0x0000FB39, 0x000005D9, 0x000005BC }, /* HEBREW LETTER YOD WITH DAGESH */ + { 0x0000FB3A, 0x000005DA, 0x000005BC }, /* HEBREW LETTER FINAL KAF WITH DAGESH */ + { 0x0000FB3B, 0x000005DB, 0x000005BC }, /* HEBREW LETTER KAF WITH DAGESH */ + { 0x0000FB3C, 0x000005DC, 0x000005BC }, /* HEBREW LETTER LAMED WITH DAGESH */ + { 0x0000FB3E, 0x000005DE, 0x000005BC }, /* HEBREW LETTER MEM WITH DAGESH */ + { 0x0000FB40, 0x000005E0, 0x000005BC }, /* HEBREW LETTER NUN WITH DAGESH */ + { 0x0000FB41, 0x000005E1, 0x000005BC }, /* HEBREW LETTER SAMEKH WITH DAGESH */ + { 0x0000FB43, 0x000005E3, 0x000005BC }, /* HEBREW LETTER FINAL PE WITH DAGESH */ + { 0x0000FB44, 0x000005E4, 0x000005BC }, /* HEBREW LETTER PE WITH DAGESH */ + { 0x0000FB46, 0x000005E6, 0x000005BC }, /* HEBREW LETTER TSADI WITH DAGESH */ + { 0x0000FB47, 0x000005E7, 0x000005BC }, /* HEBREW LETTER QOF WITH DAGESH */ + { 0x0000FB48, 0x000005E8, 0x000005BC }, /* HEBREW LETTER RESH WITH DAGESH */ + { 0x0000FB49, 0x000005E9, 0x000005BC }, /* HEBREW LETTER SHIN WITH DAGESH */ + { 0x0000FB4A, 0x000005EA, 0x000005BC }, /* HEBREW LETTER TAV WITH DAGESH */ + { 0x0000FB4B, 0x000005D5, 0x000005B9 }, /* HEBREW LETTER VAV WITH HOLAM */ + { 0x0000FB4C, 0x000005D1, 0x000005BF }, /* HEBREW LETTER BET WITH RAFE */ + { 0x0000FB4D, 0x000005DB, 0x000005BF }, /* HEBREW LETTER KAF WITH RAFE */ + { 0x0000FB4E, 0x000005E4, 0x000005BF }, /* HEBREW LETTER PE WITH RAFE */ +/*{ 0x0001109A, 0x00011099, 0x000110BA },*/ /* KAITHI LETTER DDDHA */ +/*{ 0x0001109C, 0x0001109B, 0x000110BA },*/ /* KAITHI LETTER RHA */ +/*{ 0x000110AB, 0x000110A5, 0x000110BA },*/ /* KAITHI LETTER VA */ +/*{ 0x0001112E, 0x00011131, 0x00011127 },*/ /* CHAKMA VOWEL SIGN O */ +/*{ 0x0001112F, 0x00011132, 0x00011127 },*/ /* CHAKMA VOWEL SIGN AU */ +/*{ 0x0001134B, 0x00011347, 0x0001133E },*/ /* GRANTHA VOWEL SIGN OO */ +/*{ 0x0001134C, 0x00011347, 0x00011357 },*/ /* GRANTHA VOWEL SIGN AU */ +/*{ 0x000114BB, 0x000114B9, 0x000114BA },*/ /* TIRHUTA VOWEL SIGN AI */ +/*{ 0x000114BC, 0x000114B9, 0x000114B0 },*/ /* TIRHUTA VOWEL SIGN O */ +/*{ 0x000114BE, 0x000114B9, 0x000114BD },*/ /* TIRHUTA VOWEL SIGN AU */ +/*{ 0x000115BA, 0x000115B8, 0x000115AF },*/ /* SIDDHAM VOWEL SIGN O */ +/*{ 0x000115BB, 0x000115B9, 0x000115AF },*/ /* SIDDHAM VOWEL SIGN AU */ +/*{ 0x0001D15E, 0x0001D157, 0x0001D165 },*/ /* MUSICAL SYMBOL HALF NOTE */ +/*{ 0x0001D15F, 0x0001D158, 0x0001D165 },*/ /* MUSICAL SYMBOL QUARTER NOTE */ +/*{ 0x0001D160, 0x0001D15F, 0x0001D16E },*/ /* MUSICAL SYMBOL EIGHTH NOTE */ +/*{ 0x0001D161, 0x0001D15F, 0x0001D16F },*/ /* MUSICAL SYMBOL SIXTEENTH NOTE */ +/*{ 0x0001D162, 0x0001D15F, 0x0001D170 },*/ /* MUSICAL SYMBOL THIRTY-SECOND NOTE */ +/*{ 0x0001D163, 0x0001D15F, 0x0001D171 },*/ /* MUSICAL SYMBOL SIXTY-FOURTH NOTE */ +/*{ 0x0001D164, 0x0001D15F, 0x0001D172 },*/ /* MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE */ +/*{ 0x0001D1BB, 0x0001D1B9, 0x0001D165 },*/ /* MUSICAL SYMBOL MINIMA */ +/*{ 0x0001D1BC, 0x0001D1BA, 0x0001D165 },*/ /* MUSICAL SYMBOL MINIMA BLACK */ +/*{ 0x0001D1BD, 0x0001D1BB, 0x0001D16E },*/ /* MUSICAL SYMBOL SEMIMINIMA WHITE */ +/*{ 0x0001D1BE, 0x0001D1BC, 0x0001D16E },*/ /* MUSICAL SYMBOL SEMIMINIMA BLACK */ +/*{ 0x0001D1BF, 0x0001D1BB, 0x0001D16F },*/ /* MUSICAL SYMBOL FUSA WHITE */ +/*{ 0x0001D1C0, 0x0001D1BC, 0x0001D16F },*/ /* MUSICAL SYMBOL FUSA BLACK */ +}; + +static const struct { + unsigned int replacement_sp; + unsigned int base_sp; + unsigned int comb_sp; +} precompositions_sp[] = { + { 0xD804DC9A, 0xD804DC99, 0xD804DCBA }, /* KAITHI LETTER DDDHA */ + { 0xD804DC9C, 0xD804DC9B, 0xD804DCBA }, /* KAITHI LETTER RHA */ + { 0xD804DCAB, 0xD804DCA5, 0xD804DCBA }, /* KAITHI LETTER VA */ + { 0xD804DD2E, 0xD804DD31, 0xD804DD27 }, /* CHAKMA VOWEL SIGN O */ + { 0xD804DD2F, 0xD804DD32, 0xD804DD27 }, /* CHAKMA VOWEL SIGN AU */ + { 0xD804DF4B, 0xD804DF47, 0xD804DF3E }, /* GRANTHA VOWEL SIGN OO */ + { 0xD804DF4C, 0xD804DF47, 0xD804DF57 }, /* GRANTHA VOWEL SIGN AU */ + { 0xD805DCBC, 0xD805DCB9, 0xD805DCB0 }, /* TIRHUTA VOWEL SIGN O */ + { 0xD805DCBB, 0xD805DCB9, 0xD805DCBA }, /* TIRHUTA VOWEL SIGN AI */ + { 0xD805DCBE, 0xD805DCB9, 0xD805DCBD }, /* TIRHUTA VOWEL SIGN AU */ + { 0xD805DDBA, 0xD805DDB8, 0xD805DDAF }, /* SIDDHAM VOWEL SIGN O */ + { 0xD805DDBB, 0xD805DDB9, 0xD805DDAF }, /* SIDDHAM VOWEL SIGN AU */ + { 0xD834DD5E, 0xD834DD57, 0xD834DD65 }, /* MUSICAL SYMBOL HALF NOTE */ + { 0xD834DD5F, 0xD834DD58, 0xD834DD65 }, /* MUSICAL SYMBOL QUARTER NOTE */ + { 0xD834DD60, 0xD834DD5F, 0xD834DD6E }, /* MUSICAL SYMBOL EIGHTH NOTE */ + { 0xD834DD61, 0xD834DD5F, 0xD834DD6F }, /* MUSICAL SYMBOL SIXTEENTH NOTE */ + { 0xD834DD62, 0xD834DD5F, 0xD834DD70 }, /* MUSICAL SYMBOL THIRTY-SECOND NOTE */ + { 0xD834DD63, 0xD834DD5F, 0xD834DD71 }, /* MUSICAL SYMBOL SIXTY-FOURTH NOTE */ + { 0xD834DD64, 0xD834DD5F, 0xD834DD72 }, /* MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE */ + { 0xD834DDBB, 0xD834DDB9, 0xD834DD65 }, /* MUSICAL SYMBOL MINIMA */ + { 0xD834DDBC, 0xD834DDBA, 0xD834DD65 }, /* MUSICAL SYMBOL MINIMA BLACK */ + { 0xD834DDBD, 0xD834DDBB, 0xD834DD6E }, /* MUSICAL SYMBOL SEMIMINIMA WHITE */ + { 0xD834DDBF, 0xD834DDBB, 0xD834DD6F }, /* MUSICAL SYMBOL FUSA WHITE */ + { 0xD834DDBE, 0xD834DDBC, 0xD834DD6E }, /* MUSICAL SYMBOL SEMIMINIMA BLACK */ + { 0xD834DDC0, 0xD834DDBC, 0xD834DD6F }, /* MUSICAL SYMBOL FUSA BLACK */ +}; + +static const struct { + unsigned int replacement_sp; + unsigned int base_sp; + unsigned int comb_sp; +} decompositions_sp[] = { + { 0xD804DC9A, 0xD804DC99, 0xD804DCBA }, /* KAITHI LETTER DDDHA */ + { 0xD804DC9C, 0xD804DC9B, 0xD804DCBA }, /* KAITHI LETTER RHA */ + { 0xD804DCAB, 0xD804DCA5, 0xD804DCBA }, /* KAITHI LETTER VA */ + { 0xD804DD2E, 0xD804DD31, 0xD804DD27 }, /* CHAKMA VOWEL SIGN O */ + { 0xD804DD2F, 0xD804DD32, 0xD804DD27 }, /* CHAKMA VOWEL SIGN AU */ + { 0xD804DF4B, 0xD804DF47, 0xD804DF3E }, /* GRANTHA VOWEL SIGN OO */ + { 0xD804DF4C, 0xD804DF47, 0xD804DF57 }, /* GRANTHA VOWEL SIGN AU */ + { 0xD805DCBB, 0xD805DCB9, 0xD805DCBA }, /* TIRHUTA VOWEL SIGN AI */ + { 0xD805DCBC, 0xD805DCB9, 0xD805DCB0 }, /* TIRHUTA VOWEL SIGN O */ + { 0xD805DCBE, 0xD805DCB9, 0xD805DCBD }, /* TIRHUTA VOWEL SIGN AU */ + { 0xD805DDBA, 0xD805DDB8, 0xD805DDAF }, /* SIDDHAM VOWEL SIGN O */ + { 0xD805DDBB, 0xD805DDB9, 0xD805DDAF }, /* SIDDHAM VOWEL SIGN AU */ + { 0xD834DD5E, 0xD834DD57, 0xD834DD65 }, /* MUSICAL SYMBOL HALF NOTE */ + { 0xD834DD5F, 0xD834DD58, 0xD834DD65 }, /* MUSICAL SYMBOL QUARTER NOTE */ + { 0xD834DD60, 0xD834DD5F, 0xD834DD6E }, /* MUSICAL SYMBOL EIGHTH NOTE */ + { 0xD834DD61, 0xD834DD5F, 0xD834DD6F }, /* MUSICAL SYMBOL SIXTEENTH NOTE */ + { 0xD834DD62, 0xD834DD5F, 0xD834DD70 }, /* MUSICAL SYMBOL THIRTY-SECOND NOTE */ + { 0xD834DD63, 0xD834DD5F, 0xD834DD71 }, /* MUSICAL SYMBOL SIXTY-FOURTH NOTE */ + { 0xD834DD64, 0xD834DD5F, 0xD834DD72 }, /* MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE */ + { 0xD834DDBB, 0xD834DDB9, 0xD834DD65 }, /* MUSICAL SYMBOL MINIMA */ + { 0xD834DDBC, 0xD834DDBA, 0xD834DD65 }, /* MUSICAL SYMBOL MINIMA BLACK */ + { 0xD834DDBD, 0xD834DDBB, 0xD834DD6E }, /* MUSICAL SYMBOL SEMIMINIMA WHITE */ + { 0xD834DDBE, 0xD834DDBC, 0xD834DD6E }, /* MUSICAL SYMBOL SEMIMINIMA BLACK */ + { 0xD834DDBF, 0xD834DDBB, 0xD834DD6F }, /* MUSICAL SYMBOL FUSA WHITE */ + { 0xD834DDC0, 0xD834DDBC, 0xD834DD6F }, /* MUSICAL SYMBOL FUSA BLACK */ +}; + +/* EOF */ diff --git a/libatalk/unicode/utf16_case.c b/libatalk/unicode/utf16_case.c new file mode 100644 index 0000000..ca9285c --- /dev/null +++ b/libatalk/unicode/utf16_case.c @@ -0,0 +1,122 @@ +/* +DO NOT EDIT BY HAND!!! + +This file is generated by + contrib/shell_utils/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c + +UnicodeData.txt is got from +http://www.unicode.org/Public/UNIDATA/UnicodeData.txt +*/ + +#include +#include +#include "utf16_casetable.h" + +/******************************************************************* + Convert a wide character to upper case. +*******************************************************************/ +ucs2_t toupper_w(ucs2_t val) +{ + if ( val <= 0x02BF) + return upper_table_1[val]; + + if ( val >= 0x0340 && val <= 0x05BF) + return upper_table_2[val-0x0340]; + + if ( val >= 0x1D40 && val <= 0x1D7F) + return upper_table_3[val-0x1D40]; + + if ( val >= 0x1E00 && val <= 0x1FFF) + return upper_table_4[val-0x1E00]; + + if ( val >= 0x2140 && val <= 0x21BF) + return upper_table_5[val-0x2140]; + + if ( val >= 0x24C0 && val <= 0x24FF) + return upper_table_6[val-0x24C0]; + + if ( val >= 0x2C00 && val <= 0x2D3F) + return upper_table_7[val-0x2C00]; + + if ( val >= 0xA640 && val <= 0xA6BF) + return upper_table_8[val-0xA640]; + + if ( val >= 0xA700 && val <= 0xA7BF) + return upper_table_9[val-0xA700]; + + if ( val >= 0xFF40 && val <= 0xFF7F) + return upper_table_10[val-0xFF40]; + + return (val); +} + +/******************************************************************* + Convert a surrogate pair to upper case. +*******************************************************************/ +uint32_t toupper_sp(uint32_t val) +{ + if ( val >= 0xD801DC00 && val <= 0xD801DC7F) + return upper_table_sp_1[val-0xD801DC00]; + + if ( val >= 0xD806DCC0 && val <= 0xD806DCFF) + return upper_table_sp_2[val-0xD806DCC0]; + + return (val); +} + +/******************************************************************* + Convert a wide character to lower case. +*******************************************************************/ +ucs2_t tolower_w(ucs2_t val) +{ + if ( val <= 0x007F) + return lower_table_1[val]; + + if ( val >= 0x00C0 && val <= 0x027F) + return lower_table_2[val-0x00C0]; + + if ( val >= 0x0340 && val <= 0x057F) + return lower_table_3[val-0x0340]; + + if ( val >= 0x1080 && val <= 0x10FF) + return lower_table_4[val-0x1080]; + + if ( val >= 0x1E00 && val <= 0x1FFF) + return lower_table_5[val-0x1E00]; + + if ( val >= 0x2100 && val <= 0x21BF) + return lower_table_6[val-0x2100]; + + if ( val >= 0x2480 && val <= 0x24FF) + return lower_table_7[val-0x2480]; + + if ( val >= 0x2C00 && val <= 0x2CFF) + return lower_table_8[val-0x2C00]; + + if ( val >= 0xA640 && val <= 0xA6BF) + return lower_table_9[val-0xA640]; + + if ( val >= 0xA700 && val <= 0xA7BF) + return lower_table_10[val-0xA700]; + + if ( val >= 0xFF00 && val <= 0xFF3F) + return lower_table_11[val-0xFF00]; + + return (val); +} + +/******************************************************************* + Convert a surrogate pair to lower case. +*******************************************************************/ +uint32_t tolower_sp(uint32_t val) +{ + if ( val >= 0xD801DC00 && val <= 0xD801DC3F) + return lower_table_sp_1[val-0xD801DC00]; + + if ( val >= 0xD806DC80 && val <= 0xD806DCBF) + return lower_table_sp_2[val-0xD806DC80]; + + return (val); +} + +/* EOF */ diff --git a/libatalk/unicode/utf16_casetable.h b/libatalk/unicode/utf16_casetable.h new file mode 100644 index 0000000..4d32d78 --- /dev/null +++ b/libatalk/unicode/utf16_casetable.h @@ -0,0 +1,5974 @@ +/* +DO NOT EDIT BY HAND!!! + +This file is generated by + contrib/shell_utils/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c + +UnicodeData.txt is got from +http://www.unicode.org/Public/UNIDATA/UnicodeData.txt +*/ + +static const uint16_t upper_table_1[704] = { + 0x0000, /*U+0000*/ /**/ + 0x0001, /*U+0001*/ /**/ + 0x0002, /*U+0002*/ /**/ + 0x0003, /*U+0003*/ /**/ + 0x0004, /*U+0004*/ /**/ + 0x0005, /*U+0005*/ /**/ + 0x0006, /*U+0006*/ /**/ + 0x0007, /*U+0007*/ /**/ + 0x0008, /*U+0008*/ /**/ + 0x0009, /*U+0009*/ /**/ + 0x000A, /*U+000A*/ /**/ + 0x000B, /*U+000B*/ /**/ + 0x000C, /*U+000C*/ /**/ + 0x000D, /*U+000D*/ /**/ + 0x000E, /*U+000E*/ /**/ + 0x000F, /*U+000F*/ /**/ + 0x0010, /*U+0010*/ /**/ + 0x0011, /*U+0011*/ /**/ + 0x0012, /*U+0012*/ /**/ + 0x0013, /*U+0013*/ /**/ + 0x0014, /*U+0014*/ /**/ + 0x0015, /*U+0015*/ /**/ + 0x0016, /*U+0016*/ /**/ + 0x0017, /*U+0017*/ /**/ + 0x0018, /*U+0018*/ /**/ + 0x0019, /*U+0019*/ /**/ + 0x001A, /*U+001A*/ /**/ + 0x001B, /*U+001B*/ /**/ + 0x001C, /*U+001C*/ /**/ + 0x001D, /*U+001D*/ /**/ + 0x001E, /*U+001E*/ /**/ + 0x001F, /*U+001F*/ /**/ + 0x0020, /*U+0020*/ /**/ + 0x0021, /*U+0021*/ /**/ + 0x0022, /*U+0022*/ /**/ + 0x0023, /*U+0023*/ /**/ + 0x0024, /*U+0024*/ /**/ + 0x0025, /*U+0025*/ /**/ + 0x0026, /*U+0026*/ /**/ + 0x0027, /*U+0027*/ /**/ + 0x0028, /*U+0028*/ /**/ + 0x0029, /*U+0029*/ /**/ + 0x002A, /*U+002A*/ /**/ + 0x002B, /*U+002B*/ /**/ + 0x002C, /*U+002C*/ /**/ + 0x002D, /*U+002D*/ /**/ + 0x002E, /*U+002E*/ /**/ + 0x002F, /*U+002F*/ /**/ + 0x0030, /*U+0030*/ /**/ + 0x0031, /*U+0031*/ /**/ + 0x0032, /*U+0032*/ /**/ + 0x0033, /*U+0033*/ /**/ + 0x0034, /*U+0034*/ /**/ + 0x0035, /*U+0035*/ /**/ + 0x0036, /*U+0036*/ /**/ + 0x0037, /*U+0037*/ /**/ + 0x0038, /*U+0038*/ /**/ + 0x0039, /*U+0039*/ /**/ + 0x003A, /*U+003A*/ /**/ + 0x003B, /*U+003B*/ /**/ + 0x003C, /*U+003C*/ /**/ + 0x003D, /*U+003D*/ /**/ + 0x003E, /*U+003E*/ /**/ + 0x003F, /*U+003F*/ /**/ + 0x0040, /*U+0040*/ /**/ + 0x0041, /*U+0041*/ /**/ + 0x0042, /*U+0042*/ /**/ + 0x0043, /*U+0043*/ /**/ + 0x0044, /*U+0044*/ /**/ + 0x0045, /*U+0045*/ /**/ + 0x0046, /*U+0046*/ /**/ + 0x0047, /*U+0047*/ /**/ + 0x0048, /*U+0048*/ /**/ + 0x0049, /*U+0049*/ /**/ + 0x004A, /*U+004A*/ /**/ + 0x004B, /*U+004B*/ /**/ + 0x004C, /*U+004C*/ /**/ + 0x004D, /*U+004D*/ /**/ + 0x004E, /*U+004E*/ /**/ + 0x004F, /*U+004F*/ /**/ + 0x0050, /*U+0050*/ /**/ + 0x0051, /*U+0051*/ /**/ + 0x0052, /*U+0052*/ /**/ + 0x0053, /*U+0053*/ /**/ + 0x0054, /*U+0054*/ /**/ + 0x0055, /*U+0055*/ /**/ + 0x0056, /*U+0056*/ /**/ + 0x0057, /*U+0057*/ /**/ + 0x0058, /*U+0058*/ /**/ + 0x0059, /*U+0059*/ /**/ + 0x005A, /*U+005A*/ /**/ + 0x005B, /*U+005B*/ /**/ + 0x005C, /*U+005C*/ /**/ + 0x005D, /*U+005D*/ /**/ + 0x005E, /*U+005E*/ /**/ + 0x005F, /*U+005F*/ /**/ + 0x0060, /*U+0060*/ /**/ + 0x0041, /*U+0061*/ /*LATIN SMALL LETTER A*/ + 0x0042, /*U+0062*/ /*LATIN SMALL LETTER B*/ + 0x0043, /*U+0063*/ /*LATIN SMALL LETTER C*/ + 0x0044, /*U+0064*/ /*LATIN SMALL LETTER D*/ + 0x0045, /*U+0065*/ /*LATIN SMALL LETTER E*/ + 0x0046, /*U+0066*/ /*LATIN SMALL LETTER F*/ + 0x0047, /*U+0067*/ /*LATIN SMALL LETTER G*/ + 0x0048, /*U+0068*/ /*LATIN SMALL LETTER H*/ + 0x0049, /*U+0069*/ /*LATIN SMALL LETTER I*/ + 0x004A, /*U+006A*/ /*LATIN SMALL LETTER J*/ + 0x004B, /*U+006B*/ /*LATIN SMALL LETTER K*/ + 0x004C, /*U+006C*/ /*LATIN SMALL LETTER L*/ + 0x004D, /*U+006D*/ /*LATIN SMALL LETTER M*/ + 0x004E, /*U+006E*/ /*LATIN SMALL LETTER N*/ + 0x004F, /*U+006F*/ /*LATIN SMALL LETTER O*/ + 0x0050, /*U+0070*/ /*LATIN SMALL LETTER P*/ + 0x0051, /*U+0071*/ /*LATIN SMALL LETTER Q*/ + 0x0052, /*U+0072*/ /*LATIN SMALL LETTER R*/ + 0x0053, /*U+0073*/ /*LATIN SMALL LETTER S*/ + 0x0054, /*U+0074*/ /*LATIN SMALL LETTER T*/ + 0x0055, /*U+0075*/ /*LATIN SMALL LETTER U*/ + 0x0056, /*U+0076*/ /*LATIN SMALL LETTER V*/ + 0x0057, /*U+0077*/ /*LATIN SMALL LETTER W*/ + 0x0058, /*U+0078*/ /*LATIN SMALL LETTER X*/ + 0x0059, /*U+0079*/ /*LATIN SMALL LETTER Y*/ + 0x005A, /*U+007A*/ /*LATIN SMALL LETTER Z*/ + 0x007B, /*U+007B*/ /**/ + 0x007C, /*U+007C*/ /**/ + 0x007D, /*U+007D*/ /**/ + 0x007E, /*U+007E*/ /**/ + 0x007F, /*U+007F*/ /**/ + 0x0080, /*U+0080*/ /**/ + 0x0081, /*U+0081*/ /**/ + 0x0082, /*U+0082*/ /**/ + 0x0083, /*U+0083*/ /**/ + 0x0084, /*U+0084*/ /**/ + 0x0085, /*U+0085*/ /**/ + 0x0086, /*U+0086*/ /**/ + 0x0087, /*U+0087*/ /**/ + 0x0088, /*U+0088*/ /**/ + 0x0089, /*U+0089*/ /**/ + 0x008A, /*U+008A*/ /**/ + 0x008B, /*U+008B*/ /**/ + 0x008C, /*U+008C*/ /**/ + 0x008D, /*U+008D*/ /**/ + 0x008E, /*U+008E*/ /**/ + 0x008F, /*U+008F*/ /**/ + 0x0090, /*U+0090*/ /**/ + 0x0091, /*U+0091*/ /**/ + 0x0092, /*U+0092*/ /**/ + 0x0093, /*U+0093*/ /**/ + 0x0094, /*U+0094*/ /**/ + 0x0095, /*U+0095*/ /**/ + 0x0096, /*U+0096*/ /**/ + 0x0097, /*U+0097*/ /**/ + 0x0098, /*U+0098*/ /**/ + 0x0099, /*U+0099*/ /**/ + 0x009A, /*U+009A*/ /**/ + 0x009B, /*U+009B*/ /**/ + 0x009C, /*U+009C*/ /**/ + 0x009D, /*U+009D*/ /**/ + 0x009E, /*U+009E*/ /**/ + 0x009F, /*U+009F*/ /**/ + 0x00A0, /*U+00A0*/ /**/ + 0x00A1, /*U+00A1*/ /**/ + 0x00A2, /*U+00A2*/ /**/ + 0x00A3, /*U+00A3*/ /**/ + 0x00A4, /*U+00A4*/ /**/ + 0x00A5, /*U+00A5*/ /**/ + 0x00A6, /*U+00A6*/ /**/ + 0x00A7, /*U+00A7*/ /**/ + 0x00A8, /*U+00A8*/ /**/ + 0x00A9, /*U+00A9*/ /**/ + 0x00AA, /*U+00AA*/ /**/ + 0x00AB, /*U+00AB*/ /**/ + 0x00AC, /*U+00AC*/ /**/ + 0x00AD, /*U+00AD*/ /**/ + 0x00AE, /*U+00AE*/ /**/ + 0x00AF, /*U+00AF*/ /**/ + 0x00B0, /*U+00B0*/ /**/ + 0x00B1, /*U+00B1*/ /**/ + 0x00B2, /*U+00B2*/ /**/ + 0x00B3, /*U+00B3*/ /**/ + 0x00B4, /*U+00B4*/ /**/ + 0x039C, /*U+00B5*/ /*MICRO SIGN*/ + 0x00B6, /*U+00B6*/ /**/ + 0x00B7, /*U+00B7*/ /**/ + 0x00B8, /*U+00B8*/ /**/ + 0x00B9, /*U+00B9*/ /**/ + 0x00BA, /*U+00BA*/ /**/ + 0x00BB, /*U+00BB*/ /**/ + 0x00BC, /*U+00BC*/ /**/ + 0x00BD, /*U+00BD*/ /**/ + 0x00BE, /*U+00BE*/ /**/ + 0x00BF, /*U+00BF*/ /**/ + 0x00C0, /*U+00C0*/ /**/ + 0x00C1, /*U+00C1*/ /**/ + 0x00C2, /*U+00C2*/ /**/ + 0x00C3, /*U+00C3*/ /**/ + 0x00C4, /*U+00C4*/ /**/ + 0x00C5, /*U+00C5*/ /**/ + 0x00C6, /*U+00C6*/ /**/ + 0x00C7, /*U+00C7*/ /**/ + 0x00C8, /*U+00C8*/ /**/ + 0x00C9, /*U+00C9*/ /**/ + 0x00CA, /*U+00CA*/ /**/ + 0x00CB, /*U+00CB*/ /**/ + 0x00CC, /*U+00CC*/ /**/ + 0x00CD, /*U+00CD*/ /**/ + 0x00CE, /*U+00CE*/ /**/ + 0x00CF, /*U+00CF*/ /**/ + 0x00D0, /*U+00D0*/ /**/ + 0x00D1, /*U+00D1*/ /**/ + 0x00D2, /*U+00D2*/ /**/ + 0x00D3, /*U+00D3*/ /**/ + 0x00D4, /*U+00D4*/ /**/ + 0x00D5, /*U+00D5*/ /**/ + 0x00D6, /*U+00D6*/ /**/ + 0x00D7, /*U+00D7*/ /**/ + 0x00D8, /*U+00D8*/ /**/ + 0x00D9, /*U+00D9*/ /**/ + 0x00DA, /*U+00DA*/ /**/ + 0x00DB, /*U+00DB*/ /**/ + 0x00DC, /*U+00DC*/ /**/ + 0x00DD, /*U+00DD*/ /**/ + 0x00DE, /*U+00DE*/ /**/ + 0x00DF, /*U+00DF*/ /**/ + 0x00C0, /*U+00E0*/ /*LATIN SMALL LETTER A WITH GRAVE*/ + 0x00C1, /*U+00E1*/ /*LATIN SMALL LETTER A WITH ACUTE*/ + 0x00C2, /*U+00E2*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX*/ + 0x00C3, /*U+00E3*/ /*LATIN SMALL LETTER A WITH TILDE*/ + 0x00C4, /*U+00E4*/ /*LATIN SMALL LETTER A WITH DIAERESIS*/ + 0x00C5, /*U+00E5*/ /*LATIN SMALL LETTER A WITH RING ABOVE*/ + 0x00C6, /*U+00E6*/ /*LATIN SMALL LETTER AE*/ + 0x00C7, /*U+00E7*/ /*LATIN SMALL LETTER C WITH CEDILLA*/ + 0x00C8, /*U+00E8*/ /*LATIN SMALL LETTER E WITH GRAVE*/ + 0x00C9, /*U+00E9*/ /*LATIN SMALL LETTER E WITH ACUTE*/ + 0x00CA, /*U+00EA*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX*/ + 0x00CB, /*U+00EB*/ /*LATIN SMALL LETTER E WITH DIAERESIS*/ + 0x00CC, /*U+00EC*/ /*LATIN SMALL LETTER I WITH GRAVE*/ + 0x00CD, /*U+00ED*/ /*LATIN SMALL LETTER I WITH ACUTE*/ + 0x00CE, /*U+00EE*/ /*LATIN SMALL LETTER I WITH CIRCUMFLEX*/ + 0x00CF, /*U+00EF*/ /*LATIN SMALL LETTER I WITH DIAERESIS*/ + 0x00D0, /*U+00F0*/ /*LATIN SMALL LETTER ETH*/ + 0x00D1, /*U+00F1*/ /*LATIN SMALL LETTER N WITH TILDE*/ + 0x00D2, /*U+00F2*/ /*LATIN SMALL LETTER O WITH GRAVE*/ + 0x00D3, /*U+00F3*/ /*LATIN SMALL LETTER O WITH ACUTE*/ + 0x00D4, /*U+00F4*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX*/ + 0x00D5, /*U+00F5*/ /*LATIN SMALL LETTER O WITH TILDE*/ + 0x00D6, /*U+00F6*/ /*LATIN SMALL LETTER O WITH DIAERESIS*/ + 0x00F7, /*U+00F7*/ /**/ + 0x00D8, /*U+00F8*/ /*LATIN SMALL LETTER O WITH STROKE*/ + 0x00D9, /*U+00F9*/ /*LATIN SMALL LETTER U WITH GRAVE*/ + 0x00DA, /*U+00FA*/ /*LATIN SMALL LETTER U WITH ACUTE*/ + 0x00DB, /*U+00FB*/ /*LATIN SMALL LETTER U WITH CIRCUMFLEX*/ + 0x00DC, /*U+00FC*/ /*LATIN SMALL LETTER U WITH DIAERESIS*/ + 0x00DD, /*U+00FD*/ /*LATIN SMALL LETTER Y WITH ACUTE*/ + 0x00DE, /*U+00FE*/ /*LATIN SMALL LETTER THORN*/ + 0x0178, /*U+00FF*/ /*LATIN SMALL LETTER Y WITH DIAERESIS*/ + 0x0100, /*U+0100*/ /**/ + 0x0100, /*U+0101*/ /*LATIN SMALL LETTER A WITH MACRON*/ + 0x0102, /*U+0102*/ /**/ + 0x0102, /*U+0103*/ /*LATIN SMALL LETTER A WITH BREVE*/ + 0x0104, /*U+0104*/ /**/ + 0x0104, /*U+0105*/ /*LATIN SMALL LETTER A WITH OGONEK*/ + 0x0106, /*U+0106*/ /**/ + 0x0106, /*U+0107*/ /*LATIN SMALL LETTER C WITH ACUTE*/ + 0x0108, /*U+0108*/ /**/ + 0x0108, /*U+0109*/ /*LATIN SMALL LETTER C WITH CIRCUMFLEX*/ + 0x010A, /*U+010A*/ /**/ + 0x010A, /*U+010B*/ /*LATIN SMALL LETTER C WITH DOT ABOVE*/ + 0x010C, /*U+010C*/ /**/ + 0x010C, /*U+010D*/ /*LATIN SMALL LETTER C WITH CARON*/ + 0x010E, /*U+010E*/ /**/ + 0x010E, /*U+010F*/ /*LATIN SMALL LETTER D WITH CARON*/ + 0x0110, /*U+0110*/ /**/ + 0x0110, /*U+0111*/ /*LATIN SMALL LETTER D WITH STROKE*/ + 0x0112, /*U+0112*/ /**/ + 0x0112, /*U+0113*/ /*LATIN SMALL LETTER E WITH MACRON*/ + 0x0114, /*U+0114*/ /**/ + 0x0114, /*U+0115*/ /*LATIN SMALL LETTER E WITH BREVE*/ + 0x0116, /*U+0116*/ /**/ + 0x0116, /*U+0117*/ /*LATIN SMALL LETTER E WITH DOT ABOVE*/ + 0x0118, /*U+0118*/ /**/ + 0x0118, /*U+0119*/ /*LATIN SMALL LETTER E WITH OGONEK*/ + 0x011A, /*U+011A*/ /**/ + 0x011A, /*U+011B*/ /*LATIN SMALL LETTER E WITH CARON*/ + 0x011C, /*U+011C*/ /**/ + 0x011C, /*U+011D*/ /*LATIN SMALL LETTER G WITH CIRCUMFLEX*/ + 0x011E, /*U+011E*/ /**/ + 0x011E, /*U+011F*/ /*LATIN SMALL LETTER G WITH BREVE*/ + 0x0120, /*U+0120*/ /**/ + 0x0120, /*U+0121*/ /*LATIN SMALL LETTER G WITH DOT ABOVE*/ + 0x0122, /*U+0122*/ /**/ + 0x0122, /*U+0123*/ /*LATIN SMALL LETTER G WITH CEDILLA*/ + 0x0124, /*U+0124*/ /**/ + 0x0124, /*U+0125*/ /*LATIN SMALL LETTER H WITH CIRCUMFLEX*/ + 0x0126, /*U+0126*/ /**/ + 0x0126, /*U+0127*/ /*LATIN SMALL LETTER H WITH STROKE*/ + 0x0128, /*U+0128*/ /**/ + 0x0128, /*U+0129*/ /*LATIN SMALL LETTER I WITH TILDE*/ + 0x012A, /*U+012A*/ /**/ + 0x012A, /*U+012B*/ /*LATIN SMALL LETTER I WITH MACRON*/ + 0x012C, /*U+012C*/ /**/ + 0x012C, /*U+012D*/ /*LATIN SMALL LETTER I WITH BREVE*/ + 0x012E, /*U+012E*/ /**/ + 0x012E, /*U+012F*/ /*LATIN SMALL LETTER I WITH OGONEK*/ + 0x0130, /*U+0130*/ /**/ + 0x0049, /*U+0131*/ /*LATIN SMALL LETTER DOTLESS I*/ + 0x0132, /*U+0132*/ /**/ + 0x0132, /*U+0133*/ /*LATIN SMALL LIGATURE IJ*/ + 0x0134, /*U+0134*/ /**/ + 0x0134, /*U+0135*/ /*LATIN SMALL LETTER J WITH CIRCUMFLEX*/ + 0x0136, /*U+0136*/ /**/ + 0x0136, /*U+0137*/ /*LATIN SMALL LETTER K WITH CEDILLA*/ + 0x0138, /*U+0138*/ /**/ + 0x0139, /*U+0139*/ /**/ + 0x0139, /*U+013A*/ /*LATIN SMALL LETTER L WITH ACUTE*/ + 0x013B, /*U+013B*/ /**/ + 0x013B, /*U+013C*/ /*LATIN SMALL LETTER L WITH CEDILLA*/ + 0x013D, /*U+013D*/ /**/ + 0x013D, /*U+013E*/ /*LATIN SMALL LETTER L WITH CARON*/ + 0x013F, /*U+013F*/ /**/ + 0x013F, /*U+0140*/ /*LATIN SMALL LETTER L WITH MIDDLE DOT*/ + 0x0141, /*U+0141*/ /**/ + 0x0141, /*U+0142*/ /*LATIN SMALL LETTER L WITH STROKE*/ + 0x0143, /*U+0143*/ /**/ + 0x0143, /*U+0144*/ /*LATIN SMALL LETTER N WITH ACUTE*/ + 0x0145, /*U+0145*/ /**/ + 0x0145, /*U+0146*/ /*LATIN SMALL LETTER N WITH CEDILLA*/ + 0x0147, /*U+0147*/ /**/ + 0x0147, /*U+0148*/ /*LATIN SMALL LETTER N WITH CARON*/ + 0x0149, /*U+0149*/ /**/ + 0x014A, /*U+014A*/ /**/ + 0x014A, /*U+014B*/ /*LATIN SMALL LETTER ENG*/ + 0x014C, /*U+014C*/ /**/ + 0x014C, /*U+014D*/ /*LATIN SMALL LETTER O WITH MACRON*/ + 0x014E, /*U+014E*/ /**/ + 0x014E, /*U+014F*/ /*LATIN SMALL LETTER O WITH BREVE*/ + 0x0150, /*U+0150*/ /**/ + 0x0150, /*U+0151*/ /*LATIN SMALL LETTER O WITH DOUBLE ACUTE*/ + 0x0152, /*U+0152*/ /**/ + 0x0152, /*U+0153*/ /*LATIN SMALL LIGATURE OE*/ + 0x0154, /*U+0154*/ /**/ + 0x0154, /*U+0155*/ /*LATIN SMALL LETTER R WITH ACUTE*/ + 0x0156, /*U+0156*/ /**/ + 0x0156, /*U+0157*/ /*LATIN SMALL LETTER R WITH CEDILLA*/ + 0x0158, /*U+0158*/ /**/ + 0x0158, /*U+0159*/ /*LATIN SMALL LETTER R WITH CARON*/ + 0x015A, /*U+015A*/ /**/ + 0x015A, /*U+015B*/ /*LATIN SMALL LETTER S WITH ACUTE*/ + 0x015C, /*U+015C*/ /**/ + 0x015C, /*U+015D*/ /*LATIN SMALL LETTER S WITH CIRCUMFLEX*/ + 0x015E, /*U+015E*/ /**/ + 0x015E, /*U+015F*/ /*LATIN SMALL LETTER S WITH CEDILLA*/ + 0x0160, /*U+0160*/ /**/ + 0x0160, /*U+0161*/ /*LATIN SMALL LETTER S WITH CARON*/ + 0x0162, /*U+0162*/ /**/ + 0x0162, /*U+0163*/ /*LATIN SMALL LETTER T WITH CEDILLA*/ + 0x0164, /*U+0164*/ /**/ + 0x0164, /*U+0165*/ /*LATIN SMALL LETTER T WITH CARON*/ + 0x0166, /*U+0166*/ /**/ + 0x0166, /*U+0167*/ /*LATIN SMALL LETTER T WITH STROKE*/ + 0x0168, /*U+0168*/ /**/ + 0x0168, /*U+0169*/ /*LATIN SMALL LETTER U WITH TILDE*/ + 0x016A, /*U+016A*/ /**/ + 0x016A, /*U+016B*/ /*LATIN SMALL LETTER U WITH MACRON*/ + 0x016C, /*U+016C*/ /**/ + 0x016C, /*U+016D*/ /*LATIN SMALL LETTER U WITH BREVE*/ + 0x016E, /*U+016E*/ /**/ + 0x016E, /*U+016F*/ /*LATIN SMALL LETTER U WITH RING ABOVE*/ + 0x0170, /*U+0170*/ /**/ + 0x0170, /*U+0171*/ /*LATIN SMALL LETTER U WITH DOUBLE ACUTE*/ + 0x0172, /*U+0172*/ /**/ + 0x0172, /*U+0173*/ /*LATIN SMALL LETTER U WITH OGONEK*/ + 0x0174, /*U+0174*/ /**/ + 0x0174, /*U+0175*/ /*LATIN SMALL LETTER W WITH CIRCUMFLEX*/ + 0x0176, /*U+0176*/ /**/ + 0x0176, /*U+0177*/ /*LATIN SMALL LETTER Y WITH CIRCUMFLEX*/ + 0x0178, /*U+0178*/ /**/ + 0x0179, /*U+0179*/ /**/ + 0x0179, /*U+017A*/ /*LATIN SMALL LETTER Z WITH ACUTE*/ + 0x017B, /*U+017B*/ /**/ + 0x017B, /*U+017C*/ /*LATIN SMALL LETTER Z WITH DOT ABOVE*/ + 0x017D, /*U+017D*/ /**/ + 0x017D, /*U+017E*/ /*LATIN SMALL LETTER Z WITH CARON*/ + 0x0053, /*U+017F*/ /*LATIN SMALL LETTER LONG S*/ + 0x0243, /*U+0180*/ /*LATIN SMALL LETTER B WITH STROKE*/ + 0x0181, /*U+0181*/ /**/ + 0x0182, /*U+0182*/ /**/ + 0x0182, /*U+0183*/ /*LATIN SMALL LETTER B WITH TOPBAR*/ + 0x0184, /*U+0184*/ /**/ + 0x0184, /*U+0185*/ /*LATIN SMALL LETTER TONE SIX*/ + 0x0186, /*U+0186*/ /**/ + 0x0187, /*U+0187*/ /**/ + 0x0187, /*U+0188*/ /*LATIN SMALL LETTER C WITH HOOK*/ + 0x0189, /*U+0189*/ /**/ + 0x018A, /*U+018A*/ /**/ + 0x018B, /*U+018B*/ /**/ + 0x018B, /*U+018C*/ /*LATIN SMALL LETTER D WITH TOPBAR*/ + 0x018D, /*U+018D*/ /**/ + 0x018E, /*U+018E*/ /**/ + 0x018F, /*U+018F*/ /**/ + 0x0190, /*U+0190*/ /**/ + 0x0191, /*U+0191*/ /**/ + 0x0191, /*U+0192*/ /*LATIN SMALL LETTER F WITH HOOK*/ + 0x0193, /*U+0193*/ /**/ + 0x0194, /*U+0194*/ /**/ + 0x01F6, /*U+0195*/ /*LATIN SMALL LETTER HV*/ + 0x0196, /*U+0196*/ /**/ + 0x0197, /*U+0197*/ /**/ + 0x0198, /*U+0198*/ /**/ + 0x0198, /*U+0199*/ /*LATIN SMALL LETTER K WITH HOOK*/ + 0x023D, /*U+019A*/ /*LATIN SMALL LETTER L WITH BAR*/ + 0x019B, /*U+019B*/ /**/ + 0x019C, /*U+019C*/ /**/ + 0x019D, /*U+019D*/ /**/ + 0x0220, /*U+019E*/ /*LATIN SMALL LETTER N WITH LONG RIGHT LEG*/ + 0x019F, /*U+019F*/ /**/ + 0x01A0, /*U+01A0*/ /**/ + 0x01A0, /*U+01A1*/ /*LATIN SMALL LETTER O WITH HORN*/ + 0x01A2, /*U+01A2*/ /**/ + 0x01A2, /*U+01A3*/ /*LATIN SMALL LETTER OI*/ + 0x01A4, /*U+01A4*/ /**/ + 0x01A4, /*U+01A5*/ /*LATIN SMALL LETTER P WITH HOOK*/ + 0x01A6, /*U+01A6*/ /**/ + 0x01A7, /*U+01A7*/ /**/ + 0x01A7, /*U+01A8*/ /*LATIN SMALL LETTER TONE TWO*/ + 0x01A9, /*U+01A9*/ /**/ + 0x01AA, /*U+01AA*/ /**/ + 0x01AB, /*U+01AB*/ /**/ + 0x01AC, /*U+01AC*/ /**/ + 0x01AC, /*U+01AD*/ /*LATIN SMALL LETTER T WITH HOOK*/ + 0x01AE, /*U+01AE*/ /**/ + 0x01AF, /*U+01AF*/ /**/ + 0x01AF, /*U+01B0*/ /*LATIN SMALL LETTER U WITH HORN*/ + 0x01B1, /*U+01B1*/ /**/ + 0x01B2, /*U+01B2*/ /**/ + 0x01B3, /*U+01B3*/ /**/ + 0x01B3, /*U+01B4*/ /*LATIN SMALL LETTER Y WITH HOOK*/ + 0x01B5, /*U+01B5*/ /**/ + 0x01B5, /*U+01B6*/ /*LATIN SMALL LETTER Z WITH STROKE*/ + 0x01B7, /*U+01B7*/ /**/ + 0x01B8, /*U+01B8*/ /**/ + 0x01B8, /*U+01B9*/ /*LATIN SMALL LETTER EZH REVERSED*/ + 0x01BA, /*U+01BA*/ /**/ + 0x01BB, /*U+01BB*/ /**/ + 0x01BC, /*U+01BC*/ /**/ + 0x01BC, /*U+01BD*/ /*LATIN SMALL LETTER TONE FIVE*/ + 0x01BE, /*U+01BE*/ /**/ + 0x01F7, /*U+01BF*/ /*LATIN LETTER WYNN*/ + 0x01C0, /*U+01C0*/ /**/ + 0x01C1, /*U+01C1*/ /**/ + 0x01C2, /*U+01C2*/ /**/ + 0x01C3, /*U+01C3*/ /**/ + 0x01C4, /*U+01C4*/ /**/ + 0x01C4, /*U+01C5*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON*/ + 0x01C4, /*U+01C6*/ /*LATIN SMALL LETTER DZ WITH CARON*/ + 0x01C7, /*U+01C7*/ /**/ + 0x01C7, /*U+01C8*/ /*LATIN CAPITAL LETTER L WITH SMALL LETTER J*/ + 0x01C7, /*U+01C9*/ /*LATIN SMALL LETTER LJ*/ + 0x01CA, /*U+01CA*/ /**/ + 0x01CA, /*U+01CB*/ /*LATIN CAPITAL LETTER N WITH SMALL LETTER J*/ + 0x01CA, /*U+01CC*/ /*LATIN SMALL LETTER NJ*/ + 0x01CD, /*U+01CD*/ /**/ + 0x01CD, /*U+01CE*/ /*LATIN SMALL LETTER A WITH CARON*/ + 0x01CF, /*U+01CF*/ /**/ + 0x01CF, /*U+01D0*/ /*LATIN SMALL LETTER I WITH CARON*/ + 0x01D1, /*U+01D1*/ /**/ + 0x01D1, /*U+01D2*/ /*LATIN SMALL LETTER O WITH CARON*/ + 0x01D3, /*U+01D3*/ /**/ + 0x01D3, /*U+01D4*/ /*LATIN SMALL LETTER U WITH CARON*/ + 0x01D5, /*U+01D5*/ /**/ + 0x01D5, /*U+01D6*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND MACRON*/ + 0x01D7, /*U+01D7*/ /**/ + 0x01D7, /*U+01D8*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE*/ + 0x01D9, /*U+01D9*/ /**/ + 0x01D9, /*U+01DA*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND CARON*/ + 0x01DB, /*U+01DB*/ /**/ + 0x01DB, /*U+01DC*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE*/ + 0x018E, /*U+01DD*/ /*LATIN SMALL LETTER TURNED E*/ + 0x01DE, /*U+01DE*/ /**/ + 0x01DE, /*U+01DF*/ /*LATIN SMALL LETTER A WITH DIAERESIS AND MACRON*/ + 0x01E0, /*U+01E0*/ /**/ + 0x01E0, /*U+01E1*/ /*LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON*/ + 0x01E2, /*U+01E2*/ /**/ + 0x01E2, /*U+01E3*/ /*LATIN SMALL LETTER AE WITH MACRON*/ + 0x01E4, /*U+01E4*/ /**/ + 0x01E4, /*U+01E5*/ /*LATIN SMALL LETTER G WITH STROKE*/ + 0x01E6, /*U+01E6*/ /**/ + 0x01E6, /*U+01E7*/ /*LATIN SMALL LETTER G WITH CARON*/ + 0x01E8, /*U+01E8*/ /**/ + 0x01E8, /*U+01E9*/ /*LATIN SMALL LETTER K WITH CARON*/ + 0x01EA, /*U+01EA*/ /**/ + 0x01EA, /*U+01EB*/ /*LATIN SMALL LETTER O WITH OGONEK*/ + 0x01EC, /*U+01EC*/ /**/ + 0x01EC, /*U+01ED*/ /*LATIN SMALL LETTER O WITH OGONEK AND MACRON*/ + 0x01EE, /*U+01EE*/ /**/ + 0x01EE, /*U+01EF*/ /*LATIN SMALL LETTER EZH WITH CARON*/ + 0x01F0, /*U+01F0*/ /**/ + 0x01F1, /*U+01F1*/ /**/ + 0x01F1, /*U+01F2*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z*/ + 0x01F1, /*U+01F3*/ /*LATIN SMALL LETTER DZ*/ + 0x01F4, /*U+01F4*/ /**/ + 0x01F4, /*U+01F5*/ /*LATIN SMALL LETTER G WITH ACUTE*/ + 0x01F6, /*U+01F6*/ /**/ + 0x01F7, /*U+01F7*/ /**/ + 0x01F8, /*U+01F8*/ /**/ + 0x01F8, /*U+01F9*/ /*LATIN SMALL LETTER N WITH GRAVE*/ + 0x01FA, /*U+01FA*/ /**/ + 0x01FA, /*U+01FB*/ /*LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE*/ + 0x01FC, /*U+01FC*/ /**/ + 0x01FC, /*U+01FD*/ /*LATIN SMALL LETTER AE WITH ACUTE*/ + 0x01FE, /*U+01FE*/ /**/ + 0x01FE, /*U+01FF*/ /*LATIN SMALL LETTER O WITH STROKE AND ACUTE*/ + 0x0200, /*U+0200*/ /**/ + 0x0200, /*U+0201*/ /*LATIN SMALL LETTER A WITH DOUBLE GRAVE*/ + 0x0202, /*U+0202*/ /**/ + 0x0202, /*U+0203*/ /*LATIN SMALL LETTER A WITH INVERTED BREVE*/ + 0x0204, /*U+0204*/ /**/ + 0x0204, /*U+0205*/ /*LATIN SMALL LETTER E WITH DOUBLE GRAVE*/ + 0x0206, /*U+0206*/ /**/ + 0x0206, /*U+0207*/ /*LATIN SMALL LETTER E WITH INVERTED BREVE*/ + 0x0208, /*U+0208*/ /**/ + 0x0208, /*U+0209*/ /*LATIN SMALL LETTER I WITH DOUBLE GRAVE*/ + 0x020A, /*U+020A*/ /**/ + 0x020A, /*U+020B*/ /*LATIN SMALL LETTER I WITH INVERTED BREVE*/ + 0x020C, /*U+020C*/ /**/ + 0x020C, /*U+020D*/ /*LATIN SMALL LETTER O WITH DOUBLE GRAVE*/ + 0x020E, /*U+020E*/ /**/ + 0x020E, /*U+020F*/ /*LATIN SMALL LETTER O WITH INVERTED BREVE*/ + 0x0210, /*U+0210*/ /**/ + 0x0210, /*U+0211*/ /*LATIN SMALL LETTER R WITH DOUBLE GRAVE*/ + 0x0212, /*U+0212*/ /**/ + 0x0212, /*U+0213*/ /*LATIN SMALL LETTER R WITH INVERTED BREVE*/ + 0x0214, /*U+0214*/ /**/ + 0x0214, /*U+0215*/ /*LATIN SMALL LETTER U WITH DOUBLE GRAVE*/ + 0x0216, /*U+0216*/ /**/ + 0x0216, /*U+0217*/ /*LATIN SMALL LETTER U WITH INVERTED BREVE*/ + 0x0218, /*U+0218*/ /**/ + 0x0218, /*U+0219*/ /*LATIN SMALL LETTER S WITH COMMA BELOW*/ + 0x021A, /*U+021A*/ /**/ + 0x021A, /*U+021B*/ /*LATIN SMALL LETTER T WITH COMMA BELOW*/ + 0x021C, /*U+021C*/ /**/ + 0x021C, /*U+021D*/ /*LATIN SMALL LETTER YOGH*/ + 0x021E, /*U+021E*/ /**/ + 0x021E, /*U+021F*/ /*LATIN SMALL LETTER H WITH CARON*/ + 0x0220, /*U+0220*/ /**/ + 0x0221, /*U+0221*/ /**/ + 0x0222, /*U+0222*/ /**/ + 0x0222, /*U+0223*/ /*LATIN SMALL LETTER OU*/ + 0x0224, /*U+0224*/ /**/ + 0x0224, /*U+0225*/ /*LATIN SMALL LETTER Z WITH HOOK*/ + 0x0226, /*U+0226*/ /**/ + 0x0226, /*U+0227*/ /*LATIN SMALL LETTER A WITH DOT ABOVE*/ + 0x0228, /*U+0228*/ /**/ + 0x0228, /*U+0229*/ /*LATIN SMALL LETTER E WITH CEDILLA*/ + 0x022A, /*U+022A*/ /**/ + 0x022A, /*U+022B*/ /*LATIN SMALL LETTER O WITH DIAERESIS AND MACRON*/ + 0x022C, /*U+022C*/ /**/ + 0x022C, /*U+022D*/ /*LATIN SMALL LETTER O WITH TILDE AND MACRON*/ + 0x022E, /*U+022E*/ /**/ + 0x022E, /*U+022F*/ /*LATIN SMALL LETTER O WITH DOT ABOVE*/ + 0x0230, /*U+0230*/ /**/ + 0x0230, /*U+0231*/ /*LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON*/ + 0x0232, /*U+0232*/ /**/ + 0x0232, /*U+0233*/ /*LATIN SMALL LETTER Y WITH MACRON*/ + 0x0234, /*U+0234*/ /**/ + 0x0235, /*U+0235*/ /**/ + 0x0236, /*U+0236*/ /**/ + 0x0237, /*U+0237*/ /**/ + 0x0238, /*U+0238*/ /**/ + 0x0239, /*U+0239*/ /**/ + 0x023A, /*U+023A*/ /**/ + 0x023B, /*U+023B*/ /**/ + 0x023B, /*U+023C*/ /*LATIN SMALL LETTER C WITH STROKE*/ + 0x023D, /*U+023D*/ /**/ + 0x023E, /*U+023E*/ /**/ + 0x2C7E, /*U+023F*/ /*LATIN SMALL LETTER S WITH SWASH TAIL*/ + 0x2C7F, /*U+0240*/ /*LATIN SMALL LETTER Z WITH SWASH TAIL*/ + 0x0241, /*U+0241*/ /**/ + 0x0241, /*U+0242*/ /*LATIN SMALL LETTER GLOTTAL STOP*/ + 0x0243, /*U+0243*/ /**/ + 0x0244, /*U+0244*/ /**/ + 0x0245, /*U+0245*/ /**/ + 0x0246, /*U+0246*/ /**/ + 0x0246, /*U+0247*/ /*LATIN SMALL LETTER E WITH STROKE*/ + 0x0248, /*U+0248*/ /**/ + 0x0248, /*U+0249*/ /*LATIN SMALL LETTER J WITH STROKE*/ + 0x024A, /*U+024A*/ /**/ + 0x024A, /*U+024B*/ /*LATIN SMALL LETTER Q WITH HOOK TAIL*/ + 0x024C, /*U+024C*/ /**/ + 0x024C, /*U+024D*/ /*LATIN SMALL LETTER R WITH STROKE*/ + 0x024E, /*U+024E*/ /**/ + 0x024E, /*U+024F*/ /*LATIN SMALL LETTER Y WITH STROKE*/ + 0x2C6F, /*U+0250*/ /*LATIN SMALL LETTER TURNED A*/ + 0x2C6D, /*U+0251*/ /*LATIN SMALL LETTER ALPHA*/ + 0x2C70, /*U+0252*/ /*LATIN SMALL LETTER TURNED ALPHA*/ + 0x0181, /*U+0253*/ /*LATIN SMALL LETTER B WITH HOOK*/ + 0x0186, /*U+0254*/ /*LATIN SMALL LETTER OPEN O*/ + 0x0255, /*U+0255*/ /**/ + 0x0189, /*U+0256*/ /*LATIN SMALL LETTER D WITH TAIL*/ + 0x018A, /*U+0257*/ /*LATIN SMALL LETTER D WITH HOOK*/ + 0x0258, /*U+0258*/ /**/ + 0x018F, /*U+0259*/ /*LATIN SMALL LETTER SCHWA*/ + 0x025A, /*U+025A*/ /**/ + 0x0190, /*U+025B*/ /*LATIN SMALL LETTER OPEN E*/ + 0xA7AB, /*U+025C*/ /*LATIN SMALL LETTER REVERSED OPEN E*/ + 0x025D, /*U+025D*/ /**/ + 0x025E, /*U+025E*/ /**/ + 0x025F, /*U+025F*/ /**/ + 0x0193, /*U+0260*/ /*LATIN SMALL LETTER G WITH HOOK*/ + 0xA7AC, /*U+0261*/ /*LATIN SMALL LETTER SCRIPT G*/ + 0x0262, /*U+0262*/ /**/ + 0x0194, /*U+0263*/ /*LATIN SMALL LETTER GAMMA*/ + 0x0264, /*U+0264*/ /**/ + 0xA78D, /*U+0265*/ /*LATIN SMALL LETTER TURNED H*/ + 0xA7AA, /*U+0266*/ /*LATIN SMALL LETTER H WITH HOOK*/ + 0x0267, /*U+0267*/ /**/ + 0x0197, /*U+0268*/ /*LATIN SMALL LETTER I WITH STROKE*/ + 0x0196, /*U+0269*/ /*LATIN SMALL LETTER IOTA*/ + 0x026A, /*U+026A*/ /**/ + 0x2C62, /*U+026B*/ /*LATIN SMALL LETTER L WITH MIDDLE TILDE*/ + 0xA7AD, /*U+026C*/ /*LATIN SMALL LETTER L WITH BELT*/ + 0x026D, /*U+026D*/ /**/ + 0x026E, /*U+026E*/ /**/ + 0x019C, /*U+026F*/ /*LATIN SMALL LETTER TURNED M*/ + 0x0270, /*U+0270*/ /**/ + 0x2C6E, /*U+0271*/ /*LATIN SMALL LETTER M WITH HOOK*/ + 0x019D, /*U+0272*/ /*LATIN SMALL LETTER N WITH LEFT HOOK*/ + 0x0273, /*U+0273*/ /**/ + 0x0274, /*U+0274*/ /**/ + 0x019F, /*U+0275*/ /*LATIN SMALL LETTER BARRED O*/ + 0x0276, /*U+0276*/ /**/ + 0x0277, /*U+0277*/ /**/ + 0x0278, /*U+0278*/ /**/ + 0x0279, /*U+0279*/ /**/ + 0x027A, /*U+027A*/ /**/ + 0x027B, /*U+027B*/ /**/ + 0x027C, /*U+027C*/ /**/ + 0x2C64, /*U+027D*/ /*LATIN SMALL LETTER R WITH TAIL*/ + 0x027E, /*U+027E*/ /**/ + 0x027F, /*U+027F*/ /**/ + 0x01A6, /*U+0280*/ /*LATIN LETTER SMALL CAPITAL R*/ + 0x0281, /*U+0281*/ /**/ + 0x0282, /*U+0282*/ /**/ + 0x01A9, /*U+0283*/ /*LATIN SMALL LETTER ESH*/ + 0x0284, /*U+0284*/ /**/ + 0x0285, /*U+0285*/ /**/ + 0x0286, /*U+0286*/ /**/ + 0xA7B1, /*U+0287*/ /*LATIN SMALL LETTER TURNED T*/ + 0x01AE, /*U+0288*/ /*LATIN SMALL LETTER T WITH RETROFLEX HOOK*/ + 0x0244, /*U+0289*/ /*LATIN SMALL LETTER U BAR*/ + 0x01B1, /*U+028A*/ /*LATIN SMALL LETTER UPSILON*/ + 0x01B2, /*U+028B*/ /*LATIN SMALL LETTER V WITH HOOK*/ + 0x0245, /*U+028C*/ /*LATIN SMALL LETTER TURNED V*/ + 0x028D, /*U+028D*/ /**/ + 0x028E, /*U+028E*/ /**/ + 0x028F, /*U+028F*/ /**/ + 0x0290, /*U+0290*/ /**/ + 0x0291, /*U+0291*/ /**/ + 0x01B7, /*U+0292*/ /*LATIN SMALL LETTER EZH*/ + 0x0293, /*U+0293*/ /**/ + 0x0294, /*U+0294*/ /**/ + 0x0295, /*U+0295*/ /**/ + 0x0296, /*U+0296*/ /**/ + 0x0297, /*U+0297*/ /**/ + 0x0298, /*U+0298*/ /**/ + 0x0299, /*U+0299*/ /**/ + 0x029A, /*U+029A*/ /**/ + 0x029B, /*U+029B*/ /**/ + 0x029C, /*U+029C*/ /**/ + 0x029D, /*U+029D*/ /**/ + 0xA7B0, /*U+029E*/ /*LATIN SMALL LETTER TURNED K*/ + 0x029F, /*U+029F*/ /**/ + 0x02A0, /*U+02A0*/ /**/ + 0x02A1, /*U+02A1*/ /**/ + 0x02A2, /*U+02A2*/ /**/ + 0x02A3, /*U+02A3*/ /**/ + 0x02A4, /*U+02A4*/ /**/ + 0x02A5, /*U+02A5*/ /**/ + 0x02A6, /*U+02A6*/ /**/ + 0x02A7, /*U+02A7*/ /**/ + 0x02A8, /*U+02A8*/ /**/ + 0x02A9, /*U+02A9*/ /**/ + 0x02AA, /*U+02AA*/ /**/ + 0x02AB, /*U+02AB*/ /**/ + 0x02AC, /*U+02AC*/ /**/ + 0x02AD, /*U+02AD*/ /**/ + 0x02AE, /*U+02AE*/ /**/ + 0x02AF, /*U+02AF*/ /**/ + 0x02B0, /*U+02B0*/ /**/ + 0x02B1, /*U+02B1*/ /**/ + 0x02B2, /*U+02B2*/ /**/ + 0x02B3, /*U+02B3*/ /**/ + 0x02B4, /*U+02B4*/ /**/ + 0x02B5, /*U+02B5*/ /**/ + 0x02B6, /*U+02B6*/ /**/ + 0x02B7, /*U+02B7*/ /**/ + 0x02B8, /*U+02B8*/ /**/ + 0x02B9, /*U+02B9*/ /**/ + 0x02BA, /*U+02BA*/ /**/ + 0x02BB, /*U+02BB*/ /**/ + 0x02BC, /*U+02BC*/ /**/ + 0x02BD, /*U+02BD*/ /**/ + 0x02BE, /*U+02BE*/ /**/ + 0x02BF, /*U+02BF*/ /**/ +}; + +static const uint16_t upper_table_2[640] = { + 0x0340, /*U+0340*/ /**/ + 0x0341, /*U+0341*/ /**/ + 0x0342, /*U+0342*/ /**/ + 0x0343, /*U+0343*/ /**/ + 0x0344, /*U+0344*/ /**/ + 0x0399, /*U+0345*/ /*COMBINING GREEK YPOGEGRAMMENI*/ + 0x0346, /*U+0346*/ /**/ + 0x0347, /*U+0347*/ /**/ + 0x0348, /*U+0348*/ /**/ + 0x0349, /*U+0349*/ /**/ + 0x034A, /*U+034A*/ /**/ + 0x034B, /*U+034B*/ /**/ + 0x034C, /*U+034C*/ /**/ + 0x034D, /*U+034D*/ /**/ + 0x034E, /*U+034E*/ /**/ + 0x034F, /*U+034F*/ /**/ + 0x0350, /*U+0350*/ /**/ + 0x0351, /*U+0351*/ /**/ + 0x0352, /*U+0352*/ /**/ + 0x0353, /*U+0353*/ /**/ + 0x0354, /*U+0354*/ /**/ + 0x0355, /*U+0355*/ /**/ + 0x0356, /*U+0356*/ /**/ + 0x0357, /*U+0357*/ /**/ + 0x0358, /*U+0358*/ /**/ + 0x0359, /*U+0359*/ /**/ + 0x035A, /*U+035A*/ /**/ + 0x035B, /*U+035B*/ /**/ + 0x035C, /*U+035C*/ /**/ + 0x035D, /*U+035D*/ /**/ + 0x035E, /*U+035E*/ /**/ + 0x035F, /*U+035F*/ /**/ + 0x0360, /*U+0360*/ /**/ + 0x0361, /*U+0361*/ /**/ + 0x0362, /*U+0362*/ /**/ + 0x0363, /*U+0363*/ /**/ + 0x0364, /*U+0364*/ /**/ + 0x0365, /*U+0365*/ /**/ + 0x0366, /*U+0366*/ /**/ + 0x0367, /*U+0367*/ /**/ + 0x0368, /*U+0368*/ /**/ + 0x0369, /*U+0369*/ /**/ + 0x036A, /*U+036A*/ /**/ + 0x036B, /*U+036B*/ /**/ + 0x036C, /*U+036C*/ /**/ + 0x036D, /*U+036D*/ /**/ + 0x036E, /*U+036E*/ /**/ + 0x036F, /*U+036F*/ /**/ + 0x0370, /*U+0370*/ /**/ + 0x0370, /*U+0371*/ /*GREEK SMALL LETTER HETA*/ + 0x0372, /*U+0372*/ /**/ + 0x0372, /*U+0373*/ /*GREEK SMALL LETTER ARCHAIC SAMPI*/ + 0x0374, /*U+0374*/ /**/ + 0x0375, /*U+0375*/ /**/ + 0x0376, /*U+0376*/ /**/ + 0x0376, /*U+0377*/ /*GREEK SMALL LETTER PAMPHYLIAN DIGAMMA*/ + 0x0378, /*U+0378*/ /**/ + 0x0379, /*U+0379*/ /**/ + 0x037A, /*U+037A*/ /**/ + 0x03FD, /*U+037B*/ /*GREEK SMALL REVERSED LUNATE SIGMA SYMBOL*/ + 0x03FE, /*U+037C*/ /*GREEK SMALL DOTTED LUNATE SIGMA SYMBOL*/ + 0x03FF, /*U+037D*/ /*GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL*/ + 0x037E, /*U+037E*/ /**/ + 0x037F, /*U+037F*/ /**/ + 0x0380, /*U+0380*/ /**/ + 0x0381, /*U+0381*/ /**/ + 0x0382, /*U+0382*/ /**/ + 0x0383, /*U+0383*/ /**/ + 0x0384, /*U+0384*/ /**/ + 0x0385, /*U+0385*/ /**/ + 0x0386, /*U+0386*/ /**/ + 0x0387, /*U+0387*/ /**/ + 0x0388, /*U+0388*/ /**/ + 0x0389, /*U+0389*/ /**/ + 0x038A, /*U+038A*/ /**/ + 0x038B, /*U+038B*/ /**/ + 0x038C, /*U+038C*/ /**/ + 0x038D, /*U+038D*/ /**/ + 0x038E, /*U+038E*/ /**/ + 0x038F, /*U+038F*/ /**/ + 0x0390, /*U+0390*/ /**/ + 0x0391, /*U+0391*/ /**/ + 0x0392, /*U+0392*/ /**/ + 0x0393, /*U+0393*/ /**/ + 0x0394, /*U+0394*/ /**/ + 0x0395, /*U+0395*/ /**/ + 0x0396, /*U+0396*/ /**/ + 0x0397, /*U+0397*/ /**/ + 0x0398, /*U+0398*/ /**/ + 0x0399, /*U+0399*/ /**/ + 0x039A, /*U+039A*/ /**/ + 0x039B, /*U+039B*/ /**/ + 0x039C, /*U+039C*/ /**/ + 0x039D, /*U+039D*/ /**/ + 0x039E, /*U+039E*/ /**/ + 0x039F, /*U+039F*/ /**/ + 0x03A0, /*U+03A0*/ /**/ + 0x03A1, /*U+03A1*/ /**/ + 0x03A2, /*U+03A2*/ /**/ + 0x03A3, /*U+03A3*/ /**/ + 0x03A4, /*U+03A4*/ /**/ + 0x03A5, /*U+03A5*/ /**/ + 0x03A6, /*U+03A6*/ /**/ + 0x03A7, /*U+03A7*/ /**/ + 0x03A8, /*U+03A8*/ /**/ + 0x03A9, /*U+03A9*/ /**/ + 0x03AA, /*U+03AA*/ /**/ + 0x03AB, /*U+03AB*/ /**/ + 0x0386, /*U+03AC*/ /*GREEK SMALL LETTER ALPHA WITH TONOS*/ + 0x0388, /*U+03AD*/ /*GREEK SMALL LETTER EPSILON WITH TONOS*/ + 0x0389, /*U+03AE*/ /*GREEK SMALL LETTER ETA WITH TONOS*/ + 0x038A, /*U+03AF*/ /*GREEK SMALL LETTER IOTA WITH TONOS*/ + 0x03B0, /*U+03B0*/ /**/ + 0x0391, /*U+03B1*/ /*GREEK SMALL LETTER ALPHA*/ + 0x0392, /*U+03B2*/ /*GREEK SMALL LETTER BETA*/ + 0x0393, /*U+03B3*/ /*GREEK SMALL LETTER GAMMA*/ + 0x0394, /*U+03B4*/ /*GREEK SMALL LETTER DELTA*/ + 0x0395, /*U+03B5*/ /*GREEK SMALL LETTER EPSILON*/ + 0x0396, /*U+03B6*/ /*GREEK SMALL LETTER ZETA*/ + 0x0397, /*U+03B7*/ /*GREEK SMALL LETTER ETA*/ + 0x0398, /*U+03B8*/ /*GREEK SMALL LETTER THETA*/ + 0x0399, /*U+03B9*/ /*GREEK SMALL LETTER IOTA*/ + 0x039A, /*U+03BA*/ /*GREEK SMALL LETTER KAPPA*/ + 0x039B, /*U+03BB*/ /*GREEK SMALL LETTER LAMDA*/ + 0x039C, /*U+03BC*/ /*GREEK SMALL LETTER MU*/ + 0x039D, /*U+03BD*/ /*GREEK SMALL LETTER NU*/ + 0x039E, /*U+03BE*/ /*GREEK SMALL LETTER XI*/ + 0x039F, /*U+03BF*/ /*GREEK SMALL LETTER OMICRON*/ + 0x03A0, /*U+03C0*/ /*GREEK SMALL LETTER PI*/ + 0x03A1, /*U+03C1*/ /*GREEK SMALL LETTER RHO*/ + 0x03A3, /*U+03C2*/ /*GREEK SMALL LETTER FINAL SIGMA*/ + 0x03A3, /*U+03C3*/ /*GREEK SMALL LETTER SIGMA*/ + 0x03A4, /*U+03C4*/ /*GREEK SMALL LETTER TAU*/ + 0x03A5, /*U+03C5*/ /*GREEK SMALL LETTER UPSILON*/ + 0x03A6, /*U+03C6*/ /*GREEK SMALL LETTER PHI*/ + 0x03A7, /*U+03C7*/ /*GREEK SMALL LETTER CHI*/ + 0x03A8, /*U+03C8*/ /*GREEK SMALL LETTER PSI*/ + 0x03A9, /*U+03C9*/ /*GREEK SMALL LETTER OMEGA*/ + 0x03AA, /*U+03CA*/ /*GREEK SMALL LETTER IOTA WITH DIALYTIKA*/ + 0x03AB, /*U+03CB*/ /*GREEK SMALL LETTER UPSILON WITH DIALYTIKA*/ + 0x038C, /*U+03CC*/ /*GREEK SMALL LETTER OMICRON WITH TONOS*/ + 0x038E, /*U+03CD*/ /*GREEK SMALL LETTER UPSILON WITH TONOS*/ + 0x038F, /*U+03CE*/ /*GREEK SMALL LETTER OMEGA WITH TONOS*/ + 0x03CF, /*U+03CF*/ /**/ + 0x0392, /*U+03D0*/ /*GREEK BETA SYMBOL*/ + 0x0398, /*U+03D1*/ /*GREEK THETA SYMBOL*/ + 0x03D2, /*U+03D2*/ /**/ + 0x03D3, /*U+03D3*/ /**/ + 0x03D4, /*U+03D4*/ /**/ + 0x03A6, /*U+03D5*/ /*GREEK PHI SYMBOL*/ + 0x03A0, /*U+03D6*/ /*GREEK PI SYMBOL*/ + 0x03CF, /*U+03D7*/ /*GREEK KAI SYMBOL*/ + 0x03D8, /*U+03D8*/ /**/ + 0x03D8, /*U+03D9*/ /*GREEK SMALL LETTER ARCHAIC KOPPA*/ + 0x03DA, /*U+03DA*/ /**/ + 0x03DA, /*U+03DB*/ /*GREEK SMALL LETTER STIGMA*/ + 0x03DC, /*U+03DC*/ /**/ + 0x03DC, /*U+03DD*/ /*GREEK SMALL LETTER DIGAMMA*/ + 0x03DE, /*U+03DE*/ /**/ + 0x03DE, /*U+03DF*/ /*GREEK SMALL LETTER KOPPA*/ + 0x03E0, /*U+03E0*/ /**/ + 0x03E0, /*U+03E1*/ /*GREEK SMALL LETTER SAMPI*/ + 0x03E2, /*U+03E2*/ /**/ + 0x03E2, /*U+03E3*/ /*COPTIC SMALL LETTER SHEI*/ + 0x03E4, /*U+03E4*/ /**/ + 0x03E4, /*U+03E5*/ /*COPTIC SMALL LETTER FEI*/ + 0x03E6, /*U+03E6*/ /**/ + 0x03E6, /*U+03E7*/ /*COPTIC SMALL LETTER KHEI*/ + 0x03E8, /*U+03E8*/ /**/ + 0x03E8, /*U+03E9*/ /*COPTIC SMALL LETTER HORI*/ + 0x03EA, /*U+03EA*/ /**/ + 0x03EA, /*U+03EB*/ /*COPTIC SMALL LETTER GANGIA*/ + 0x03EC, /*U+03EC*/ /**/ + 0x03EC, /*U+03ED*/ /*COPTIC SMALL LETTER SHIMA*/ + 0x03EE, /*U+03EE*/ /**/ + 0x03EE, /*U+03EF*/ /*COPTIC SMALL LETTER DEI*/ + 0x039A, /*U+03F0*/ /*GREEK KAPPA SYMBOL*/ + 0x03A1, /*U+03F1*/ /*GREEK RHO SYMBOL*/ + 0x03F9, /*U+03F2*/ /*GREEK LUNATE SIGMA SYMBOL*/ + 0x037F, /*U+03F3*/ /*GREEK LETTER YOT*/ + 0x03F4, /*U+03F4*/ /**/ + 0x0395, /*U+03F5*/ /*GREEK LUNATE EPSILON SYMBOL*/ + 0x03F6, /*U+03F6*/ /**/ + 0x03F7, /*U+03F7*/ /**/ + 0x03F7, /*U+03F8*/ /*GREEK SMALL LETTER SHO*/ + 0x03F9, /*U+03F9*/ /**/ + 0x03FA, /*U+03FA*/ /**/ + 0x03FA, /*U+03FB*/ /*GREEK SMALL LETTER SAN*/ + 0x03FC, /*U+03FC*/ /**/ + 0x03FD, /*U+03FD*/ /**/ + 0x03FE, /*U+03FE*/ /**/ + 0x03FF, /*U+03FF*/ /**/ + 0x0400, /*U+0400*/ /**/ + 0x0401, /*U+0401*/ /**/ + 0x0402, /*U+0402*/ /**/ + 0x0403, /*U+0403*/ /**/ + 0x0404, /*U+0404*/ /**/ + 0x0405, /*U+0405*/ /**/ + 0x0406, /*U+0406*/ /**/ + 0x0407, /*U+0407*/ /**/ + 0x0408, /*U+0408*/ /**/ + 0x0409, /*U+0409*/ /**/ + 0x040A, /*U+040A*/ /**/ + 0x040B, /*U+040B*/ /**/ + 0x040C, /*U+040C*/ /**/ + 0x040D, /*U+040D*/ /**/ + 0x040E, /*U+040E*/ /**/ + 0x040F, /*U+040F*/ /**/ + 0x0410, /*U+0410*/ /**/ + 0x0411, /*U+0411*/ /**/ + 0x0412, /*U+0412*/ /**/ + 0x0413, /*U+0413*/ /**/ + 0x0414, /*U+0414*/ /**/ + 0x0415, /*U+0415*/ /**/ + 0x0416, /*U+0416*/ /**/ + 0x0417, /*U+0417*/ /**/ + 0x0418, /*U+0418*/ /**/ + 0x0419, /*U+0419*/ /**/ + 0x041A, /*U+041A*/ /**/ + 0x041B, /*U+041B*/ /**/ + 0x041C, /*U+041C*/ /**/ + 0x041D, /*U+041D*/ /**/ + 0x041E, /*U+041E*/ /**/ + 0x041F, /*U+041F*/ /**/ + 0x0420, /*U+0420*/ /**/ + 0x0421, /*U+0421*/ /**/ + 0x0422, /*U+0422*/ /**/ + 0x0423, /*U+0423*/ /**/ + 0x0424, /*U+0424*/ /**/ + 0x0425, /*U+0425*/ /**/ + 0x0426, /*U+0426*/ /**/ + 0x0427, /*U+0427*/ /**/ + 0x0428, /*U+0428*/ /**/ + 0x0429, /*U+0429*/ /**/ + 0x042A, /*U+042A*/ /**/ + 0x042B, /*U+042B*/ /**/ + 0x042C, /*U+042C*/ /**/ + 0x042D, /*U+042D*/ /**/ + 0x042E, /*U+042E*/ /**/ + 0x042F, /*U+042F*/ /**/ + 0x0410, /*U+0430*/ /*CYRILLIC SMALL LETTER A*/ + 0x0411, /*U+0431*/ /*CYRILLIC SMALL LETTER BE*/ + 0x0412, /*U+0432*/ /*CYRILLIC SMALL LETTER VE*/ + 0x0413, /*U+0433*/ /*CYRILLIC SMALL LETTER GHE*/ + 0x0414, /*U+0434*/ /*CYRILLIC SMALL LETTER DE*/ + 0x0415, /*U+0435*/ /*CYRILLIC SMALL LETTER IE*/ + 0x0416, /*U+0436*/ /*CYRILLIC SMALL LETTER ZHE*/ + 0x0417, /*U+0437*/ /*CYRILLIC SMALL LETTER ZE*/ + 0x0418, /*U+0438*/ /*CYRILLIC SMALL LETTER I*/ + 0x0419, /*U+0439*/ /*CYRILLIC SMALL LETTER SHORT I*/ + 0x041A, /*U+043A*/ /*CYRILLIC SMALL LETTER KA*/ + 0x041B, /*U+043B*/ /*CYRILLIC SMALL LETTER EL*/ + 0x041C, /*U+043C*/ /*CYRILLIC SMALL LETTER EM*/ + 0x041D, /*U+043D*/ /*CYRILLIC SMALL LETTER EN*/ + 0x041E, /*U+043E*/ /*CYRILLIC SMALL LETTER O*/ + 0x041F, /*U+043F*/ /*CYRILLIC SMALL LETTER PE*/ + 0x0420, /*U+0440*/ /*CYRILLIC SMALL LETTER ER*/ + 0x0421, /*U+0441*/ /*CYRILLIC SMALL LETTER ES*/ + 0x0422, /*U+0442*/ /*CYRILLIC SMALL LETTER TE*/ + 0x0423, /*U+0443*/ /*CYRILLIC SMALL LETTER U*/ + 0x0424, /*U+0444*/ /*CYRILLIC SMALL LETTER EF*/ + 0x0425, /*U+0445*/ /*CYRILLIC SMALL LETTER HA*/ + 0x0426, /*U+0446*/ /*CYRILLIC SMALL LETTER TSE*/ + 0x0427, /*U+0447*/ /*CYRILLIC SMALL LETTER CHE*/ + 0x0428, /*U+0448*/ /*CYRILLIC SMALL LETTER SHA*/ + 0x0429, /*U+0449*/ /*CYRILLIC SMALL LETTER SHCHA*/ + 0x042A, /*U+044A*/ /*CYRILLIC SMALL LETTER HARD SIGN*/ + 0x042B, /*U+044B*/ /*CYRILLIC SMALL LETTER YERU*/ + 0x042C, /*U+044C*/ /*CYRILLIC SMALL LETTER SOFT SIGN*/ + 0x042D, /*U+044D*/ /*CYRILLIC SMALL LETTER E*/ + 0x042E, /*U+044E*/ /*CYRILLIC SMALL LETTER YU*/ + 0x042F, /*U+044F*/ /*CYRILLIC SMALL LETTER YA*/ + 0x0400, /*U+0450*/ /*CYRILLIC SMALL LETTER IE WITH GRAVE*/ + 0x0401, /*U+0451*/ /*CYRILLIC SMALL LETTER IO*/ + 0x0402, /*U+0452*/ /*CYRILLIC SMALL LETTER DJE*/ + 0x0403, /*U+0453*/ /*CYRILLIC SMALL LETTER GJE*/ + 0x0404, /*U+0454*/ /*CYRILLIC SMALL LETTER UKRAINIAN IE*/ + 0x0405, /*U+0455*/ /*CYRILLIC SMALL LETTER DZE*/ + 0x0406, /*U+0456*/ /*CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I*/ + 0x0407, /*U+0457*/ /*CYRILLIC SMALL LETTER YI*/ + 0x0408, /*U+0458*/ /*CYRILLIC SMALL LETTER JE*/ + 0x0409, /*U+0459*/ /*CYRILLIC SMALL LETTER LJE*/ + 0x040A, /*U+045A*/ /*CYRILLIC SMALL LETTER NJE*/ + 0x040B, /*U+045B*/ /*CYRILLIC SMALL LETTER TSHE*/ + 0x040C, /*U+045C*/ /*CYRILLIC SMALL LETTER KJE*/ + 0x040D, /*U+045D*/ /*CYRILLIC SMALL LETTER I WITH GRAVE*/ + 0x040E, /*U+045E*/ /*CYRILLIC SMALL LETTER SHORT U*/ + 0x040F, /*U+045F*/ /*CYRILLIC SMALL LETTER DZHE*/ + 0x0460, /*U+0460*/ /**/ + 0x0460, /*U+0461*/ /*CYRILLIC SMALL LETTER OMEGA*/ + 0x0462, /*U+0462*/ /**/ + 0x0462, /*U+0463*/ /*CYRILLIC SMALL LETTER YAT*/ + 0x0464, /*U+0464*/ /**/ + 0x0464, /*U+0465*/ /*CYRILLIC SMALL LETTER IOTIFIED E*/ + 0x0466, /*U+0466*/ /**/ + 0x0466, /*U+0467*/ /*CYRILLIC SMALL LETTER LITTLE YUS*/ + 0x0468, /*U+0468*/ /**/ + 0x0468, /*U+0469*/ /*CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS*/ + 0x046A, /*U+046A*/ /**/ + 0x046A, /*U+046B*/ /*CYRILLIC SMALL LETTER BIG YUS*/ + 0x046C, /*U+046C*/ /**/ + 0x046C, /*U+046D*/ /*CYRILLIC SMALL LETTER IOTIFIED BIG YUS*/ + 0x046E, /*U+046E*/ /**/ + 0x046E, /*U+046F*/ /*CYRILLIC SMALL LETTER KSI*/ + 0x0470, /*U+0470*/ /**/ + 0x0470, /*U+0471*/ /*CYRILLIC SMALL LETTER PSI*/ + 0x0472, /*U+0472*/ /**/ + 0x0472, /*U+0473*/ /*CYRILLIC SMALL LETTER FITA*/ + 0x0474, /*U+0474*/ /**/ + 0x0474, /*U+0475*/ /*CYRILLIC SMALL LETTER IZHITSA*/ + 0x0476, /*U+0476*/ /**/ + 0x0476, /*U+0477*/ /*CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT*/ + 0x0478, /*U+0478*/ /**/ + 0x0478, /*U+0479*/ /*CYRILLIC SMALL LETTER UK*/ + 0x047A, /*U+047A*/ /**/ + 0x047A, /*U+047B*/ /*CYRILLIC SMALL LETTER ROUND OMEGA*/ + 0x047C, /*U+047C*/ /**/ + 0x047C, /*U+047D*/ /*CYRILLIC SMALL LETTER OMEGA WITH TITLO*/ + 0x047E, /*U+047E*/ /**/ + 0x047E, /*U+047F*/ /*CYRILLIC SMALL LETTER OT*/ + 0x0480, /*U+0480*/ /**/ + 0x0480, /*U+0481*/ /*CYRILLIC SMALL LETTER KOPPA*/ + 0x0482, /*U+0482*/ /**/ + 0x0483, /*U+0483*/ /**/ + 0x0484, /*U+0484*/ /**/ + 0x0485, /*U+0485*/ /**/ + 0x0486, /*U+0486*/ /**/ + 0x0487, /*U+0487*/ /**/ + 0x0488, /*U+0488*/ /**/ + 0x0489, /*U+0489*/ /**/ + 0x048A, /*U+048A*/ /**/ + 0x048A, /*U+048B*/ /*CYRILLIC SMALL LETTER SHORT I WITH TAIL*/ + 0x048C, /*U+048C*/ /**/ + 0x048C, /*U+048D*/ /*CYRILLIC SMALL LETTER SEMISOFT SIGN*/ + 0x048E, /*U+048E*/ /**/ + 0x048E, /*U+048F*/ /*CYRILLIC SMALL LETTER ER WITH TICK*/ + 0x0490, /*U+0490*/ /**/ + 0x0490, /*U+0491*/ /*CYRILLIC SMALL LETTER GHE WITH UPTURN*/ + 0x0492, /*U+0492*/ /**/ + 0x0492, /*U+0493*/ /*CYRILLIC SMALL LETTER GHE WITH STROKE*/ + 0x0494, /*U+0494*/ /**/ + 0x0494, /*U+0495*/ /*CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK*/ + 0x0496, /*U+0496*/ /**/ + 0x0496, /*U+0497*/ /*CYRILLIC SMALL LETTER ZHE WITH DESCENDER*/ + 0x0498, /*U+0498*/ /**/ + 0x0498, /*U+0499*/ /*CYRILLIC SMALL LETTER ZE WITH DESCENDER*/ + 0x049A, /*U+049A*/ /**/ + 0x049A, /*U+049B*/ /*CYRILLIC SMALL LETTER KA WITH DESCENDER*/ + 0x049C, /*U+049C*/ /**/ + 0x049C, /*U+049D*/ /*CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE*/ + 0x049E, /*U+049E*/ /**/ + 0x049E, /*U+049F*/ /*CYRILLIC SMALL LETTER KA WITH STROKE*/ + 0x04A0, /*U+04A0*/ /**/ + 0x04A0, /*U+04A1*/ /*CYRILLIC SMALL LETTER BASHKIR KA*/ + 0x04A2, /*U+04A2*/ /**/ + 0x04A2, /*U+04A3*/ /*CYRILLIC SMALL LETTER EN WITH DESCENDER*/ + 0x04A4, /*U+04A4*/ /**/ + 0x04A4, /*U+04A5*/ /*CYRILLIC SMALL LIGATURE EN GHE*/ + 0x04A6, /*U+04A6*/ /**/ + 0x04A6, /*U+04A7*/ /*CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK*/ + 0x04A8, /*U+04A8*/ /**/ + 0x04A8, /*U+04A9*/ /*CYRILLIC SMALL LETTER ABKHASIAN HA*/ + 0x04AA, /*U+04AA*/ /**/ + 0x04AA, /*U+04AB*/ /*CYRILLIC SMALL LETTER ES WITH DESCENDER*/ + 0x04AC, /*U+04AC*/ /**/ + 0x04AC, /*U+04AD*/ /*CYRILLIC SMALL LETTER TE WITH DESCENDER*/ + 0x04AE, /*U+04AE*/ /**/ + 0x04AE, /*U+04AF*/ /*CYRILLIC SMALL LETTER STRAIGHT U*/ + 0x04B0, /*U+04B0*/ /**/ + 0x04B0, /*U+04B1*/ /*CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE*/ + 0x04B2, /*U+04B2*/ /**/ + 0x04B2, /*U+04B3*/ /*CYRILLIC SMALL LETTER HA WITH DESCENDER*/ + 0x04B4, /*U+04B4*/ /**/ + 0x04B4, /*U+04B5*/ /*CYRILLIC SMALL LIGATURE TE TSE*/ + 0x04B6, /*U+04B6*/ /**/ + 0x04B6, /*U+04B7*/ /*CYRILLIC SMALL LETTER CHE WITH DESCENDER*/ + 0x04B8, /*U+04B8*/ /**/ + 0x04B8, /*U+04B9*/ /*CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE*/ + 0x04BA, /*U+04BA*/ /**/ + 0x04BA, /*U+04BB*/ /*CYRILLIC SMALL LETTER SHHA*/ + 0x04BC, /*U+04BC*/ /**/ + 0x04BC, /*U+04BD*/ /*CYRILLIC SMALL LETTER ABKHASIAN CHE*/ + 0x04BE, /*U+04BE*/ /**/ + 0x04BE, /*U+04BF*/ /*CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER*/ + 0x04C0, /*U+04C0*/ /**/ + 0x04C1, /*U+04C1*/ /**/ + 0x04C1, /*U+04C2*/ /*CYRILLIC SMALL LETTER ZHE WITH BREVE*/ + 0x04C3, /*U+04C3*/ /**/ + 0x04C3, /*U+04C4*/ /*CYRILLIC SMALL LETTER KA WITH HOOK*/ + 0x04C5, /*U+04C5*/ /**/ + 0x04C5, /*U+04C6*/ /*CYRILLIC SMALL LETTER EL WITH TAIL*/ + 0x04C7, /*U+04C7*/ /**/ + 0x04C7, /*U+04C8*/ /*CYRILLIC SMALL LETTER EN WITH HOOK*/ + 0x04C9, /*U+04C9*/ /**/ + 0x04C9, /*U+04CA*/ /*CYRILLIC SMALL LETTER EN WITH TAIL*/ + 0x04CB, /*U+04CB*/ /**/ + 0x04CB, /*U+04CC*/ /*CYRILLIC SMALL LETTER KHAKASSIAN CHE*/ + 0x04CD, /*U+04CD*/ /**/ + 0x04CD, /*U+04CE*/ /*CYRILLIC SMALL LETTER EM WITH TAIL*/ + 0x04C0, /*U+04CF*/ /*CYRILLIC SMALL LETTER PALOCHKA*/ + 0x04D0, /*U+04D0*/ /**/ + 0x04D0, /*U+04D1*/ /*CYRILLIC SMALL LETTER A WITH BREVE*/ + 0x04D2, /*U+04D2*/ /**/ + 0x04D2, /*U+04D3*/ /*CYRILLIC SMALL LETTER A WITH DIAERESIS*/ + 0x04D4, /*U+04D4*/ /**/ + 0x04D4, /*U+04D5*/ /*CYRILLIC SMALL LIGATURE A IE*/ + 0x04D6, /*U+04D6*/ /**/ + 0x04D6, /*U+04D7*/ /*CYRILLIC SMALL LETTER IE WITH BREVE*/ + 0x04D8, /*U+04D8*/ /**/ + 0x04D8, /*U+04D9*/ /*CYRILLIC SMALL LETTER SCHWA*/ + 0x04DA, /*U+04DA*/ /**/ + 0x04DA, /*U+04DB*/ /*CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS*/ + 0x04DC, /*U+04DC*/ /**/ + 0x04DC, /*U+04DD*/ /*CYRILLIC SMALL LETTER ZHE WITH DIAERESIS*/ + 0x04DE, /*U+04DE*/ /**/ + 0x04DE, /*U+04DF*/ /*CYRILLIC SMALL LETTER ZE WITH DIAERESIS*/ + 0x04E0, /*U+04E0*/ /**/ + 0x04E0, /*U+04E1*/ /*CYRILLIC SMALL LETTER ABKHASIAN DZE*/ + 0x04E2, /*U+04E2*/ /**/ + 0x04E2, /*U+04E3*/ /*CYRILLIC SMALL LETTER I WITH MACRON*/ + 0x04E4, /*U+04E4*/ /**/ + 0x04E4, /*U+04E5*/ /*CYRILLIC SMALL LETTER I WITH DIAERESIS*/ + 0x04E6, /*U+04E6*/ /**/ + 0x04E6, /*U+04E7*/ /*CYRILLIC SMALL LETTER O WITH DIAERESIS*/ + 0x04E8, /*U+04E8*/ /**/ + 0x04E8, /*U+04E9*/ /*CYRILLIC SMALL LETTER BARRED O*/ + 0x04EA, /*U+04EA*/ /**/ + 0x04EA, /*U+04EB*/ /*CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS*/ + 0x04EC, /*U+04EC*/ /**/ + 0x04EC, /*U+04ED*/ /*CYRILLIC SMALL LETTER E WITH DIAERESIS*/ + 0x04EE, /*U+04EE*/ /**/ + 0x04EE, /*U+04EF*/ /*CYRILLIC SMALL LETTER U WITH MACRON*/ + 0x04F0, /*U+04F0*/ /**/ + 0x04F0, /*U+04F1*/ /*CYRILLIC SMALL LETTER U WITH DIAERESIS*/ + 0x04F2, /*U+04F2*/ /**/ + 0x04F2, /*U+04F3*/ /*CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE*/ + 0x04F4, /*U+04F4*/ /**/ + 0x04F4, /*U+04F5*/ /*CYRILLIC SMALL LETTER CHE WITH DIAERESIS*/ + 0x04F6, /*U+04F6*/ /**/ + 0x04F6, /*U+04F7*/ /*CYRILLIC SMALL LETTER GHE WITH DESCENDER*/ + 0x04F8, /*U+04F8*/ /**/ + 0x04F8, /*U+04F9*/ /*CYRILLIC SMALL LETTER YERU WITH DIAERESIS*/ + 0x04FA, /*U+04FA*/ /**/ + 0x04FA, /*U+04FB*/ /*CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK*/ + 0x04FC, /*U+04FC*/ /**/ + 0x04FC, /*U+04FD*/ /*CYRILLIC SMALL LETTER HA WITH HOOK*/ + 0x04FE, /*U+04FE*/ /**/ + 0x04FE, /*U+04FF*/ /*CYRILLIC SMALL LETTER HA WITH STROKE*/ + 0x0500, /*U+0500*/ /**/ + 0x0500, /*U+0501*/ /*CYRILLIC SMALL LETTER KOMI DE*/ + 0x0502, /*U+0502*/ /**/ + 0x0502, /*U+0503*/ /*CYRILLIC SMALL LETTER KOMI DJE*/ + 0x0504, /*U+0504*/ /**/ + 0x0504, /*U+0505*/ /*CYRILLIC SMALL LETTER KOMI ZJE*/ + 0x0506, /*U+0506*/ /**/ + 0x0506, /*U+0507*/ /*CYRILLIC SMALL LETTER KOMI DZJE*/ + 0x0508, /*U+0508*/ /**/ + 0x0508, /*U+0509*/ /*CYRILLIC SMALL LETTER KOMI LJE*/ + 0x050A, /*U+050A*/ /**/ + 0x050A, /*U+050B*/ /*CYRILLIC SMALL LETTER KOMI NJE*/ + 0x050C, /*U+050C*/ /**/ + 0x050C, /*U+050D*/ /*CYRILLIC SMALL LETTER KOMI SJE*/ + 0x050E, /*U+050E*/ /**/ + 0x050E, /*U+050F*/ /*CYRILLIC SMALL LETTER KOMI TJE*/ + 0x0510, /*U+0510*/ /**/ + 0x0510, /*U+0511*/ /*CYRILLIC SMALL LETTER REVERSED ZE*/ + 0x0512, /*U+0512*/ /**/ + 0x0512, /*U+0513*/ /*CYRILLIC SMALL LETTER EL WITH HOOK*/ + 0x0514, /*U+0514*/ /**/ + 0x0514, /*U+0515*/ /*CYRILLIC SMALL LETTER LHA*/ + 0x0516, /*U+0516*/ /**/ + 0x0516, /*U+0517*/ /*CYRILLIC SMALL LETTER RHA*/ + 0x0518, /*U+0518*/ /**/ + 0x0518, /*U+0519*/ /*CYRILLIC SMALL LETTER YAE*/ + 0x051A, /*U+051A*/ /**/ + 0x051A, /*U+051B*/ /*CYRILLIC SMALL LETTER QA*/ + 0x051C, /*U+051C*/ /**/ + 0x051C, /*U+051D*/ /*CYRILLIC SMALL LETTER WE*/ + 0x051E, /*U+051E*/ /**/ + 0x051E, /*U+051F*/ /*CYRILLIC SMALL LETTER ALEUT KA*/ + 0x0520, /*U+0520*/ /**/ + 0x0520, /*U+0521*/ /*CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK*/ + 0x0522, /*U+0522*/ /**/ + 0x0522, /*U+0523*/ /*CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK*/ + 0x0524, /*U+0524*/ /**/ + 0x0524, /*U+0525*/ /*CYRILLIC SMALL LETTER PE WITH DESCENDER*/ + 0x0526, /*U+0526*/ /**/ + 0x0526, /*U+0527*/ /*CYRILLIC SMALL LETTER SHHA WITH DESCENDER*/ + 0x0528, /*U+0528*/ /**/ + 0x0528, /*U+0529*/ /*CYRILLIC SMALL LETTER EN WITH LEFT HOOK*/ + 0x052A, /*U+052A*/ /**/ + 0x052A, /*U+052B*/ /*CYRILLIC SMALL LETTER DZZHE*/ + 0x052C, /*U+052C*/ /**/ + 0x052C, /*U+052D*/ /*CYRILLIC SMALL LETTER DCHE*/ + 0x052E, /*U+052E*/ /**/ + 0x052E, /*U+052F*/ /*CYRILLIC SMALL LETTER EL WITH DESCENDER*/ + 0x0530, /*U+0530*/ /**/ + 0x0531, /*U+0531*/ /**/ + 0x0532, /*U+0532*/ /**/ + 0x0533, /*U+0533*/ /**/ + 0x0534, /*U+0534*/ /**/ + 0x0535, /*U+0535*/ /**/ + 0x0536, /*U+0536*/ /**/ + 0x0537, /*U+0537*/ /**/ + 0x0538, /*U+0538*/ /**/ + 0x0539, /*U+0539*/ /**/ + 0x053A, /*U+053A*/ /**/ + 0x053B, /*U+053B*/ /**/ + 0x053C, /*U+053C*/ /**/ + 0x053D, /*U+053D*/ /**/ + 0x053E, /*U+053E*/ /**/ + 0x053F, /*U+053F*/ /**/ + 0x0540, /*U+0540*/ /**/ + 0x0541, /*U+0541*/ /**/ + 0x0542, /*U+0542*/ /**/ + 0x0543, /*U+0543*/ /**/ + 0x0544, /*U+0544*/ /**/ + 0x0545, /*U+0545*/ /**/ + 0x0546, /*U+0546*/ /**/ + 0x0547, /*U+0547*/ /**/ + 0x0548, /*U+0548*/ /**/ + 0x0549, /*U+0549*/ /**/ + 0x054A, /*U+054A*/ /**/ + 0x054B, /*U+054B*/ /**/ + 0x054C, /*U+054C*/ /**/ + 0x054D, /*U+054D*/ /**/ + 0x054E, /*U+054E*/ /**/ + 0x054F, /*U+054F*/ /**/ + 0x0550, /*U+0550*/ /**/ + 0x0551, /*U+0551*/ /**/ + 0x0552, /*U+0552*/ /**/ + 0x0553, /*U+0553*/ /**/ + 0x0554, /*U+0554*/ /**/ + 0x0555, /*U+0555*/ /**/ + 0x0556, /*U+0556*/ /**/ + 0x0557, /*U+0557*/ /**/ + 0x0558, /*U+0558*/ /**/ + 0x0559, /*U+0559*/ /**/ + 0x055A, /*U+055A*/ /**/ + 0x055B, /*U+055B*/ /**/ + 0x055C, /*U+055C*/ /**/ + 0x055D, /*U+055D*/ /**/ + 0x055E, /*U+055E*/ /**/ + 0x055F, /*U+055F*/ /**/ + 0x0560, /*U+0560*/ /**/ + 0x0531, /*U+0561*/ /*ARMENIAN SMALL LETTER AYB*/ + 0x0532, /*U+0562*/ /*ARMENIAN SMALL LETTER BEN*/ + 0x0533, /*U+0563*/ /*ARMENIAN SMALL LETTER GIM*/ + 0x0534, /*U+0564*/ /*ARMENIAN SMALL LETTER DA*/ + 0x0535, /*U+0565*/ /*ARMENIAN SMALL LETTER ECH*/ + 0x0536, /*U+0566*/ /*ARMENIAN SMALL LETTER ZA*/ + 0x0537, /*U+0567*/ /*ARMENIAN SMALL LETTER EH*/ + 0x0538, /*U+0568*/ /*ARMENIAN SMALL LETTER ET*/ + 0x0539, /*U+0569*/ /*ARMENIAN SMALL LETTER TO*/ + 0x053A, /*U+056A*/ /*ARMENIAN SMALL LETTER ZHE*/ + 0x053B, /*U+056B*/ /*ARMENIAN SMALL LETTER INI*/ + 0x053C, /*U+056C*/ /*ARMENIAN SMALL LETTER LIWN*/ + 0x053D, /*U+056D*/ /*ARMENIAN SMALL LETTER XEH*/ + 0x053E, /*U+056E*/ /*ARMENIAN SMALL LETTER CA*/ + 0x053F, /*U+056F*/ /*ARMENIAN SMALL LETTER KEN*/ + 0x0540, /*U+0570*/ /*ARMENIAN SMALL LETTER HO*/ + 0x0541, /*U+0571*/ /*ARMENIAN SMALL LETTER JA*/ + 0x0542, /*U+0572*/ /*ARMENIAN SMALL LETTER GHAD*/ + 0x0543, /*U+0573*/ /*ARMENIAN SMALL LETTER CHEH*/ + 0x0544, /*U+0574*/ /*ARMENIAN SMALL LETTER MEN*/ + 0x0545, /*U+0575*/ /*ARMENIAN SMALL LETTER YI*/ + 0x0546, /*U+0576*/ /*ARMENIAN SMALL LETTER NOW*/ + 0x0547, /*U+0577*/ /*ARMENIAN SMALL LETTER SHA*/ + 0x0548, /*U+0578*/ /*ARMENIAN SMALL LETTER VO*/ + 0x0549, /*U+0579*/ /*ARMENIAN SMALL LETTER CHA*/ + 0x054A, /*U+057A*/ /*ARMENIAN SMALL LETTER PEH*/ + 0x054B, /*U+057B*/ /*ARMENIAN SMALL LETTER JHEH*/ + 0x054C, /*U+057C*/ /*ARMENIAN SMALL LETTER RA*/ + 0x054D, /*U+057D*/ /*ARMENIAN SMALL LETTER SEH*/ + 0x054E, /*U+057E*/ /*ARMENIAN SMALL LETTER VEW*/ + 0x054F, /*U+057F*/ /*ARMENIAN SMALL LETTER TIWN*/ + 0x0550, /*U+0580*/ /*ARMENIAN SMALL LETTER REH*/ + 0x0551, /*U+0581*/ /*ARMENIAN SMALL LETTER CO*/ + 0x0552, /*U+0582*/ /*ARMENIAN SMALL LETTER YIWN*/ + 0x0553, /*U+0583*/ /*ARMENIAN SMALL LETTER PIWR*/ + 0x0554, /*U+0584*/ /*ARMENIAN SMALL LETTER KEH*/ + 0x0555, /*U+0585*/ /*ARMENIAN SMALL LETTER OH*/ + 0x0556, /*U+0586*/ /*ARMENIAN SMALL LETTER FEH*/ + 0x0587, /*U+0587*/ /**/ + 0x0588, /*U+0588*/ /**/ + 0x0589, /*U+0589*/ /**/ + 0x058A, /*U+058A*/ /**/ + 0x058B, /*U+058B*/ /**/ + 0x058C, /*U+058C*/ /**/ + 0x058D, /*U+058D*/ /**/ + 0x058E, /*U+058E*/ /**/ + 0x058F, /*U+058F*/ /**/ + 0x0590, /*U+0590*/ /**/ + 0x0591, /*U+0591*/ /**/ + 0x0592, /*U+0592*/ /**/ + 0x0593, /*U+0593*/ /**/ + 0x0594, /*U+0594*/ /**/ + 0x0595, /*U+0595*/ /**/ + 0x0596, /*U+0596*/ /**/ + 0x0597, /*U+0597*/ /**/ + 0x0598, /*U+0598*/ /**/ + 0x0599, /*U+0599*/ /**/ + 0x059A, /*U+059A*/ /**/ + 0x059B, /*U+059B*/ /**/ + 0x059C, /*U+059C*/ /**/ + 0x059D, /*U+059D*/ /**/ + 0x059E, /*U+059E*/ /**/ + 0x059F, /*U+059F*/ /**/ + 0x05A0, /*U+05A0*/ /**/ + 0x05A1, /*U+05A1*/ /**/ + 0x05A2, /*U+05A2*/ /**/ + 0x05A3, /*U+05A3*/ /**/ + 0x05A4, /*U+05A4*/ /**/ + 0x05A5, /*U+05A5*/ /**/ + 0x05A6, /*U+05A6*/ /**/ + 0x05A7, /*U+05A7*/ /**/ + 0x05A8, /*U+05A8*/ /**/ + 0x05A9, /*U+05A9*/ /**/ + 0x05AA, /*U+05AA*/ /**/ + 0x05AB, /*U+05AB*/ /**/ + 0x05AC, /*U+05AC*/ /**/ + 0x05AD, /*U+05AD*/ /**/ + 0x05AE, /*U+05AE*/ /**/ + 0x05AF, /*U+05AF*/ /**/ + 0x05B0, /*U+05B0*/ /**/ + 0x05B1, /*U+05B1*/ /**/ + 0x05B2, /*U+05B2*/ /**/ + 0x05B3, /*U+05B3*/ /**/ + 0x05B4, /*U+05B4*/ /**/ + 0x05B5, /*U+05B5*/ /**/ + 0x05B6, /*U+05B6*/ /**/ + 0x05B7, /*U+05B7*/ /**/ + 0x05B8, /*U+05B8*/ /**/ + 0x05B9, /*U+05B9*/ /**/ + 0x05BA, /*U+05BA*/ /**/ + 0x05BB, /*U+05BB*/ /**/ + 0x05BC, /*U+05BC*/ /**/ + 0x05BD, /*U+05BD*/ /**/ + 0x05BE, /*U+05BE*/ /**/ + 0x05BF, /*U+05BF*/ /**/ +}; + +static const uint16_t upper_table_3[64] = { + 0x1D40, /*U+1D40*/ /**/ + 0x1D41, /*U+1D41*/ /**/ + 0x1D42, /*U+1D42*/ /**/ + 0x1D43, /*U+1D43*/ /**/ + 0x1D44, /*U+1D44*/ /**/ + 0x1D45, /*U+1D45*/ /**/ + 0x1D46, /*U+1D46*/ /**/ + 0x1D47, /*U+1D47*/ /**/ + 0x1D48, /*U+1D48*/ /**/ + 0x1D49, /*U+1D49*/ /**/ + 0x1D4A, /*U+1D4A*/ /**/ + 0x1D4B, /*U+1D4B*/ /**/ + 0x1D4C, /*U+1D4C*/ /**/ + 0x1D4D, /*U+1D4D*/ /**/ + 0x1D4E, /*U+1D4E*/ /**/ + 0x1D4F, /*U+1D4F*/ /**/ + 0x1D50, /*U+1D50*/ /**/ + 0x1D51, /*U+1D51*/ /**/ + 0x1D52, /*U+1D52*/ /**/ + 0x1D53, /*U+1D53*/ /**/ + 0x1D54, /*U+1D54*/ /**/ + 0x1D55, /*U+1D55*/ /**/ + 0x1D56, /*U+1D56*/ /**/ + 0x1D57, /*U+1D57*/ /**/ + 0x1D58, /*U+1D58*/ /**/ + 0x1D59, /*U+1D59*/ /**/ + 0x1D5A, /*U+1D5A*/ /**/ + 0x1D5B, /*U+1D5B*/ /**/ + 0x1D5C, /*U+1D5C*/ /**/ + 0x1D5D, /*U+1D5D*/ /**/ + 0x1D5E, /*U+1D5E*/ /**/ + 0x1D5F, /*U+1D5F*/ /**/ + 0x1D60, /*U+1D60*/ /**/ + 0x1D61, /*U+1D61*/ /**/ + 0x1D62, /*U+1D62*/ /**/ + 0x1D63, /*U+1D63*/ /**/ + 0x1D64, /*U+1D64*/ /**/ + 0x1D65, /*U+1D65*/ /**/ + 0x1D66, /*U+1D66*/ /**/ + 0x1D67, /*U+1D67*/ /**/ + 0x1D68, /*U+1D68*/ /**/ + 0x1D69, /*U+1D69*/ /**/ + 0x1D6A, /*U+1D6A*/ /**/ + 0x1D6B, /*U+1D6B*/ /**/ + 0x1D6C, /*U+1D6C*/ /**/ + 0x1D6D, /*U+1D6D*/ /**/ + 0x1D6E, /*U+1D6E*/ /**/ + 0x1D6F, /*U+1D6F*/ /**/ + 0x1D70, /*U+1D70*/ /**/ + 0x1D71, /*U+1D71*/ /**/ + 0x1D72, /*U+1D72*/ /**/ + 0x1D73, /*U+1D73*/ /**/ + 0x1D74, /*U+1D74*/ /**/ + 0x1D75, /*U+1D75*/ /**/ + 0x1D76, /*U+1D76*/ /**/ + 0x1D77, /*U+1D77*/ /**/ + 0x1D78, /*U+1D78*/ /**/ + 0xA77D, /*U+1D79*/ /*LATIN SMALL LETTER INSULAR G*/ + 0x1D7A, /*U+1D7A*/ /**/ + 0x1D7B, /*U+1D7B*/ /**/ + 0x1D7C, /*U+1D7C*/ /**/ + 0x2C63, /*U+1D7D*/ /*LATIN SMALL LETTER P WITH STROKE*/ + 0x1D7E, /*U+1D7E*/ /**/ + 0x1D7F, /*U+1D7F*/ /**/ +}; + +static const uint16_t upper_table_4[512] = { + 0x1E00, /*U+1E00*/ /**/ + 0x1E00, /*U+1E01*/ /*LATIN SMALL LETTER A WITH RING BELOW*/ + 0x1E02, /*U+1E02*/ /**/ + 0x1E02, /*U+1E03*/ /*LATIN SMALL LETTER B WITH DOT ABOVE*/ + 0x1E04, /*U+1E04*/ /**/ + 0x1E04, /*U+1E05*/ /*LATIN SMALL LETTER B WITH DOT BELOW*/ + 0x1E06, /*U+1E06*/ /**/ + 0x1E06, /*U+1E07*/ /*LATIN SMALL LETTER B WITH LINE BELOW*/ + 0x1E08, /*U+1E08*/ /**/ + 0x1E08, /*U+1E09*/ /*LATIN SMALL LETTER C WITH CEDILLA AND ACUTE*/ + 0x1E0A, /*U+1E0A*/ /**/ + 0x1E0A, /*U+1E0B*/ /*LATIN SMALL LETTER D WITH DOT ABOVE*/ + 0x1E0C, /*U+1E0C*/ /**/ + 0x1E0C, /*U+1E0D*/ /*LATIN SMALL LETTER D WITH DOT BELOW*/ + 0x1E0E, /*U+1E0E*/ /**/ + 0x1E0E, /*U+1E0F*/ /*LATIN SMALL LETTER D WITH LINE BELOW*/ + 0x1E10, /*U+1E10*/ /**/ + 0x1E10, /*U+1E11*/ /*LATIN SMALL LETTER D WITH CEDILLA*/ + 0x1E12, /*U+1E12*/ /**/ + 0x1E12, /*U+1E13*/ /*LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW*/ + 0x1E14, /*U+1E14*/ /**/ + 0x1E14, /*U+1E15*/ /*LATIN SMALL LETTER E WITH MACRON AND GRAVE*/ + 0x1E16, /*U+1E16*/ /**/ + 0x1E16, /*U+1E17*/ /*LATIN SMALL LETTER E WITH MACRON AND ACUTE*/ + 0x1E18, /*U+1E18*/ /**/ + 0x1E18, /*U+1E19*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW*/ + 0x1E1A, /*U+1E1A*/ /**/ + 0x1E1A, /*U+1E1B*/ /*LATIN SMALL LETTER E WITH TILDE BELOW*/ + 0x1E1C, /*U+1E1C*/ /**/ + 0x1E1C, /*U+1E1D*/ /*LATIN SMALL LETTER E WITH CEDILLA AND BREVE*/ + 0x1E1E, /*U+1E1E*/ /**/ + 0x1E1E, /*U+1E1F*/ /*LATIN SMALL LETTER F WITH DOT ABOVE*/ + 0x1E20, /*U+1E20*/ /**/ + 0x1E20, /*U+1E21*/ /*LATIN SMALL LETTER G WITH MACRON*/ + 0x1E22, /*U+1E22*/ /**/ + 0x1E22, /*U+1E23*/ /*LATIN SMALL LETTER H WITH DOT ABOVE*/ + 0x1E24, /*U+1E24*/ /**/ + 0x1E24, /*U+1E25*/ /*LATIN SMALL LETTER H WITH DOT BELOW*/ + 0x1E26, /*U+1E26*/ /**/ + 0x1E26, /*U+1E27*/ /*LATIN SMALL LETTER H WITH DIAERESIS*/ + 0x1E28, /*U+1E28*/ /**/ + 0x1E28, /*U+1E29*/ /*LATIN SMALL LETTER H WITH CEDILLA*/ + 0x1E2A, /*U+1E2A*/ /**/ + 0x1E2A, /*U+1E2B*/ /*LATIN SMALL LETTER H WITH BREVE BELOW*/ + 0x1E2C, /*U+1E2C*/ /**/ + 0x1E2C, /*U+1E2D*/ /*LATIN SMALL LETTER I WITH TILDE BELOW*/ + 0x1E2E, /*U+1E2E*/ /**/ + 0x1E2E, /*U+1E2F*/ /*LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE*/ + 0x1E30, /*U+1E30*/ /**/ + 0x1E30, /*U+1E31*/ /*LATIN SMALL LETTER K WITH ACUTE*/ + 0x1E32, /*U+1E32*/ /**/ + 0x1E32, /*U+1E33*/ /*LATIN SMALL LETTER K WITH DOT BELOW*/ + 0x1E34, /*U+1E34*/ /**/ + 0x1E34, /*U+1E35*/ /*LATIN SMALL LETTER K WITH LINE BELOW*/ + 0x1E36, /*U+1E36*/ /**/ + 0x1E36, /*U+1E37*/ /*LATIN SMALL LETTER L WITH DOT BELOW*/ + 0x1E38, /*U+1E38*/ /**/ + 0x1E38, /*U+1E39*/ /*LATIN SMALL LETTER L WITH DOT BELOW AND MACRON*/ + 0x1E3A, /*U+1E3A*/ /**/ + 0x1E3A, /*U+1E3B*/ /*LATIN SMALL LETTER L WITH LINE BELOW*/ + 0x1E3C, /*U+1E3C*/ /**/ + 0x1E3C, /*U+1E3D*/ /*LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW*/ + 0x1E3E, /*U+1E3E*/ /**/ + 0x1E3E, /*U+1E3F*/ /*LATIN SMALL LETTER M WITH ACUTE*/ + 0x1E40, /*U+1E40*/ /**/ + 0x1E40, /*U+1E41*/ /*LATIN SMALL LETTER M WITH DOT ABOVE*/ + 0x1E42, /*U+1E42*/ /**/ + 0x1E42, /*U+1E43*/ /*LATIN SMALL LETTER M WITH DOT BELOW*/ + 0x1E44, /*U+1E44*/ /**/ + 0x1E44, /*U+1E45*/ /*LATIN SMALL LETTER N WITH DOT ABOVE*/ + 0x1E46, /*U+1E46*/ /**/ + 0x1E46, /*U+1E47*/ /*LATIN SMALL LETTER N WITH DOT BELOW*/ + 0x1E48, /*U+1E48*/ /**/ + 0x1E48, /*U+1E49*/ /*LATIN SMALL LETTER N WITH LINE BELOW*/ + 0x1E4A, /*U+1E4A*/ /**/ + 0x1E4A, /*U+1E4B*/ /*LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW*/ + 0x1E4C, /*U+1E4C*/ /**/ + 0x1E4C, /*U+1E4D*/ /*LATIN SMALL LETTER O WITH TILDE AND ACUTE*/ + 0x1E4E, /*U+1E4E*/ /**/ + 0x1E4E, /*U+1E4F*/ /*LATIN SMALL LETTER O WITH TILDE AND DIAERESIS*/ + 0x1E50, /*U+1E50*/ /**/ + 0x1E50, /*U+1E51*/ /*LATIN SMALL LETTER O WITH MACRON AND GRAVE*/ + 0x1E52, /*U+1E52*/ /**/ + 0x1E52, /*U+1E53*/ /*LATIN SMALL LETTER O WITH MACRON AND ACUTE*/ + 0x1E54, /*U+1E54*/ /**/ + 0x1E54, /*U+1E55*/ /*LATIN SMALL LETTER P WITH ACUTE*/ + 0x1E56, /*U+1E56*/ /**/ + 0x1E56, /*U+1E57*/ /*LATIN SMALL LETTER P WITH DOT ABOVE*/ + 0x1E58, /*U+1E58*/ /**/ + 0x1E58, /*U+1E59*/ /*LATIN SMALL LETTER R WITH DOT ABOVE*/ + 0x1E5A, /*U+1E5A*/ /**/ + 0x1E5A, /*U+1E5B*/ /*LATIN SMALL LETTER R WITH DOT BELOW*/ + 0x1E5C, /*U+1E5C*/ /**/ + 0x1E5C, /*U+1E5D*/ /*LATIN SMALL LETTER R WITH DOT BELOW AND MACRON*/ + 0x1E5E, /*U+1E5E*/ /**/ + 0x1E5E, /*U+1E5F*/ /*LATIN SMALL LETTER R WITH LINE BELOW*/ + 0x1E60, /*U+1E60*/ /**/ + 0x1E60, /*U+1E61*/ /*LATIN SMALL LETTER S WITH DOT ABOVE*/ + 0x1E62, /*U+1E62*/ /**/ + 0x1E62, /*U+1E63*/ /*LATIN SMALL LETTER S WITH DOT BELOW*/ + 0x1E64, /*U+1E64*/ /**/ + 0x1E64, /*U+1E65*/ /*LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE*/ + 0x1E66, /*U+1E66*/ /**/ + 0x1E66, /*U+1E67*/ /*LATIN SMALL LETTER S WITH CARON AND DOT ABOVE*/ + 0x1E68, /*U+1E68*/ /**/ + 0x1E68, /*U+1E69*/ /*LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE*/ + 0x1E6A, /*U+1E6A*/ /**/ + 0x1E6A, /*U+1E6B*/ /*LATIN SMALL LETTER T WITH DOT ABOVE*/ + 0x1E6C, /*U+1E6C*/ /**/ + 0x1E6C, /*U+1E6D*/ /*LATIN SMALL LETTER T WITH DOT BELOW*/ + 0x1E6E, /*U+1E6E*/ /**/ + 0x1E6E, /*U+1E6F*/ /*LATIN SMALL LETTER T WITH LINE BELOW*/ + 0x1E70, /*U+1E70*/ /**/ + 0x1E70, /*U+1E71*/ /*LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW*/ + 0x1E72, /*U+1E72*/ /**/ + 0x1E72, /*U+1E73*/ /*LATIN SMALL LETTER U WITH DIAERESIS BELOW*/ + 0x1E74, /*U+1E74*/ /**/ + 0x1E74, /*U+1E75*/ /*LATIN SMALL LETTER U WITH TILDE BELOW*/ + 0x1E76, /*U+1E76*/ /**/ + 0x1E76, /*U+1E77*/ /*LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW*/ + 0x1E78, /*U+1E78*/ /**/ + 0x1E78, /*U+1E79*/ /*LATIN SMALL LETTER U WITH TILDE AND ACUTE*/ + 0x1E7A, /*U+1E7A*/ /**/ + 0x1E7A, /*U+1E7B*/ /*LATIN SMALL LETTER U WITH MACRON AND DIAERESIS*/ + 0x1E7C, /*U+1E7C*/ /**/ + 0x1E7C, /*U+1E7D*/ /*LATIN SMALL LETTER V WITH TILDE*/ + 0x1E7E, /*U+1E7E*/ /**/ + 0x1E7E, /*U+1E7F*/ /*LATIN SMALL LETTER V WITH DOT BELOW*/ + 0x1E80, /*U+1E80*/ /**/ + 0x1E80, /*U+1E81*/ /*LATIN SMALL LETTER W WITH GRAVE*/ + 0x1E82, /*U+1E82*/ /**/ + 0x1E82, /*U+1E83*/ /*LATIN SMALL LETTER W WITH ACUTE*/ + 0x1E84, /*U+1E84*/ /**/ + 0x1E84, /*U+1E85*/ /*LATIN SMALL LETTER W WITH DIAERESIS*/ + 0x1E86, /*U+1E86*/ /**/ + 0x1E86, /*U+1E87*/ /*LATIN SMALL LETTER W WITH DOT ABOVE*/ + 0x1E88, /*U+1E88*/ /**/ + 0x1E88, /*U+1E89*/ /*LATIN SMALL LETTER W WITH DOT BELOW*/ + 0x1E8A, /*U+1E8A*/ /**/ + 0x1E8A, /*U+1E8B*/ /*LATIN SMALL LETTER X WITH DOT ABOVE*/ + 0x1E8C, /*U+1E8C*/ /**/ + 0x1E8C, /*U+1E8D*/ /*LATIN SMALL LETTER X WITH DIAERESIS*/ + 0x1E8E, /*U+1E8E*/ /**/ + 0x1E8E, /*U+1E8F*/ /*LATIN SMALL LETTER Y WITH DOT ABOVE*/ + 0x1E90, /*U+1E90*/ /**/ + 0x1E90, /*U+1E91*/ /*LATIN SMALL LETTER Z WITH CIRCUMFLEX*/ + 0x1E92, /*U+1E92*/ /**/ + 0x1E92, /*U+1E93*/ /*LATIN SMALL LETTER Z WITH DOT BELOW*/ + 0x1E94, /*U+1E94*/ /**/ + 0x1E94, /*U+1E95*/ /*LATIN SMALL LETTER Z WITH LINE BELOW*/ + 0x1E96, /*U+1E96*/ /**/ + 0x1E97, /*U+1E97*/ /**/ + 0x1E98, /*U+1E98*/ /**/ + 0x1E99, /*U+1E99*/ /**/ + 0x1E9A, /*U+1E9A*/ /**/ + 0x1E60, /*U+1E9B*/ /*LATIN SMALL LETTER LONG S WITH DOT ABOVE*/ + 0x1E9C, /*U+1E9C*/ /**/ + 0x1E9D, /*U+1E9D*/ /**/ + 0x1E9E, /*U+1E9E*/ /**/ + 0x1E9F, /*U+1E9F*/ /**/ + 0x1EA0, /*U+1EA0*/ /**/ + 0x1EA0, /*U+1EA1*/ /*LATIN SMALL LETTER A WITH DOT BELOW*/ + 0x1EA2, /*U+1EA2*/ /**/ + 0x1EA2, /*U+1EA3*/ /*LATIN SMALL LETTER A WITH HOOK ABOVE*/ + 0x1EA4, /*U+1EA4*/ /**/ + 0x1EA4, /*U+1EA5*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE*/ + 0x1EA6, /*U+1EA6*/ /**/ + 0x1EA6, /*U+1EA7*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE*/ + 0x1EA8, /*U+1EA8*/ /**/ + 0x1EA8, /*U+1EA9*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE*/ + 0x1EAA, /*U+1EAA*/ /**/ + 0x1EAA, /*U+1EAB*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE*/ + 0x1EAC, /*U+1EAC*/ /**/ + 0x1EAC, /*U+1EAD*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW*/ + 0x1EAE, /*U+1EAE*/ /**/ + 0x1EAE, /*U+1EAF*/ /*LATIN SMALL LETTER A WITH BREVE AND ACUTE*/ + 0x1EB0, /*U+1EB0*/ /**/ + 0x1EB0, /*U+1EB1*/ /*LATIN SMALL LETTER A WITH BREVE AND GRAVE*/ + 0x1EB2, /*U+1EB2*/ /**/ + 0x1EB2, /*U+1EB3*/ /*LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE*/ + 0x1EB4, /*U+1EB4*/ /**/ + 0x1EB4, /*U+1EB5*/ /*LATIN SMALL LETTER A WITH BREVE AND TILDE*/ + 0x1EB6, /*U+1EB6*/ /**/ + 0x1EB6, /*U+1EB7*/ /*LATIN SMALL LETTER A WITH BREVE AND DOT BELOW*/ + 0x1EB8, /*U+1EB8*/ /**/ + 0x1EB8, /*U+1EB9*/ /*LATIN SMALL LETTER E WITH DOT BELOW*/ + 0x1EBA, /*U+1EBA*/ /**/ + 0x1EBA, /*U+1EBB*/ /*LATIN SMALL LETTER E WITH HOOK ABOVE*/ + 0x1EBC, /*U+1EBC*/ /**/ + 0x1EBC, /*U+1EBD*/ /*LATIN SMALL LETTER E WITH TILDE*/ + 0x1EBE, /*U+1EBE*/ /**/ + 0x1EBE, /*U+1EBF*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE*/ + 0x1EC0, /*U+1EC0*/ /**/ + 0x1EC0, /*U+1EC1*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE*/ + 0x1EC2, /*U+1EC2*/ /**/ + 0x1EC2, /*U+1EC3*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE*/ + 0x1EC4, /*U+1EC4*/ /**/ + 0x1EC4, /*U+1EC5*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE*/ + 0x1EC6, /*U+1EC6*/ /**/ + 0x1EC6, /*U+1EC7*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW*/ + 0x1EC8, /*U+1EC8*/ /**/ + 0x1EC8, /*U+1EC9*/ /*LATIN SMALL LETTER I WITH HOOK ABOVE*/ + 0x1ECA, /*U+1ECA*/ /**/ + 0x1ECA, /*U+1ECB*/ /*LATIN SMALL LETTER I WITH DOT BELOW*/ + 0x1ECC, /*U+1ECC*/ /**/ + 0x1ECC, /*U+1ECD*/ /*LATIN SMALL LETTER O WITH DOT BELOW*/ + 0x1ECE, /*U+1ECE*/ /**/ + 0x1ECE, /*U+1ECF*/ /*LATIN SMALL LETTER O WITH HOOK ABOVE*/ + 0x1ED0, /*U+1ED0*/ /**/ + 0x1ED0, /*U+1ED1*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE*/ + 0x1ED2, /*U+1ED2*/ /**/ + 0x1ED2, /*U+1ED3*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE*/ + 0x1ED4, /*U+1ED4*/ /**/ + 0x1ED4, /*U+1ED5*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE*/ + 0x1ED6, /*U+1ED6*/ /**/ + 0x1ED6, /*U+1ED7*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE*/ + 0x1ED8, /*U+1ED8*/ /**/ + 0x1ED8, /*U+1ED9*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW*/ + 0x1EDA, /*U+1EDA*/ /**/ + 0x1EDA, /*U+1EDB*/ /*LATIN SMALL LETTER O WITH HORN AND ACUTE*/ + 0x1EDC, /*U+1EDC*/ /**/ + 0x1EDC, /*U+1EDD*/ /*LATIN SMALL LETTER O WITH HORN AND GRAVE*/ + 0x1EDE, /*U+1EDE*/ /**/ + 0x1EDE, /*U+1EDF*/ /*LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE*/ + 0x1EE0, /*U+1EE0*/ /**/ + 0x1EE0, /*U+1EE1*/ /*LATIN SMALL LETTER O WITH HORN AND TILDE*/ + 0x1EE2, /*U+1EE2*/ /**/ + 0x1EE2, /*U+1EE3*/ /*LATIN SMALL LETTER O WITH HORN AND DOT BELOW*/ + 0x1EE4, /*U+1EE4*/ /**/ + 0x1EE4, /*U+1EE5*/ /*LATIN SMALL LETTER U WITH DOT BELOW*/ + 0x1EE6, /*U+1EE6*/ /**/ + 0x1EE6, /*U+1EE7*/ /*LATIN SMALL LETTER U WITH HOOK ABOVE*/ + 0x1EE8, /*U+1EE8*/ /**/ + 0x1EE8, /*U+1EE9*/ /*LATIN SMALL LETTER U WITH HORN AND ACUTE*/ + 0x1EEA, /*U+1EEA*/ /**/ + 0x1EEA, /*U+1EEB*/ /*LATIN SMALL LETTER U WITH HORN AND GRAVE*/ + 0x1EEC, /*U+1EEC*/ /**/ + 0x1EEC, /*U+1EED*/ /*LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE*/ + 0x1EEE, /*U+1EEE*/ /**/ + 0x1EEE, /*U+1EEF*/ /*LATIN SMALL LETTER U WITH HORN AND TILDE*/ + 0x1EF0, /*U+1EF0*/ /**/ + 0x1EF0, /*U+1EF1*/ /*LATIN SMALL LETTER U WITH HORN AND DOT BELOW*/ + 0x1EF2, /*U+1EF2*/ /**/ + 0x1EF2, /*U+1EF3*/ /*LATIN SMALL LETTER Y WITH GRAVE*/ + 0x1EF4, /*U+1EF4*/ /**/ + 0x1EF4, /*U+1EF5*/ /*LATIN SMALL LETTER Y WITH DOT BELOW*/ + 0x1EF6, /*U+1EF6*/ /**/ + 0x1EF6, /*U+1EF7*/ /*LATIN SMALL LETTER Y WITH HOOK ABOVE*/ + 0x1EF8, /*U+1EF8*/ /**/ + 0x1EF8, /*U+1EF9*/ /*LATIN SMALL LETTER Y WITH TILDE*/ + 0x1EFA, /*U+1EFA*/ /**/ + 0x1EFA, /*U+1EFB*/ /*LATIN SMALL LETTER MIDDLE-WELSH LL*/ + 0x1EFC, /*U+1EFC*/ /**/ + 0x1EFC, /*U+1EFD*/ /*LATIN SMALL LETTER MIDDLE-WELSH V*/ + 0x1EFE, /*U+1EFE*/ /**/ + 0x1EFE, /*U+1EFF*/ /*LATIN SMALL LETTER Y WITH LOOP*/ + 0x1F08, /*U+1F00*/ /*GREEK SMALL LETTER ALPHA WITH PSILI*/ + 0x1F09, /*U+1F01*/ /*GREEK SMALL LETTER ALPHA WITH DASIA*/ + 0x1F0A, /*U+1F02*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA*/ + 0x1F0B, /*U+1F03*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA*/ + 0x1F0C, /*U+1F04*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA*/ + 0x1F0D, /*U+1F05*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA*/ + 0x1F0E, /*U+1F06*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI*/ + 0x1F0F, /*U+1F07*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI*/ + 0x1F08, /*U+1F08*/ /**/ + 0x1F09, /*U+1F09*/ /**/ + 0x1F0A, /*U+1F0A*/ /**/ + 0x1F0B, /*U+1F0B*/ /**/ + 0x1F0C, /*U+1F0C*/ /**/ + 0x1F0D, /*U+1F0D*/ /**/ + 0x1F0E, /*U+1F0E*/ /**/ + 0x1F0F, /*U+1F0F*/ /**/ + 0x1F18, /*U+1F10*/ /*GREEK SMALL LETTER EPSILON WITH PSILI*/ + 0x1F19, /*U+1F11*/ /*GREEK SMALL LETTER EPSILON WITH DASIA*/ + 0x1F1A, /*U+1F12*/ /*GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA*/ + 0x1F1B, /*U+1F13*/ /*GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA*/ + 0x1F1C, /*U+1F14*/ /*GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA*/ + 0x1F1D, /*U+1F15*/ /*GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA*/ + 0x1F16, /*U+1F16*/ /**/ + 0x1F17, /*U+1F17*/ /**/ + 0x1F18, /*U+1F18*/ /**/ + 0x1F19, /*U+1F19*/ /**/ + 0x1F1A, /*U+1F1A*/ /**/ + 0x1F1B, /*U+1F1B*/ /**/ + 0x1F1C, /*U+1F1C*/ /**/ + 0x1F1D, /*U+1F1D*/ /**/ + 0x1F1E, /*U+1F1E*/ /**/ + 0x1F1F, /*U+1F1F*/ /**/ + 0x1F28, /*U+1F20*/ /*GREEK SMALL LETTER ETA WITH PSILI*/ + 0x1F29, /*U+1F21*/ /*GREEK SMALL LETTER ETA WITH DASIA*/ + 0x1F2A, /*U+1F22*/ /*GREEK SMALL LETTER ETA WITH PSILI AND VARIA*/ + 0x1F2B, /*U+1F23*/ /*GREEK SMALL LETTER ETA WITH DASIA AND VARIA*/ + 0x1F2C, /*U+1F24*/ /*GREEK SMALL LETTER ETA WITH PSILI AND OXIA*/ + 0x1F2D, /*U+1F25*/ /*GREEK SMALL LETTER ETA WITH DASIA AND OXIA*/ + 0x1F2E, /*U+1F26*/ /*GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI*/ + 0x1F2F, /*U+1F27*/ /*GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI*/ + 0x1F28, /*U+1F28*/ /**/ + 0x1F29, /*U+1F29*/ /**/ + 0x1F2A, /*U+1F2A*/ /**/ + 0x1F2B, /*U+1F2B*/ /**/ + 0x1F2C, /*U+1F2C*/ /**/ + 0x1F2D, /*U+1F2D*/ /**/ + 0x1F2E, /*U+1F2E*/ /**/ + 0x1F2F, /*U+1F2F*/ /**/ + 0x1F38, /*U+1F30*/ /*GREEK SMALL LETTER IOTA WITH PSILI*/ + 0x1F39, /*U+1F31*/ /*GREEK SMALL LETTER IOTA WITH DASIA*/ + 0x1F3A, /*U+1F32*/ /*GREEK SMALL LETTER IOTA WITH PSILI AND VARIA*/ + 0x1F3B, /*U+1F33*/ /*GREEK SMALL LETTER IOTA WITH DASIA AND VARIA*/ + 0x1F3C, /*U+1F34*/ /*GREEK SMALL LETTER IOTA WITH PSILI AND OXIA*/ + 0x1F3D, /*U+1F35*/ /*GREEK SMALL LETTER IOTA WITH DASIA AND OXIA*/ + 0x1F3E, /*U+1F36*/ /*GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI*/ + 0x1F3F, /*U+1F37*/ /*GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI*/ + 0x1F38, /*U+1F38*/ /**/ + 0x1F39, /*U+1F39*/ /**/ + 0x1F3A, /*U+1F3A*/ /**/ + 0x1F3B, /*U+1F3B*/ /**/ + 0x1F3C, /*U+1F3C*/ /**/ + 0x1F3D, /*U+1F3D*/ /**/ + 0x1F3E, /*U+1F3E*/ /**/ + 0x1F3F, /*U+1F3F*/ /**/ + 0x1F48, /*U+1F40*/ /*GREEK SMALL LETTER OMICRON WITH PSILI*/ + 0x1F49, /*U+1F41*/ /*GREEK SMALL LETTER OMICRON WITH DASIA*/ + 0x1F4A, /*U+1F42*/ /*GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA*/ + 0x1F4B, /*U+1F43*/ /*GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA*/ + 0x1F4C, /*U+1F44*/ /*GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA*/ + 0x1F4D, /*U+1F45*/ /*GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA*/ + 0x1F46, /*U+1F46*/ /**/ + 0x1F47, /*U+1F47*/ /**/ + 0x1F48, /*U+1F48*/ /**/ + 0x1F49, /*U+1F49*/ /**/ + 0x1F4A, /*U+1F4A*/ /**/ + 0x1F4B, /*U+1F4B*/ /**/ + 0x1F4C, /*U+1F4C*/ /**/ + 0x1F4D, /*U+1F4D*/ /**/ + 0x1F4E, /*U+1F4E*/ /**/ + 0x1F4F, /*U+1F4F*/ /**/ + 0x1F50, /*U+1F50*/ /**/ + 0x1F59, /*U+1F51*/ /*GREEK SMALL LETTER UPSILON WITH DASIA*/ + 0x1F52, /*U+1F52*/ /**/ + 0x1F5B, /*U+1F53*/ /*GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA*/ + 0x1F54, /*U+1F54*/ /**/ + 0x1F5D, /*U+1F55*/ /*GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA*/ + 0x1F56, /*U+1F56*/ /**/ + 0x1F5F, /*U+1F57*/ /*GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI*/ + 0x1F58, /*U+1F58*/ /**/ + 0x1F59, /*U+1F59*/ /**/ + 0x1F5A, /*U+1F5A*/ /**/ + 0x1F5B, /*U+1F5B*/ /**/ + 0x1F5C, /*U+1F5C*/ /**/ + 0x1F5D, /*U+1F5D*/ /**/ + 0x1F5E, /*U+1F5E*/ /**/ + 0x1F5F, /*U+1F5F*/ /**/ + 0x1F68, /*U+1F60*/ /*GREEK SMALL LETTER OMEGA WITH PSILI*/ + 0x1F69, /*U+1F61*/ /*GREEK SMALL LETTER OMEGA WITH DASIA*/ + 0x1F6A, /*U+1F62*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA*/ + 0x1F6B, /*U+1F63*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA*/ + 0x1F6C, /*U+1F64*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA*/ + 0x1F6D, /*U+1F65*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA*/ + 0x1F6E, /*U+1F66*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI*/ + 0x1F6F, /*U+1F67*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI*/ + 0x1F68, /*U+1F68*/ /**/ + 0x1F69, /*U+1F69*/ /**/ + 0x1F6A, /*U+1F6A*/ /**/ + 0x1F6B, /*U+1F6B*/ /**/ + 0x1F6C, /*U+1F6C*/ /**/ + 0x1F6D, /*U+1F6D*/ /**/ + 0x1F6E, /*U+1F6E*/ /**/ + 0x1F6F, /*U+1F6F*/ /**/ + 0x1FBA, /*U+1F70*/ /*GREEK SMALL LETTER ALPHA WITH VARIA*/ + 0x1FBB, /*U+1F71*/ /*GREEK SMALL LETTER ALPHA WITH OXIA*/ + 0x1FC8, /*U+1F72*/ /*GREEK SMALL LETTER EPSILON WITH VARIA*/ + 0x1FC9, /*U+1F73*/ /*GREEK SMALL LETTER EPSILON WITH OXIA*/ + 0x1FCA, /*U+1F74*/ /*GREEK SMALL LETTER ETA WITH VARIA*/ + 0x1FCB, /*U+1F75*/ /*GREEK SMALL LETTER ETA WITH OXIA*/ + 0x1FDA, /*U+1F76*/ /*GREEK SMALL LETTER IOTA WITH VARIA*/ + 0x1FDB, /*U+1F77*/ /*GREEK SMALL LETTER IOTA WITH OXIA*/ + 0x1FF8, /*U+1F78*/ /*GREEK SMALL LETTER OMICRON WITH VARIA*/ + 0x1FF9, /*U+1F79*/ /*GREEK SMALL LETTER OMICRON WITH OXIA*/ + 0x1FEA, /*U+1F7A*/ /*GREEK SMALL LETTER UPSILON WITH VARIA*/ + 0x1FEB, /*U+1F7B*/ /*GREEK SMALL LETTER UPSILON WITH OXIA*/ + 0x1FFA, /*U+1F7C*/ /*GREEK SMALL LETTER OMEGA WITH VARIA*/ + 0x1FFB, /*U+1F7D*/ /*GREEK SMALL LETTER OMEGA WITH OXIA*/ + 0x1F7E, /*U+1F7E*/ /**/ + 0x1F7F, /*U+1F7F*/ /**/ + 0x1F88, /*U+1F80*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI*/ + 0x1F89, /*U+1F81*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI*/ + 0x1F8A, /*U+1F82*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI*/ + 0x1F8B, /*U+1F83*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI*/ + 0x1F8C, /*U+1F84*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI*/ + 0x1F8D, /*U+1F85*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI*/ + 0x1F8E, /*U+1F86*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI*/ + 0x1F8F, /*U+1F87*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI*/ + 0x1F88, /*U+1F88*/ /**/ + 0x1F89, /*U+1F89*/ /**/ + 0x1F8A, /*U+1F8A*/ /**/ + 0x1F8B, /*U+1F8B*/ /**/ + 0x1F8C, /*U+1F8C*/ /**/ + 0x1F8D, /*U+1F8D*/ /**/ + 0x1F8E, /*U+1F8E*/ /**/ + 0x1F8F, /*U+1F8F*/ /**/ + 0x1F98, /*U+1F90*/ /*GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI*/ + 0x1F99, /*U+1F91*/ /*GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI*/ + 0x1F9A, /*U+1F92*/ /*GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI*/ + 0x1F9B, /*U+1F93*/ /*GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI*/ + 0x1F9C, /*U+1F94*/ /*GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI*/ + 0x1F9D, /*U+1F95*/ /*GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI*/ + 0x1F9E, /*U+1F96*/ /*GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI*/ + 0x1F9F, /*U+1F97*/ /*GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI*/ + 0x1F98, /*U+1F98*/ /**/ + 0x1F99, /*U+1F99*/ /**/ + 0x1F9A, /*U+1F9A*/ /**/ + 0x1F9B, /*U+1F9B*/ /**/ + 0x1F9C, /*U+1F9C*/ /**/ + 0x1F9D, /*U+1F9D*/ /**/ + 0x1F9E, /*U+1F9E*/ /**/ + 0x1F9F, /*U+1F9F*/ /**/ + 0x1FA8, /*U+1FA0*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI*/ + 0x1FA9, /*U+1FA1*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI*/ + 0x1FAA, /*U+1FA2*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI*/ + 0x1FAB, /*U+1FA3*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI*/ + 0x1FAC, /*U+1FA4*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI*/ + 0x1FAD, /*U+1FA5*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI*/ + 0x1FAE, /*U+1FA6*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI*/ + 0x1FAF, /*U+1FA7*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI*/ + 0x1FA8, /*U+1FA8*/ /**/ + 0x1FA9, /*U+1FA9*/ /**/ + 0x1FAA, /*U+1FAA*/ /**/ + 0x1FAB, /*U+1FAB*/ /**/ + 0x1FAC, /*U+1FAC*/ /**/ + 0x1FAD, /*U+1FAD*/ /**/ + 0x1FAE, /*U+1FAE*/ /**/ + 0x1FAF, /*U+1FAF*/ /**/ + 0x1FB8, /*U+1FB0*/ /*GREEK SMALL LETTER ALPHA WITH VRACHY*/ + 0x1FB9, /*U+1FB1*/ /*GREEK SMALL LETTER ALPHA WITH MACRON*/ + 0x1FB2, /*U+1FB2*/ /**/ + 0x1FBC, /*U+1FB3*/ /*GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI*/ + 0x1FB4, /*U+1FB4*/ /**/ + 0x1FB5, /*U+1FB5*/ /**/ + 0x1FB6, /*U+1FB6*/ /**/ + 0x1FB7, /*U+1FB7*/ /**/ + 0x1FB8, /*U+1FB8*/ /**/ + 0x1FB9, /*U+1FB9*/ /**/ + 0x1FBA, /*U+1FBA*/ /**/ + 0x1FBB, /*U+1FBB*/ /**/ + 0x1FBC, /*U+1FBC*/ /**/ + 0x1FBD, /*U+1FBD*/ /**/ + 0x0399, /*U+1FBE*/ /*GREEK PROSGEGRAMMENI*/ + 0x1FBF, /*U+1FBF*/ /**/ + 0x1FC0, /*U+1FC0*/ /**/ + 0x1FC1, /*U+1FC1*/ /**/ + 0x1FC2, /*U+1FC2*/ /**/ + 0x1FCC, /*U+1FC3*/ /*GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI*/ + 0x1FC4, /*U+1FC4*/ /**/ + 0x1FC5, /*U+1FC5*/ /**/ + 0x1FC6, /*U+1FC6*/ /**/ + 0x1FC7, /*U+1FC7*/ /**/ + 0x1FC8, /*U+1FC8*/ /**/ + 0x1FC9, /*U+1FC9*/ /**/ + 0x1FCA, /*U+1FCA*/ /**/ + 0x1FCB, /*U+1FCB*/ /**/ + 0x1FCC, /*U+1FCC*/ /**/ + 0x1FCD, /*U+1FCD*/ /**/ + 0x1FCE, /*U+1FCE*/ /**/ + 0x1FCF, /*U+1FCF*/ /**/ + 0x1FD8, /*U+1FD0*/ /*GREEK SMALL LETTER IOTA WITH VRACHY*/ + 0x1FD9, /*U+1FD1*/ /*GREEK SMALL LETTER IOTA WITH MACRON*/ + 0x1FD2, /*U+1FD2*/ /**/ + 0x1FD3, /*U+1FD3*/ /**/ + 0x1FD4, /*U+1FD4*/ /**/ + 0x1FD5, /*U+1FD5*/ /**/ + 0x1FD6, /*U+1FD6*/ /**/ + 0x1FD7, /*U+1FD7*/ /**/ + 0x1FD8, /*U+1FD8*/ /**/ + 0x1FD9, /*U+1FD9*/ /**/ + 0x1FDA, /*U+1FDA*/ /**/ + 0x1FDB, /*U+1FDB*/ /**/ + 0x1FDC, /*U+1FDC*/ /**/ + 0x1FDD, /*U+1FDD*/ /**/ + 0x1FDE, /*U+1FDE*/ /**/ + 0x1FDF, /*U+1FDF*/ /**/ + 0x1FE8, /*U+1FE0*/ /*GREEK SMALL LETTER UPSILON WITH VRACHY*/ + 0x1FE9, /*U+1FE1*/ /*GREEK SMALL LETTER UPSILON WITH MACRON*/ + 0x1FE2, /*U+1FE2*/ /**/ + 0x1FE3, /*U+1FE3*/ /**/ + 0x1FE4, /*U+1FE4*/ /**/ + 0x1FEC, /*U+1FE5*/ /*GREEK SMALL LETTER RHO WITH DASIA*/ + 0x1FE6, /*U+1FE6*/ /**/ + 0x1FE7, /*U+1FE7*/ /**/ + 0x1FE8, /*U+1FE8*/ /**/ + 0x1FE9, /*U+1FE9*/ /**/ + 0x1FEA, /*U+1FEA*/ /**/ + 0x1FEB, /*U+1FEB*/ /**/ + 0x1FEC, /*U+1FEC*/ /**/ + 0x1FED, /*U+1FED*/ /**/ + 0x1FEE, /*U+1FEE*/ /**/ + 0x1FEF, /*U+1FEF*/ /**/ + 0x1FF0, /*U+1FF0*/ /**/ + 0x1FF1, /*U+1FF1*/ /**/ + 0x1FF2, /*U+1FF2*/ /**/ + 0x1FFC, /*U+1FF3*/ /*GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI*/ + 0x1FF4, /*U+1FF4*/ /**/ + 0x1FF5, /*U+1FF5*/ /**/ + 0x1FF6, /*U+1FF6*/ /**/ + 0x1FF7, /*U+1FF7*/ /**/ + 0x1FF8, /*U+1FF8*/ /**/ + 0x1FF9, /*U+1FF9*/ /**/ + 0x1FFA, /*U+1FFA*/ /**/ + 0x1FFB, /*U+1FFB*/ /**/ + 0x1FFC, /*U+1FFC*/ /**/ + 0x1FFD, /*U+1FFD*/ /**/ + 0x1FFE, /*U+1FFE*/ /**/ + 0x1FFF, /*U+1FFF*/ /**/ +}; + +static const uint16_t upper_table_5[128] = { + 0x2140, /*U+2140*/ /**/ + 0x2141, /*U+2141*/ /**/ + 0x2142, /*U+2142*/ /**/ + 0x2143, /*U+2143*/ /**/ + 0x2144, /*U+2144*/ /**/ + 0x2145, /*U+2145*/ /**/ + 0x2146, /*U+2146*/ /**/ + 0x2147, /*U+2147*/ /**/ + 0x2148, /*U+2148*/ /**/ + 0x2149, /*U+2149*/ /**/ + 0x214A, /*U+214A*/ /**/ + 0x214B, /*U+214B*/ /**/ + 0x214C, /*U+214C*/ /**/ + 0x214D, /*U+214D*/ /**/ + 0x2132, /*U+214E*/ /*TURNED SMALL F*/ + 0x214F, /*U+214F*/ /**/ + 0x2150, /*U+2150*/ /**/ + 0x2151, /*U+2151*/ /**/ + 0x2152, /*U+2152*/ /**/ + 0x2153, /*U+2153*/ /**/ + 0x2154, /*U+2154*/ /**/ + 0x2155, /*U+2155*/ /**/ + 0x2156, /*U+2156*/ /**/ + 0x2157, /*U+2157*/ /**/ + 0x2158, /*U+2158*/ /**/ + 0x2159, /*U+2159*/ /**/ + 0x215A, /*U+215A*/ /**/ + 0x215B, /*U+215B*/ /**/ + 0x215C, /*U+215C*/ /**/ + 0x215D, /*U+215D*/ /**/ + 0x215E, /*U+215E*/ /**/ + 0x215F, /*U+215F*/ /**/ + 0x2160, /*U+2160*/ /**/ + 0x2161, /*U+2161*/ /**/ + 0x2162, /*U+2162*/ /**/ + 0x2163, /*U+2163*/ /**/ + 0x2164, /*U+2164*/ /**/ + 0x2165, /*U+2165*/ /**/ + 0x2166, /*U+2166*/ /**/ + 0x2167, /*U+2167*/ /**/ + 0x2168, /*U+2168*/ /**/ + 0x2169, /*U+2169*/ /**/ + 0x216A, /*U+216A*/ /**/ + 0x216B, /*U+216B*/ /**/ + 0x216C, /*U+216C*/ /**/ + 0x216D, /*U+216D*/ /**/ + 0x216E, /*U+216E*/ /**/ + 0x216F, /*U+216F*/ /**/ + 0x2160, /*U+2170*/ /*SMALL ROMAN NUMERAL ONE*/ + 0x2161, /*U+2171*/ /*SMALL ROMAN NUMERAL TWO*/ + 0x2162, /*U+2172*/ /*SMALL ROMAN NUMERAL THREE*/ + 0x2163, /*U+2173*/ /*SMALL ROMAN NUMERAL FOUR*/ + 0x2164, /*U+2174*/ /*SMALL ROMAN NUMERAL FIVE*/ + 0x2165, /*U+2175*/ /*SMALL ROMAN NUMERAL SIX*/ + 0x2166, /*U+2176*/ /*SMALL ROMAN NUMERAL SEVEN*/ + 0x2167, /*U+2177*/ /*SMALL ROMAN NUMERAL EIGHT*/ + 0x2168, /*U+2178*/ /*SMALL ROMAN NUMERAL NINE*/ + 0x2169, /*U+2179*/ /*SMALL ROMAN NUMERAL TEN*/ + 0x216A, /*U+217A*/ /*SMALL ROMAN NUMERAL ELEVEN*/ + 0x216B, /*U+217B*/ /*SMALL ROMAN NUMERAL TWELVE*/ + 0x216C, /*U+217C*/ /*SMALL ROMAN NUMERAL FIFTY*/ + 0x216D, /*U+217D*/ /*SMALL ROMAN NUMERAL ONE HUNDRED*/ + 0x216E, /*U+217E*/ /*SMALL ROMAN NUMERAL FIVE HUNDRED*/ + 0x216F, /*U+217F*/ /*SMALL ROMAN NUMERAL ONE THOUSAND*/ + 0x2180, /*U+2180*/ /**/ + 0x2181, /*U+2181*/ /**/ + 0x2182, /*U+2182*/ /**/ + 0x2183, /*U+2183*/ /**/ + 0x2183, /*U+2184*/ /*LATIN SMALL LETTER REVERSED C*/ + 0x2185, /*U+2185*/ /**/ + 0x2186, /*U+2186*/ /**/ + 0x2187, /*U+2187*/ /**/ + 0x2188, /*U+2188*/ /**/ + 0x2189, /*U+2189*/ /**/ + 0x218A, /*U+218A*/ /**/ + 0x218B, /*U+218B*/ /**/ + 0x218C, /*U+218C*/ /**/ + 0x218D, /*U+218D*/ /**/ + 0x218E, /*U+218E*/ /**/ + 0x218F, /*U+218F*/ /**/ + 0x2190, /*U+2190*/ /**/ + 0x2191, /*U+2191*/ /**/ + 0x2192, /*U+2192*/ /**/ + 0x2193, /*U+2193*/ /**/ + 0x2194, /*U+2194*/ /**/ + 0x2195, /*U+2195*/ /**/ + 0x2196, /*U+2196*/ /**/ + 0x2197, /*U+2197*/ /**/ + 0x2198, /*U+2198*/ /**/ + 0x2199, /*U+2199*/ /**/ + 0x219A, /*U+219A*/ /**/ + 0x219B, /*U+219B*/ /**/ + 0x219C, /*U+219C*/ /**/ + 0x219D, /*U+219D*/ /**/ + 0x219E, /*U+219E*/ /**/ + 0x219F, /*U+219F*/ /**/ + 0x21A0, /*U+21A0*/ /**/ + 0x21A1, /*U+21A1*/ /**/ + 0x21A2, /*U+21A2*/ /**/ + 0x21A3, /*U+21A3*/ /**/ + 0x21A4, /*U+21A4*/ /**/ + 0x21A5, /*U+21A5*/ /**/ + 0x21A6, /*U+21A6*/ /**/ + 0x21A7, /*U+21A7*/ /**/ + 0x21A8, /*U+21A8*/ /**/ + 0x21A9, /*U+21A9*/ /**/ + 0x21AA, /*U+21AA*/ /**/ + 0x21AB, /*U+21AB*/ /**/ + 0x21AC, /*U+21AC*/ /**/ + 0x21AD, /*U+21AD*/ /**/ + 0x21AE, /*U+21AE*/ /**/ + 0x21AF, /*U+21AF*/ /**/ + 0x21B0, /*U+21B0*/ /**/ + 0x21B1, /*U+21B1*/ /**/ + 0x21B2, /*U+21B2*/ /**/ + 0x21B3, /*U+21B3*/ /**/ + 0x21B4, /*U+21B4*/ /**/ + 0x21B5, /*U+21B5*/ /**/ + 0x21B6, /*U+21B6*/ /**/ + 0x21B7, /*U+21B7*/ /**/ + 0x21B8, /*U+21B8*/ /**/ + 0x21B9, /*U+21B9*/ /**/ + 0x21BA, /*U+21BA*/ /**/ + 0x21BB, /*U+21BB*/ /**/ + 0x21BC, /*U+21BC*/ /**/ + 0x21BD, /*U+21BD*/ /**/ + 0x21BE, /*U+21BE*/ /**/ + 0x21BF, /*U+21BF*/ /**/ +}; + +static const uint16_t upper_table_6[64] = { + 0x24C0, /*U+24C0*/ /**/ + 0x24C1, /*U+24C1*/ /**/ + 0x24C2, /*U+24C2*/ /**/ + 0x24C3, /*U+24C3*/ /**/ + 0x24C4, /*U+24C4*/ /**/ + 0x24C5, /*U+24C5*/ /**/ + 0x24C6, /*U+24C6*/ /**/ + 0x24C7, /*U+24C7*/ /**/ + 0x24C8, /*U+24C8*/ /**/ + 0x24C9, /*U+24C9*/ /**/ + 0x24CA, /*U+24CA*/ /**/ + 0x24CB, /*U+24CB*/ /**/ + 0x24CC, /*U+24CC*/ /**/ + 0x24CD, /*U+24CD*/ /**/ + 0x24CE, /*U+24CE*/ /**/ + 0x24CF, /*U+24CF*/ /**/ + 0x24B6, /*U+24D0*/ /*CIRCLED LATIN SMALL LETTER A*/ + 0x24B7, /*U+24D1*/ /*CIRCLED LATIN SMALL LETTER B*/ + 0x24B8, /*U+24D2*/ /*CIRCLED LATIN SMALL LETTER C*/ + 0x24B9, /*U+24D3*/ /*CIRCLED LATIN SMALL LETTER D*/ + 0x24BA, /*U+24D4*/ /*CIRCLED LATIN SMALL LETTER E*/ + 0x24BB, /*U+24D5*/ /*CIRCLED LATIN SMALL LETTER F*/ + 0x24BC, /*U+24D6*/ /*CIRCLED LATIN SMALL LETTER G*/ + 0x24BD, /*U+24D7*/ /*CIRCLED LATIN SMALL LETTER H*/ + 0x24BE, /*U+24D8*/ /*CIRCLED LATIN SMALL LETTER I*/ + 0x24BF, /*U+24D9*/ /*CIRCLED LATIN SMALL LETTER J*/ + 0x24C0, /*U+24DA*/ /*CIRCLED LATIN SMALL LETTER K*/ + 0x24C1, /*U+24DB*/ /*CIRCLED LATIN SMALL LETTER L*/ + 0x24C2, /*U+24DC*/ /*CIRCLED LATIN SMALL LETTER M*/ + 0x24C3, /*U+24DD*/ /*CIRCLED LATIN SMALL LETTER N*/ + 0x24C4, /*U+24DE*/ /*CIRCLED LATIN SMALL LETTER O*/ + 0x24C5, /*U+24DF*/ /*CIRCLED LATIN SMALL LETTER P*/ + 0x24C6, /*U+24E0*/ /*CIRCLED LATIN SMALL LETTER Q*/ + 0x24C7, /*U+24E1*/ /*CIRCLED LATIN SMALL LETTER R*/ + 0x24C8, /*U+24E2*/ /*CIRCLED LATIN SMALL LETTER S*/ + 0x24C9, /*U+24E3*/ /*CIRCLED LATIN SMALL LETTER T*/ + 0x24CA, /*U+24E4*/ /*CIRCLED LATIN SMALL LETTER U*/ + 0x24CB, /*U+24E5*/ /*CIRCLED LATIN SMALL LETTER V*/ + 0x24CC, /*U+24E6*/ /*CIRCLED LATIN SMALL LETTER W*/ + 0x24CD, /*U+24E7*/ /*CIRCLED LATIN SMALL LETTER X*/ + 0x24CE, /*U+24E8*/ /*CIRCLED LATIN SMALL LETTER Y*/ + 0x24CF, /*U+24E9*/ /*CIRCLED LATIN SMALL LETTER Z*/ + 0x24EA, /*U+24EA*/ /**/ + 0x24EB, /*U+24EB*/ /**/ + 0x24EC, /*U+24EC*/ /**/ + 0x24ED, /*U+24ED*/ /**/ + 0x24EE, /*U+24EE*/ /**/ + 0x24EF, /*U+24EF*/ /**/ + 0x24F0, /*U+24F0*/ /**/ + 0x24F1, /*U+24F1*/ /**/ + 0x24F2, /*U+24F2*/ /**/ + 0x24F3, /*U+24F3*/ /**/ + 0x24F4, /*U+24F4*/ /**/ + 0x24F5, /*U+24F5*/ /**/ + 0x24F6, /*U+24F6*/ /**/ + 0x24F7, /*U+24F7*/ /**/ + 0x24F8, /*U+24F8*/ /**/ + 0x24F9, /*U+24F9*/ /**/ + 0x24FA, /*U+24FA*/ /**/ + 0x24FB, /*U+24FB*/ /**/ + 0x24FC, /*U+24FC*/ /**/ + 0x24FD, /*U+24FD*/ /**/ + 0x24FE, /*U+24FE*/ /**/ + 0x24FF, /*U+24FF*/ /**/ +}; + +static const uint16_t upper_table_7[320] = { + 0x2C00, /*U+2C00*/ /**/ + 0x2C01, /*U+2C01*/ /**/ + 0x2C02, /*U+2C02*/ /**/ + 0x2C03, /*U+2C03*/ /**/ + 0x2C04, /*U+2C04*/ /**/ + 0x2C05, /*U+2C05*/ /**/ + 0x2C06, /*U+2C06*/ /**/ + 0x2C07, /*U+2C07*/ /**/ + 0x2C08, /*U+2C08*/ /**/ + 0x2C09, /*U+2C09*/ /**/ + 0x2C0A, /*U+2C0A*/ /**/ + 0x2C0B, /*U+2C0B*/ /**/ + 0x2C0C, /*U+2C0C*/ /**/ + 0x2C0D, /*U+2C0D*/ /**/ + 0x2C0E, /*U+2C0E*/ /**/ + 0x2C0F, /*U+2C0F*/ /**/ + 0x2C10, /*U+2C10*/ /**/ + 0x2C11, /*U+2C11*/ /**/ + 0x2C12, /*U+2C12*/ /**/ + 0x2C13, /*U+2C13*/ /**/ + 0x2C14, /*U+2C14*/ /**/ + 0x2C15, /*U+2C15*/ /**/ + 0x2C16, /*U+2C16*/ /**/ + 0x2C17, /*U+2C17*/ /**/ + 0x2C18, /*U+2C18*/ /**/ + 0x2C19, /*U+2C19*/ /**/ + 0x2C1A, /*U+2C1A*/ /**/ + 0x2C1B, /*U+2C1B*/ /**/ + 0x2C1C, /*U+2C1C*/ /**/ + 0x2C1D, /*U+2C1D*/ /**/ + 0x2C1E, /*U+2C1E*/ /**/ + 0x2C1F, /*U+2C1F*/ /**/ + 0x2C20, /*U+2C20*/ /**/ + 0x2C21, /*U+2C21*/ /**/ + 0x2C22, /*U+2C22*/ /**/ + 0x2C23, /*U+2C23*/ /**/ + 0x2C24, /*U+2C24*/ /**/ + 0x2C25, /*U+2C25*/ /**/ + 0x2C26, /*U+2C26*/ /**/ + 0x2C27, /*U+2C27*/ /**/ + 0x2C28, /*U+2C28*/ /**/ + 0x2C29, /*U+2C29*/ /**/ + 0x2C2A, /*U+2C2A*/ /**/ + 0x2C2B, /*U+2C2B*/ /**/ + 0x2C2C, /*U+2C2C*/ /**/ + 0x2C2D, /*U+2C2D*/ /**/ + 0x2C2E, /*U+2C2E*/ /**/ + 0x2C2F, /*U+2C2F*/ /**/ + 0x2C00, /*U+2C30*/ /*GLAGOLITIC SMALL LETTER AZU*/ + 0x2C01, /*U+2C31*/ /*GLAGOLITIC SMALL LETTER BUKY*/ + 0x2C02, /*U+2C32*/ /*GLAGOLITIC SMALL LETTER VEDE*/ + 0x2C03, /*U+2C33*/ /*GLAGOLITIC SMALL LETTER GLAGOLI*/ + 0x2C04, /*U+2C34*/ /*GLAGOLITIC SMALL LETTER DOBRO*/ + 0x2C05, /*U+2C35*/ /*GLAGOLITIC SMALL LETTER YESTU*/ + 0x2C06, /*U+2C36*/ /*GLAGOLITIC SMALL LETTER ZHIVETE*/ + 0x2C07, /*U+2C37*/ /*GLAGOLITIC SMALL LETTER DZELO*/ + 0x2C08, /*U+2C38*/ /*GLAGOLITIC SMALL LETTER ZEMLJA*/ + 0x2C09, /*U+2C39*/ /*GLAGOLITIC SMALL LETTER IZHE*/ + 0x2C0A, /*U+2C3A*/ /*GLAGOLITIC SMALL LETTER INITIAL IZHE*/ + 0x2C0B, /*U+2C3B*/ /*GLAGOLITIC SMALL LETTER I*/ + 0x2C0C, /*U+2C3C*/ /*GLAGOLITIC SMALL LETTER DJERVI*/ + 0x2C0D, /*U+2C3D*/ /*GLAGOLITIC SMALL LETTER KAKO*/ + 0x2C0E, /*U+2C3E*/ /*GLAGOLITIC SMALL LETTER LJUDIJE*/ + 0x2C0F, /*U+2C3F*/ /*GLAGOLITIC SMALL LETTER MYSLITE*/ + 0x2C10, /*U+2C40*/ /*GLAGOLITIC SMALL LETTER NASHI*/ + 0x2C11, /*U+2C41*/ /*GLAGOLITIC SMALL LETTER ONU*/ + 0x2C12, /*U+2C42*/ /*GLAGOLITIC SMALL LETTER POKOJI*/ + 0x2C13, /*U+2C43*/ /*GLAGOLITIC SMALL LETTER RITSI*/ + 0x2C14, /*U+2C44*/ /*GLAGOLITIC SMALL LETTER SLOVO*/ + 0x2C15, /*U+2C45*/ /*GLAGOLITIC SMALL LETTER TVRIDO*/ + 0x2C16, /*U+2C46*/ /*GLAGOLITIC SMALL LETTER UKU*/ + 0x2C17, /*U+2C47*/ /*GLAGOLITIC SMALL LETTER FRITU*/ + 0x2C18, /*U+2C48*/ /*GLAGOLITIC SMALL LETTER HERU*/ + 0x2C19, /*U+2C49*/ /*GLAGOLITIC SMALL LETTER OTU*/ + 0x2C1A, /*U+2C4A*/ /*GLAGOLITIC SMALL LETTER PE*/ + 0x2C1B, /*U+2C4B*/ /*GLAGOLITIC SMALL LETTER SHTA*/ + 0x2C1C, /*U+2C4C*/ /*GLAGOLITIC SMALL LETTER TSI*/ + 0x2C1D, /*U+2C4D*/ /*GLAGOLITIC SMALL LETTER CHRIVI*/ + 0x2C1E, /*U+2C4E*/ /*GLAGOLITIC SMALL LETTER SHA*/ + 0x2C1F, /*U+2C4F*/ /*GLAGOLITIC SMALL LETTER YERU*/ + 0x2C20, /*U+2C50*/ /*GLAGOLITIC SMALL LETTER YERI*/ + 0x2C21, /*U+2C51*/ /*GLAGOLITIC SMALL LETTER YATI*/ + 0x2C22, /*U+2C52*/ /*GLAGOLITIC SMALL LETTER SPIDERY HA*/ + 0x2C23, /*U+2C53*/ /*GLAGOLITIC SMALL LETTER YU*/ + 0x2C24, /*U+2C54*/ /*GLAGOLITIC SMALL LETTER SMALL YUS*/ + 0x2C25, /*U+2C55*/ /*GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL*/ + 0x2C26, /*U+2C56*/ /*GLAGOLITIC SMALL LETTER YO*/ + 0x2C27, /*U+2C57*/ /*GLAGOLITIC SMALL LETTER IOTATED SMALL YUS*/ + 0x2C28, /*U+2C58*/ /*GLAGOLITIC SMALL LETTER BIG YUS*/ + 0x2C29, /*U+2C59*/ /*GLAGOLITIC SMALL LETTER IOTATED BIG YUS*/ + 0x2C2A, /*U+2C5A*/ /*GLAGOLITIC SMALL LETTER FITA*/ + 0x2C2B, /*U+2C5B*/ /*GLAGOLITIC SMALL LETTER IZHITSA*/ + 0x2C2C, /*U+2C5C*/ /*GLAGOLITIC SMALL LETTER SHTAPIC*/ + 0x2C2D, /*U+2C5D*/ /*GLAGOLITIC SMALL LETTER TROKUTASTI A*/ + 0x2C2E, /*U+2C5E*/ /*GLAGOLITIC SMALL LETTER LATINATE MYSLITE*/ + 0x2C5F, /*U+2C5F*/ /**/ + 0x2C60, /*U+2C60*/ /**/ + 0x2C60, /*U+2C61*/ /*LATIN SMALL LETTER L WITH DOUBLE BAR*/ + 0x2C62, /*U+2C62*/ /**/ + 0x2C63, /*U+2C63*/ /**/ + 0x2C64, /*U+2C64*/ /**/ + 0x023A, /*U+2C65*/ /*LATIN SMALL LETTER A WITH STROKE*/ + 0x023E, /*U+2C66*/ /*LATIN SMALL LETTER T WITH DIAGONAL STROKE*/ + 0x2C67, /*U+2C67*/ /**/ + 0x2C67, /*U+2C68*/ /*LATIN SMALL LETTER H WITH DESCENDER*/ + 0x2C69, /*U+2C69*/ /**/ + 0x2C69, /*U+2C6A*/ /*LATIN SMALL LETTER K WITH DESCENDER*/ + 0x2C6B, /*U+2C6B*/ /**/ + 0x2C6B, /*U+2C6C*/ /*LATIN SMALL LETTER Z WITH DESCENDER*/ + 0x2C6D, /*U+2C6D*/ /**/ + 0x2C6E, /*U+2C6E*/ /**/ + 0x2C6F, /*U+2C6F*/ /**/ + 0x2C70, /*U+2C70*/ /**/ + 0x2C71, /*U+2C71*/ /**/ + 0x2C72, /*U+2C72*/ /**/ + 0x2C72, /*U+2C73*/ /*LATIN SMALL LETTER W WITH HOOK*/ + 0x2C74, /*U+2C74*/ /**/ + 0x2C75, /*U+2C75*/ /**/ + 0x2C75, /*U+2C76*/ /*LATIN SMALL LETTER HALF H*/ + 0x2C77, /*U+2C77*/ /**/ + 0x2C78, /*U+2C78*/ /**/ + 0x2C79, /*U+2C79*/ /**/ + 0x2C7A, /*U+2C7A*/ /**/ + 0x2C7B, /*U+2C7B*/ /**/ + 0x2C7C, /*U+2C7C*/ /**/ + 0x2C7D, /*U+2C7D*/ /**/ + 0x2C7E, /*U+2C7E*/ /**/ + 0x2C7F, /*U+2C7F*/ /**/ + 0x2C80, /*U+2C80*/ /**/ + 0x2C80, /*U+2C81*/ /*COPTIC SMALL LETTER ALFA*/ + 0x2C82, /*U+2C82*/ /**/ + 0x2C82, /*U+2C83*/ /*COPTIC SMALL LETTER VIDA*/ + 0x2C84, /*U+2C84*/ /**/ + 0x2C84, /*U+2C85*/ /*COPTIC SMALL LETTER GAMMA*/ + 0x2C86, /*U+2C86*/ /**/ + 0x2C86, /*U+2C87*/ /*COPTIC SMALL LETTER DALDA*/ + 0x2C88, /*U+2C88*/ /**/ + 0x2C88, /*U+2C89*/ /*COPTIC SMALL LETTER EIE*/ + 0x2C8A, /*U+2C8A*/ /**/ + 0x2C8A, /*U+2C8B*/ /*COPTIC SMALL LETTER SOU*/ + 0x2C8C, /*U+2C8C*/ /**/ + 0x2C8C, /*U+2C8D*/ /*COPTIC SMALL LETTER ZATA*/ + 0x2C8E, /*U+2C8E*/ /**/ + 0x2C8E, /*U+2C8F*/ /*COPTIC SMALL LETTER HATE*/ + 0x2C90, /*U+2C90*/ /**/ + 0x2C90, /*U+2C91*/ /*COPTIC SMALL LETTER THETHE*/ + 0x2C92, /*U+2C92*/ /**/ + 0x2C92, /*U+2C93*/ /*COPTIC SMALL LETTER IAUDA*/ + 0x2C94, /*U+2C94*/ /**/ + 0x2C94, /*U+2C95*/ /*COPTIC SMALL LETTER KAPA*/ + 0x2C96, /*U+2C96*/ /**/ + 0x2C96, /*U+2C97*/ /*COPTIC SMALL LETTER LAULA*/ + 0x2C98, /*U+2C98*/ /**/ + 0x2C98, /*U+2C99*/ /*COPTIC SMALL LETTER MI*/ + 0x2C9A, /*U+2C9A*/ /**/ + 0x2C9A, /*U+2C9B*/ /*COPTIC SMALL LETTER NI*/ + 0x2C9C, /*U+2C9C*/ /**/ + 0x2C9C, /*U+2C9D*/ /*COPTIC SMALL LETTER KSI*/ + 0x2C9E, /*U+2C9E*/ /**/ + 0x2C9E, /*U+2C9F*/ /*COPTIC SMALL LETTER O*/ + 0x2CA0, /*U+2CA0*/ /**/ + 0x2CA0, /*U+2CA1*/ /*COPTIC SMALL LETTER PI*/ + 0x2CA2, /*U+2CA2*/ /**/ + 0x2CA2, /*U+2CA3*/ /*COPTIC SMALL LETTER RO*/ + 0x2CA4, /*U+2CA4*/ /**/ + 0x2CA4, /*U+2CA5*/ /*COPTIC SMALL LETTER SIMA*/ + 0x2CA6, /*U+2CA6*/ /**/ + 0x2CA6, /*U+2CA7*/ /*COPTIC SMALL LETTER TAU*/ + 0x2CA8, /*U+2CA8*/ /**/ + 0x2CA8, /*U+2CA9*/ /*COPTIC SMALL LETTER UA*/ + 0x2CAA, /*U+2CAA*/ /**/ + 0x2CAA, /*U+2CAB*/ /*COPTIC SMALL LETTER FI*/ + 0x2CAC, /*U+2CAC*/ /**/ + 0x2CAC, /*U+2CAD*/ /*COPTIC SMALL LETTER KHI*/ + 0x2CAE, /*U+2CAE*/ /**/ + 0x2CAE, /*U+2CAF*/ /*COPTIC SMALL LETTER PSI*/ + 0x2CB0, /*U+2CB0*/ /**/ + 0x2CB0, /*U+2CB1*/ /*COPTIC SMALL LETTER OOU*/ + 0x2CB2, /*U+2CB2*/ /**/ + 0x2CB2, /*U+2CB3*/ /*COPTIC SMALL LETTER DIALECT-P ALEF*/ + 0x2CB4, /*U+2CB4*/ /**/ + 0x2CB4, /*U+2CB5*/ /*COPTIC SMALL LETTER OLD COPTIC AIN*/ + 0x2CB6, /*U+2CB6*/ /**/ + 0x2CB6, /*U+2CB7*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC EIE*/ + 0x2CB8, /*U+2CB8*/ /**/ + 0x2CB8, /*U+2CB9*/ /*COPTIC SMALL LETTER DIALECT-P KAPA*/ + 0x2CBA, /*U+2CBA*/ /**/ + 0x2CBA, /*U+2CBB*/ /*COPTIC SMALL LETTER DIALECT-P NI*/ + 0x2CBC, /*U+2CBC*/ /**/ + 0x2CBC, /*U+2CBD*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC NI*/ + 0x2CBE, /*U+2CBE*/ /**/ + 0x2CBE, /*U+2CBF*/ /*COPTIC SMALL LETTER OLD COPTIC OOU*/ + 0x2CC0, /*U+2CC0*/ /**/ + 0x2CC0, /*U+2CC1*/ /*COPTIC SMALL LETTER SAMPI*/ + 0x2CC2, /*U+2CC2*/ /**/ + 0x2CC2, /*U+2CC3*/ /*COPTIC SMALL LETTER CROSSED SHEI*/ + 0x2CC4, /*U+2CC4*/ /**/ + 0x2CC4, /*U+2CC5*/ /*COPTIC SMALL LETTER OLD COPTIC SHEI*/ + 0x2CC6, /*U+2CC6*/ /**/ + 0x2CC6, /*U+2CC7*/ /*COPTIC SMALL LETTER OLD COPTIC ESH*/ + 0x2CC8, /*U+2CC8*/ /**/ + 0x2CC8, /*U+2CC9*/ /*COPTIC SMALL LETTER AKHMIMIC KHEI*/ + 0x2CCA, /*U+2CCA*/ /**/ + 0x2CCA, /*U+2CCB*/ /*COPTIC SMALL LETTER DIALECT-P HORI*/ + 0x2CCC, /*U+2CCC*/ /**/ + 0x2CCC, /*U+2CCD*/ /*COPTIC SMALL LETTER OLD COPTIC HORI*/ + 0x2CCE, /*U+2CCE*/ /**/ + 0x2CCE, /*U+2CCF*/ /*COPTIC SMALL LETTER OLD COPTIC HA*/ + 0x2CD0, /*U+2CD0*/ /**/ + 0x2CD0, /*U+2CD1*/ /*COPTIC SMALL LETTER L-SHAPED HA*/ + 0x2CD2, /*U+2CD2*/ /**/ + 0x2CD2, /*U+2CD3*/ /*COPTIC SMALL LETTER OLD COPTIC HEI*/ + 0x2CD4, /*U+2CD4*/ /**/ + 0x2CD4, /*U+2CD5*/ /*COPTIC SMALL LETTER OLD COPTIC HAT*/ + 0x2CD6, /*U+2CD6*/ /**/ + 0x2CD6, /*U+2CD7*/ /*COPTIC SMALL LETTER OLD COPTIC GANGIA*/ + 0x2CD8, /*U+2CD8*/ /**/ + 0x2CD8, /*U+2CD9*/ /*COPTIC SMALL LETTER OLD COPTIC DJA*/ + 0x2CDA, /*U+2CDA*/ /**/ + 0x2CDA, /*U+2CDB*/ /*COPTIC SMALL LETTER OLD COPTIC SHIMA*/ + 0x2CDC, /*U+2CDC*/ /**/ + 0x2CDC, /*U+2CDD*/ /*COPTIC SMALL LETTER OLD NUBIAN SHIMA*/ + 0x2CDE, /*U+2CDE*/ /**/ + 0x2CDE, /*U+2CDF*/ /*COPTIC SMALL LETTER OLD NUBIAN NGI*/ + 0x2CE0, /*U+2CE0*/ /**/ + 0x2CE0, /*U+2CE1*/ /*COPTIC SMALL LETTER OLD NUBIAN NYI*/ + 0x2CE2, /*U+2CE2*/ /**/ + 0x2CE2, /*U+2CE3*/ /*COPTIC SMALL LETTER OLD NUBIAN WAU*/ + 0x2CE4, /*U+2CE4*/ /**/ + 0x2CE5, /*U+2CE5*/ /**/ + 0x2CE6, /*U+2CE6*/ /**/ + 0x2CE7, /*U+2CE7*/ /**/ + 0x2CE8, /*U+2CE8*/ /**/ + 0x2CE9, /*U+2CE9*/ /**/ + 0x2CEA, /*U+2CEA*/ /**/ + 0x2CEB, /*U+2CEB*/ /**/ + 0x2CEB, /*U+2CEC*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI*/ + 0x2CED, /*U+2CED*/ /**/ + 0x2CED, /*U+2CEE*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA*/ + 0x2CEF, /*U+2CEF*/ /**/ + 0x2CF0, /*U+2CF0*/ /**/ + 0x2CF1, /*U+2CF1*/ /**/ + 0x2CF2, /*U+2CF2*/ /**/ + 0x2CF2, /*U+2CF3*/ /*COPTIC SMALL LETTER BOHAIRIC KHEI*/ + 0x2CF4, /*U+2CF4*/ /**/ + 0x2CF5, /*U+2CF5*/ /**/ + 0x2CF6, /*U+2CF6*/ /**/ + 0x2CF7, /*U+2CF7*/ /**/ + 0x2CF8, /*U+2CF8*/ /**/ + 0x2CF9, /*U+2CF9*/ /**/ + 0x2CFA, /*U+2CFA*/ /**/ + 0x2CFB, /*U+2CFB*/ /**/ + 0x2CFC, /*U+2CFC*/ /**/ + 0x2CFD, /*U+2CFD*/ /**/ + 0x2CFE, /*U+2CFE*/ /**/ + 0x2CFF, /*U+2CFF*/ /**/ + 0x10A0, /*U+2D00*/ /*GEORGIAN SMALL LETTER AN*/ + 0x10A1, /*U+2D01*/ /*GEORGIAN SMALL LETTER BAN*/ + 0x10A2, /*U+2D02*/ /*GEORGIAN SMALL LETTER GAN*/ + 0x10A3, /*U+2D03*/ /*GEORGIAN SMALL LETTER DON*/ + 0x10A4, /*U+2D04*/ /*GEORGIAN SMALL LETTER EN*/ + 0x10A5, /*U+2D05*/ /*GEORGIAN SMALL LETTER VIN*/ + 0x10A6, /*U+2D06*/ /*GEORGIAN SMALL LETTER ZEN*/ + 0x10A7, /*U+2D07*/ /*GEORGIAN SMALL LETTER TAN*/ + 0x10A8, /*U+2D08*/ /*GEORGIAN SMALL LETTER IN*/ + 0x10A9, /*U+2D09*/ /*GEORGIAN SMALL LETTER KAN*/ + 0x10AA, /*U+2D0A*/ /*GEORGIAN SMALL LETTER LAS*/ + 0x10AB, /*U+2D0B*/ /*GEORGIAN SMALL LETTER MAN*/ + 0x10AC, /*U+2D0C*/ /*GEORGIAN SMALL LETTER NAR*/ + 0x10AD, /*U+2D0D*/ /*GEORGIAN SMALL LETTER ON*/ + 0x10AE, /*U+2D0E*/ /*GEORGIAN SMALL LETTER PAR*/ + 0x10AF, /*U+2D0F*/ /*GEORGIAN SMALL LETTER ZHAR*/ + 0x10B0, /*U+2D10*/ /*GEORGIAN SMALL LETTER RAE*/ + 0x10B1, /*U+2D11*/ /*GEORGIAN SMALL LETTER SAN*/ + 0x10B2, /*U+2D12*/ /*GEORGIAN SMALL LETTER TAR*/ + 0x10B3, /*U+2D13*/ /*GEORGIAN SMALL LETTER UN*/ + 0x10B4, /*U+2D14*/ /*GEORGIAN SMALL LETTER PHAR*/ + 0x10B5, /*U+2D15*/ /*GEORGIAN SMALL LETTER KHAR*/ + 0x10B6, /*U+2D16*/ /*GEORGIAN SMALL LETTER GHAN*/ + 0x10B7, /*U+2D17*/ /*GEORGIAN SMALL LETTER QAR*/ + 0x10B8, /*U+2D18*/ /*GEORGIAN SMALL LETTER SHIN*/ + 0x10B9, /*U+2D19*/ /*GEORGIAN SMALL LETTER CHIN*/ + 0x10BA, /*U+2D1A*/ /*GEORGIAN SMALL LETTER CAN*/ + 0x10BB, /*U+2D1B*/ /*GEORGIAN SMALL LETTER JIL*/ + 0x10BC, /*U+2D1C*/ /*GEORGIAN SMALL LETTER CIL*/ + 0x10BD, /*U+2D1D*/ /*GEORGIAN SMALL LETTER CHAR*/ + 0x10BE, /*U+2D1E*/ /*GEORGIAN SMALL LETTER XAN*/ + 0x10BF, /*U+2D1F*/ /*GEORGIAN SMALL LETTER JHAN*/ + 0x10C0, /*U+2D20*/ /*GEORGIAN SMALL LETTER HAE*/ + 0x10C1, /*U+2D21*/ /*GEORGIAN SMALL LETTER HE*/ + 0x10C2, /*U+2D22*/ /*GEORGIAN SMALL LETTER HIE*/ + 0x10C3, /*U+2D23*/ /*GEORGIAN SMALL LETTER WE*/ + 0x10C4, /*U+2D24*/ /*GEORGIAN SMALL LETTER HAR*/ + 0x10C5, /*U+2D25*/ /*GEORGIAN SMALL LETTER HOE*/ + 0x2D26, /*U+2D26*/ /**/ + 0x10C7, /*U+2D27*/ /*GEORGIAN SMALL LETTER YN*/ + 0x2D28, /*U+2D28*/ /**/ + 0x2D29, /*U+2D29*/ /**/ + 0x2D2A, /*U+2D2A*/ /**/ + 0x2D2B, /*U+2D2B*/ /**/ + 0x2D2C, /*U+2D2C*/ /**/ + 0x10CD, /*U+2D2D*/ /*GEORGIAN SMALL LETTER AEN*/ + 0x2D2E, /*U+2D2E*/ /**/ + 0x2D2F, /*U+2D2F*/ /**/ + 0x2D30, /*U+2D30*/ /**/ + 0x2D31, /*U+2D31*/ /**/ + 0x2D32, /*U+2D32*/ /**/ + 0x2D33, /*U+2D33*/ /**/ + 0x2D34, /*U+2D34*/ /**/ + 0x2D35, /*U+2D35*/ /**/ + 0x2D36, /*U+2D36*/ /**/ + 0x2D37, /*U+2D37*/ /**/ + 0x2D38, /*U+2D38*/ /**/ + 0x2D39, /*U+2D39*/ /**/ + 0x2D3A, /*U+2D3A*/ /**/ + 0x2D3B, /*U+2D3B*/ /**/ + 0x2D3C, /*U+2D3C*/ /**/ + 0x2D3D, /*U+2D3D*/ /**/ + 0x2D3E, /*U+2D3E*/ /**/ + 0x2D3F, /*U+2D3F*/ /**/ +}; + +static const uint16_t upper_table_8[128] = { + 0xA640, /*U+A640*/ /**/ + 0xA640, /*U+A641*/ /*CYRILLIC SMALL LETTER ZEMLYA*/ + 0xA642, /*U+A642*/ /**/ + 0xA642, /*U+A643*/ /*CYRILLIC SMALL LETTER DZELO*/ + 0xA644, /*U+A644*/ /**/ + 0xA644, /*U+A645*/ /*CYRILLIC SMALL LETTER REVERSED DZE*/ + 0xA646, /*U+A646*/ /**/ + 0xA646, /*U+A647*/ /*CYRILLIC SMALL LETTER IOTA*/ + 0xA648, /*U+A648*/ /**/ + 0xA648, /*U+A649*/ /*CYRILLIC SMALL LETTER DJERV*/ + 0xA64A, /*U+A64A*/ /**/ + 0xA64A, /*U+A64B*/ /*CYRILLIC SMALL LETTER MONOGRAPH UK*/ + 0xA64C, /*U+A64C*/ /**/ + 0xA64C, /*U+A64D*/ /*CYRILLIC SMALL LETTER BROAD OMEGA*/ + 0xA64E, /*U+A64E*/ /**/ + 0xA64E, /*U+A64F*/ /*CYRILLIC SMALL LETTER NEUTRAL YER*/ + 0xA650, /*U+A650*/ /**/ + 0xA650, /*U+A651*/ /*CYRILLIC SMALL LETTER YERU WITH BACK YER*/ + 0xA652, /*U+A652*/ /**/ + 0xA652, /*U+A653*/ /*CYRILLIC SMALL LETTER IOTIFIED YAT*/ + 0xA654, /*U+A654*/ /**/ + 0xA654, /*U+A655*/ /*CYRILLIC SMALL LETTER REVERSED YU*/ + 0xA656, /*U+A656*/ /**/ + 0xA656, /*U+A657*/ /*CYRILLIC SMALL LETTER IOTIFIED A*/ + 0xA658, /*U+A658*/ /**/ + 0xA658, /*U+A659*/ /*CYRILLIC SMALL LETTER CLOSED LITTLE YUS*/ + 0xA65A, /*U+A65A*/ /**/ + 0xA65A, /*U+A65B*/ /*CYRILLIC SMALL LETTER BLENDED YUS*/ + 0xA65C, /*U+A65C*/ /**/ + 0xA65C, /*U+A65D*/ /*CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS*/ + 0xA65E, /*U+A65E*/ /**/ + 0xA65E, /*U+A65F*/ /*CYRILLIC SMALL LETTER YN*/ + 0xA660, /*U+A660*/ /**/ + 0xA660, /*U+A661*/ /*CYRILLIC SMALL LETTER REVERSED TSE*/ + 0xA662, /*U+A662*/ /**/ + 0xA662, /*U+A663*/ /*CYRILLIC SMALL LETTER SOFT DE*/ + 0xA664, /*U+A664*/ /**/ + 0xA664, /*U+A665*/ /*CYRILLIC SMALL LETTER SOFT EL*/ + 0xA666, /*U+A666*/ /**/ + 0xA666, /*U+A667*/ /*CYRILLIC SMALL LETTER SOFT EM*/ + 0xA668, /*U+A668*/ /**/ + 0xA668, /*U+A669*/ /*CYRILLIC SMALL LETTER MONOCULAR O*/ + 0xA66A, /*U+A66A*/ /**/ + 0xA66A, /*U+A66B*/ /*CYRILLIC SMALL LETTER BINOCULAR O*/ + 0xA66C, /*U+A66C*/ /**/ + 0xA66C, /*U+A66D*/ /*CYRILLIC SMALL LETTER DOUBLE MONOCULAR O*/ + 0xA66E, /*U+A66E*/ /**/ + 0xA66F, /*U+A66F*/ /**/ + 0xA670, /*U+A670*/ /**/ + 0xA671, /*U+A671*/ /**/ + 0xA672, /*U+A672*/ /**/ + 0xA673, /*U+A673*/ /**/ + 0xA674, /*U+A674*/ /**/ + 0xA675, /*U+A675*/ /**/ + 0xA676, /*U+A676*/ /**/ + 0xA677, /*U+A677*/ /**/ + 0xA678, /*U+A678*/ /**/ + 0xA679, /*U+A679*/ /**/ + 0xA67A, /*U+A67A*/ /**/ + 0xA67B, /*U+A67B*/ /**/ + 0xA67C, /*U+A67C*/ /**/ + 0xA67D, /*U+A67D*/ /**/ + 0xA67E, /*U+A67E*/ /**/ + 0xA67F, /*U+A67F*/ /**/ + 0xA680, /*U+A680*/ /**/ + 0xA680, /*U+A681*/ /*CYRILLIC SMALL LETTER DWE*/ + 0xA682, /*U+A682*/ /**/ + 0xA682, /*U+A683*/ /*CYRILLIC SMALL LETTER DZWE*/ + 0xA684, /*U+A684*/ /**/ + 0xA684, /*U+A685*/ /*CYRILLIC SMALL LETTER ZHWE*/ + 0xA686, /*U+A686*/ /**/ + 0xA686, /*U+A687*/ /*CYRILLIC SMALL LETTER CCHE*/ + 0xA688, /*U+A688*/ /**/ + 0xA688, /*U+A689*/ /*CYRILLIC SMALL LETTER DZZE*/ + 0xA68A, /*U+A68A*/ /**/ + 0xA68A, /*U+A68B*/ /*CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK*/ + 0xA68C, /*U+A68C*/ /**/ + 0xA68C, /*U+A68D*/ /*CYRILLIC SMALL LETTER TWE*/ + 0xA68E, /*U+A68E*/ /**/ + 0xA68E, /*U+A68F*/ /*CYRILLIC SMALL LETTER TSWE*/ + 0xA690, /*U+A690*/ /**/ + 0xA690, /*U+A691*/ /*CYRILLIC SMALL LETTER TSSE*/ + 0xA692, /*U+A692*/ /**/ + 0xA692, /*U+A693*/ /*CYRILLIC SMALL LETTER TCHE*/ + 0xA694, /*U+A694*/ /**/ + 0xA694, /*U+A695*/ /*CYRILLIC SMALL LETTER HWE*/ + 0xA696, /*U+A696*/ /**/ + 0xA696, /*U+A697*/ /*CYRILLIC SMALL LETTER SHWE*/ + 0xA698, /*U+A698*/ /**/ + 0xA698, /*U+A699*/ /*CYRILLIC SMALL LETTER DOUBLE O*/ + 0xA69A, /*U+A69A*/ /**/ + 0xA69A, /*U+A69B*/ /*CYRILLIC SMALL LETTER CROSSED O*/ + 0xA69C, /*U+A69C*/ /**/ + 0xA69D, /*U+A69D*/ /**/ + 0xA69E, /*U+A69E*/ /**/ + 0xA69F, /*U+A69F*/ /**/ + 0xA6A0, /*U+A6A0*/ /**/ + 0xA6A1, /*U+A6A1*/ /**/ + 0xA6A2, /*U+A6A2*/ /**/ + 0xA6A3, /*U+A6A3*/ /**/ + 0xA6A4, /*U+A6A4*/ /**/ + 0xA6A5, /*U+A6A5*/ /**/ + 0xA6A6, /*U+A6A6*/ /**/ + 0xA6A7, /*U+A6A7*/ /**/ + 0xA6A8, /*U+A6A8*/ /**/ + 0xA6A9, /*U+A6A9*/ /**/ + 0xA6AA, /*U+A6AA*/ /**/ + 0xA6AB, /*U+A6AB*/ /**/ + 0xA6AC, /*U+A6AC*/ /**/ + 0xA6AD, /*U+A6AD*/ /**/ + 0xA6AE, /*U+A6AE*/ /**/ + 0xA6AF, /*U+A6AF*/ /**/ + 0xA6B0, /*U+A6B0*/ /**/ + 0xA6B1, /*U+A6B1*/ /**/ + 0xA6B2, /*U+A6B2*/ /**/ + 0xA6B3, /*U+A6B3*/ /**/ + 0xA6B4, /*U+A6B4*/ /**/ + 0xA6B5, /*U+A6B5*/ /**/ + 0xA6B6, /*U+A6B6*/ /**/ + 0xA6B7, /*U+A6B7*/ /**/ + 0xA6B8, /*U+A6B8*/ /**/ + 0xA6B9, /*U+A6B9*/ /**/ + 0xA6BA, /*U+A6BA*/ /**/ + 0xA6BB, /*U+A6BB*/ /**/ + 0xA6BC, /*U+A6BC*/ /**/ + 0xA6BD, /*U+A6BD*/ /**/ + 0xA6BE, /*U+A6BE*/ /**/ + 0xA6BF, /*U+A6BF*/ /**/ +}; + +static const uint16_t upper_table_9[192] = { + 0xA700, /*U+A700*/ /**/ + 0xA701, /*U+A701*/ /**/ + 0xA702, /*U+A702*/ /**/ + 0xA703, /*U+A703*/ /**/ + 0xA704, /*U+A704*/ /**/ + 0xA705, /*U+A705*/ /**/ + 0xA706, /*U+A706*/ /**/ + 0xA707, /*U+A707*/ /**/ + 0xA708, /*U+A708*/ /**/ + 0xA709, /*U+A709*/ /**/ + 0xA70A, /*U+A70A*/ /**/ + 0xA70B, /*U+A70B*/ /**/ + 0xA70C, /*U+A70C*/ /**/ + 0xA70D, /*U+A70D*/ /**/ + 0xA70E, /*U+A70E*/ /**/ + 0xA70F, /*U+A70F*/ /**/ + 0xA710, /*U+A710*/ /**/ + 0xA711, /*U+A711*/ /**/ + 0xA712, /*U+A712*/ /**/ + 0xA713, /*U+A713*/ /**/ + 0xA714, /*U+A714*/ /**/ + 0xA715, /*U+A715*/ /**/ + 0xA716, /*U+A716*/ /**/ + 0xA717, /*U+A717*/ /**/ + 0xA718, /*U+A718*/ /**/ + 0xA719, /*U+A719*/ /**/ + 0xA71A, /*U+A71A*/ /**/ + 0xA71B, /*U+A71B*/ /**/ + 0xA71C, /*U+A71C*/ /**/ + 0xA71D, /*U+A71D*/ /**/ + 0xA71E, /*U+A71E*/ /**/ + 0xA71F, /*U+A71F*/ /**/ + 0xA720, /*U+A720*/ /**/ + 0xA721, /*U+A721*/ /**/ + 0xA722, /*U+A722*/ /**/ + 0xA722, /*U+A723*/ /*LATIN SMALL LETTER EGYPTOLOGICAL ALEF*/ + 0xA724, /*U+A724*/ /**/ + 0xA724, /*U+A725*/ /*LATIN SMALL LETTER EGYPTOLOGICAL AIN*/ + 0xA726, /*U+A726*/ /**/ + 0xA726, /*U+A727*/ /*LATIN SMALL LETTER HENG*/ + 0xA728, /*U+A728*/ /**/ + 0xA728, /*U+A729*/ /*LATIN SMALL LETTER TZ*/ + 0xA72A, /*U+A72A*/ /**/ + 0xA72A, /*U+A72B*/ /*LATIN SMALL LETTER TRESILLO*/ + 0xA72C, /*U+A72C*/ /**/ + 0xA72C, /*U+A72D*/ /*LATIN SMALL LETTER CUATRILLO*/ + 0xA72E, /*U+A72E*/ /**/ + 0xA72E, /*U+A72F*/ /*LATIN SMALL LETTER CUATRILLO WITH COMMA*/ + 0xA730, /*U+A730*/ /**/ + 0xA731, /*U+A731*/ /**/ + 0xA732, /*U+A732*/ /**/ + 0xA732, /*U+A733*/ /*LATIN SMALL LETTER AA*/ + 0xA734, /*U+A734*/ /**/ + 0xA734, /*U+A735*/ /*LATIN SMALL LETTER AO*/ + 0xA736, /*U+A736*/ /**/ + 0xA736, /*U+A737*/ /*LATIN SMALL LETTER AU*/ + 0xA738, /*U+A738*/ /**/ + 0xA738, /*U+A739*/ /*LATIN SMALL LETTER AV*/ + 0xA73A, /*U+A73A*/ /**/ + 0xA73A, /*U+A73B*/ /*LATIN SMALL LETTER AV WITH HORIZONTAL BAR*/ + 0xA73C, /*U+A73C*/ /**/ + 0xA73C, /*U+A73D*/ /*LATIN SMALL LETTER AY*/ + 0xA73E, /*U+A73E*/ /**/ + 0xA73E, /*U+A73F*/ /*LATIN SMALL LETTER REVERSED C WITH DOT*/ + 0xA740, /*U+A740*/ /**/ + 0xA740, /*U+A741*/ /*LATIN SMALL LETTER K WITH STROKE*/ + 0xA742, /*U+A742*/ /**/ + 0xA742, /*U+A743*/ /*LATIN SMALL LETTER K WITH DIAGONAL STROKE*/ + 0xA744, /*U+A744*/ /**/ + 0xA744, /*U+A745*/ /*LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE*/ + 0xA746, /*U+A746*/ /**/ + 0xA746, /*U+A747*/ /*LATIN SMALL LETTER BROKEN L*/ + 0xA748, /*U+A748*/ /**/ + 0xA748, /*U+A749*/ /*LATIN SMALL LETTER L WITH HIGH STROKE*/ + 0xA74A, /*U+A74A*/ /**/ + 0xA74A, /*U+A74B*/ /*LATIN SMALL LETTER O WITH LONG STROKE OVERLAY*/ + 0xA74C, /*U+A74C*/ /**/ + 0xA74C, /*U+A74D*/ /*LATIN SMALL LETTER O WITH LOOP*/ + 0xA74E, /*U+A74E*/ /**/ + 0xA74E, /*U+A74F*/ /*LATIN SMALL LETTER OO*/ + 0xA750, /*U+A750*/ /**/ + 0xA750, /*U+A751*/ /*LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER*/ + 0xA752, /*U+A752*/ /**/ + 0xA752, /*U+A753*/ /*LATIN SMALL LETTER P WITH FLOURISH*/ + 0xA754, /*U+A754*/ /**/ + 0xA754, /*U+A755*/ /*LATIN SMALL LETTER P WITH SQUIRREL TAIL*/ + 0xA756, /*U+A756*/ /**/ + 0xA756, /*U+A757*/ /*LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER*/ + 0xA758, /*U+A758*/ /**/ + 0xA758, /*U+A759*/ /*LATIN SMALL LETTER Q WITH DIAGONAL STROKE*/ + 0xA75A, /*U+A75A*/ /**/ + 0xA75A, /*U+A75B*/ /*LATIN SMALL LETTER R ROTUNDA*/ + 0xA75C, /*U+A75C*/ /**/ + 0xA75C, /*U+A75D*/ /*LATIN SMALL LETTER RUM ROTUNDA*/ + 0xA75E, /*U+A75E*/ /**/ + 0xA75E, /*U+A75F*/ /*LATIN SMALL LETTER V WITH DIAGONAL STROKE*/ + 0xA760, /*U+A760*/ /**/ + 0xA760, /*U+A761*/ /*LATIN SMALL LETTER VY*/ + 0xA762, /*U+A762*/ /**/ + 0xA762, /*U+A763*/ /*LATIN SMALL LETTER VISIGOTHIC Z*/ + 0xA764, /*U+A764*/ /**/ + 0xA764, /*U+A765*/ /*LATIN SMALL LETTER THORN WITH STROKE*/ + 0xA766, /*U+A766*/ /**/ + 0xA766, /*U+A767*/ /*LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER*/ + 0xA768, /*U+A768*/ /**/ + 0xA768, /*U+A769*/ /*LATIN SMALL LETTER VEND*/ + 0xA76A, /*U+A76A*/ /**/ + 0xA76A, /*U+A76B*/ /*LATIN SMALL LETTER ET*/ + 0xA76C, /*U+A76C*/ /**/ + 0xA76C, /*U+A76D*/ /*LATIN SMALL LETTER IS*/ + 0xA76E, /*U+A76E*/ /**/ + 0xA76E, /*U+A76F*/ /*LATIN SMALL LETTER CON*/ + 0xA770, /*U+A770*/ /**/ + 0xA771, /*U+A771*/ /**/ + 0xA772, /*U+A772*/ /**/ + 0xA773, /*U+A773*/ /**/ + 0xA774, /*U+A774*/ /**/ + 0xA775, /*U+A775*/ /**/ + 0xA776, /*U+A776*/ /**/ + 0xA777, /*U+A777*/ /**/ + 0xA778, /*U+A778*/ /**/ + 0xA779, /*U+A779*/ /**/ + 0xA779, /*U+A77A*/ /*LATIN SMALL LETTER INSULAR D*/ + 0xA77B, /*U+A77B*/ /**/ + 0xA77B, /*U+A77C*/ /*LATIN SMALL LETTER INSULAR F*/ + 0xA77D, /*U+A77D*/ /**/ + 0xA77E, /*U+A77E*/ /**/ + 0xA77E, /*U+A77F*/ /*LATIN SMALL LETTER TURNED INSULAR G*/ + 0xA780, /*U+A780*/ /**/ + 0xA780, /*U+A781*/ /*LATIN SMALL LETTER TURNED L*/ + 0xA782, /*U+A782*/ /**/ + 0xA782, /*U+A783*/ /*LATIN SMALL LETTER INSULAR R*/ + 0xA784, /*U+A784*/ /**/ + 0xA784, /*U+A785*/ /*LATIN SMALL LETTER INSULAR S*/ + 0xA786, /*U+A786*/ /**/ + 0xA786, /*U+A787*/ /*LATIN SMALL LETTER INSULAR T*/ + 0xA788, /*U+A788*/ /**/ + 0xA789, /*U+A789*/ /**/ + 0xA78A, /*U+A78A*/ /**/ + 0xA78B, /*U+A78B*/ /**/ + 0xA78B, /*U+A78C*/ /*LATIN SMALL LETTER SALTILLO*/ + 0xA78D, /*U+A78D*/ /**/ + 0xA78E, /*U+A78E*/ /**/ + 0xA78F, /*U+A78F*/ /**/ + 0xA790, /*U+A790*/ /**/ + 0xA790, /*U+A791*/ /*LATIN SMALL LETTER N WITH DESCENDER*/ + 0xA792, /*U+A792*/ /**/ + 0xA792, /*U+A793*/ /*LATIN SMALL LETTER C WITH BAR*/ + 0xA794, /*U+A794*/ /**/ + 0xA795, /*U+A795*/ /**/ + 0xA796, /*U+A796*/ /**/ + 0xA796, /*U+A797*/ /*LATIN SMALL LETTER B WITH FLOURISH*/ + 0xA798, /*U+A798*/ /**/ + 0xA798, /*U+A799*/ /*LATIN SMALL LETTER F WITH STROKE*/ + 0xA79A, /*U+A79A*/ /**/ + 0xA79A, /*U+A79B*/ /*LATIN SMALL LETTER VOLAPUK AE*/ + 0xA79C, /*U+A79C*/ /**/ + 0xA79C, /*U+A79D*/ /*LATIN SMALL LETTER VOLAPUK OE*/ + 0xA79E, /*U+A79E*/ /**/ + 0xA79E, /*U+A79F*/ /*LATIN SMALL LETTER VOLAPUK UE*/ + 0xA7A0, /*U+A7A0*/ /**/ + 0xA7A0, /*U+A7A1*/ /*LATIN SMALL LETTER G WITH OBLIQUE STROKE*/ + 0xA7A2, /*U+A7A2*/ /**/ + 0xA7A2, /*U+A7A3*/ /*LATIN SMALL LETTER K WITH OBLIQUE STROKE*/ + 0xA7A4, /*U+A7A4*/ /**/ + 0xA7A4, /*U+A7A5*/ /*LATIN SMALL LETTER N WITH OBLIQUE STROKE*/ + 0xA7A6, /*U+A7A6*/ /**/ + 0xA7A6, /*U+A7A7*/ /*LATIN SMALL LETTER R WITH OBLIQUE STROKE*/ + 0xA7A8, /*U+A7A8*/ /**/ + 0xA7A8, /*U+A7A9*/ /*LATIN SMALL LETTER S WITH OBLIQUE STROKE*/ + 0xA7AA, /*U+A7AA*/ /**/ + 0xA7AB, /*U+A7AB*/ /**/ + 0xA7AC, /*U+A7AC*/ /**/ + 0xA7AD, /*U+A7AD*/ /**/ + 0xA7AE, /*U+A7AE*/ /**/ + 0xA7AF, /*U+A7AF*/ /**/ + 0xA7B0, /*U+A7B0*/ /**/ + 0xA7B1, /*U+A7B1*/ /**/ + 0xA7B2, /*U+A7B2*/ /**/ + 0xA7B3, /*U+A7B3*/ /**/ + 0xA7B4, /*U+A7B4*/ /**/ + 0xA7B5, /*U+A7B5*/ /**/ + 0xA7B6, /*U+A7B6*/ /**/ + 0xA7B7, /*U+A7B7*/ /**/ + 0xA7B8, /*U+A7B8*/ /**/ + 0xA7B9, /*U+A7B9*/ /**/ + 0xA7BA, /*U+A7BA*/ /**/ + 0xA7BB, /*U+A7BB*/ /**/ + 0xA7BC, /*U+A7BC*/ /**/ + 0xA7BD, /*U+A7BD*/ /**/ + 0xA7BE, /*U+A7BE*/ /**/ + 0xA7BF, /*U+A7BF*/ /**/ +}; + +static const uint16_t upper_table_10[64] = { + 0xFF40, /*U+FF40*/ /**/ + 0xFF21, /*U+FF41*/ /*FULLWIDTH LATIN SMALL LETTER A*/ + 0xFF22, /*U+FF42*/ /*FULLWIDTH LATIN SMALL LETTER B*/ + 0xFF23, /*U+FF43*/ /*FULLWIDTH LATIN SMALL LETTER C*/ + 0xFF24, /*U+FF44*/ /*FULLWIDTH LATIN SMALL LETTER D*/ + 0xFF25, /*U+FF45*/ /*FULLWIDTH LATIN SMALL LETTER E*/ + 0xFF26, /*U+FF46*/ /*FULLWIDTH LATIN SMALL LETTER F*/ + 0xFF27, /*U+FF47*/ /*FULLWIDTH LATIN SMALL LETTER G*/ + 0xFF28, /*U+FF48*/ /*FULLWIDTH LATIN SMALL LETTER H*/ + 0xFF29, /*U+FF49*/ /*FULLWIDTH LATIN SMALL LETTER I*/ + 0xFF2A, /*U+FF4A*/ /*FULLWIDTH LATIN SMALL LETTER J*/ + 0xFF2B, /*U+FF4B*/ /*FULLWIDTH LATIN SMALL LETTER K*/ + 0xFF2C, /*U+FF4C*/ /*FULLWIDTH LATIN SMALL LETTER L*/ + 0xFF2D, /*U+FF4D*/ /*FULLWIDTH LATIN SMALL LETTER M*/ + 0xFF2E, /*U+FF4E*/ /*FULLWIDTH LATIN SMALL LETTER N*/ + 0xFF2F, /*U+FF4F*/ /*FULLWIDTH LATIN SMALL LETTER O*/ + 0xFF30, /*U+FF50*/ /*FULLWIDTH LATIN SMALL LETTER P*/ + 0xFF31, /*U+FF51*/ /*FULLWIDTH LATIN SMALL LETTER Q*/ + 0xFF32, /*U+FF52*/ /*FULLWIDTH LATIN SMALL LETTER R*/ + 0xFF33, /*U+FF53*/ /*FULLWIDTH LATIN SMALL LETTER S*/ + 0xFF34, /*U+FF54*/ /*FULLWIDTH LATIN SMALL LETTER T*/ + 0xFF35, /*U+FF55*/ /*FULLWIDTH LATIN SMALL LETTER U*/ + 0xFF36, /*U+FF56*/ /*FULLWIDTH LATIN SMALL LETTER V*/ + 0xFF37, /*U+FF57*/ /*FULLWIDTH LATIN SMALL LETTER W*/ + 0xFF38, /*U+FF58*/ /*FULLWIDTH LATIN SMALL LETTER X*/ + 0xFF39, /*U+FF59*/ /*FULLWIDTH LATIN SMALL LETTER Y*/ + 0xFF3A, /*U+FF5A*/ /*FULLWIDTH LATIN SMALL LETTER Z*/ + 0xFF5B, /*U+FF5B*/ /**/ + 0xFF5C, /*U+FF5C*/ /**/ + 0xFF5D, /*U+FF5D*/ /**/ + 0xFF5E, /*U+FF5E*/ /**/ + 0xFF5F, /*U+FF5F*/ /**/ + 0xFF60, /*U+FF60*/ /**/ + 0xFF61, /*U+FF61*/ /**/ + 0xFF62, /*U+FF62*/ /**/ + 0xFF63, /*U+FF63*/ /**/ + 0xFF64, /*U+FF64*/ /**/ + 0xFF65, /*U+FF65*/ /**/ + 0xFF66, /*U+FF66*/ /**/ + 0xFF67, /*U+FF67*/ /**/ + 0xFF68, /*U+FF68*/ /**/ + 0xFF69, /*U+FF69*/ /**/ + 0xFF6A, /*U+FF6A*/ /**/ + 0xFF6B, /*U+FF6B*/ /**/ + 0xFF6C, /*U+FF6C*/ /**/ + 0xFF6D, /*U+FF6D*/ /**/ + 0xFF6E, /*U+FF6E*/ /**/ + 0xFF6F, /*U+FF6F*/ /**/ + 0xFF70, /*U+FF70*/ /**/ + 0xFF71, /*U+FF71*/ /**/ + 0xFF72, /*U+FF72*/ /**/ + 0xFF73, /*U+FF73*/ /**/ + 0xFF74, /*U+FF74*/ /**/ + 0xFF75, /*U+FF75*/ /**/ + 0xFF76, /*U+FF76*/ /**/ + 0xFF77, /*U+FF77*/ /**/ + 0xFF78, /*U+FF78*/ /**/ + 0xFF79, /*U+FF79*/ /**/ + 0xFF7A, /*U+FF7A*/ /**/ + 0xFF7B, /*U+FF7B*/ /**/ + 0xFF7C, /*U+FF7C*/ /**/ + 0xFF7D, /*U+FF7D*/ /**/ + 0xFF7E, /*U+FF7E*/ /**/ + 0xFF7F, /*U+FF7F*/ /**/ +}; + +static const uint32_t upper_table_sp_1[128] = { + 0xD801DC00, /*0xD801DC00*/ /*U+010400*/ /*U+010400*/ /**/ + 0xD801DC01, /*0xD801DC01*/ /*U+010401*/ /*U+010401*/ /**/ + 0xD801DC02, /*0xD801DC02*/ /*U+010402*/ /*U+010402*/ /**/ + 0xD801DC03, /*0xD801DC03*/ /*U+010403*/ /*U+010403*/ /**/ + 0xD801DC04, /*0xD801DC04*/ /*U+010404*/ /*U+010404*/ /**/ + 0xD801DC05, /*0xD801DC05*/ /*U+010405*/ /*U+010405*/ /**/ + 0xD801DC06, /*0xD801DC06*/ /*U+010406*/ /*U+010406*/ /**/ + 0xD801DC07, /*0xD801DC07*/ /*U+010407*/ /*U+010407*/ /**/ + 0xD801DC08, /*0xD801DC08*/ /*U+010408*/ /*U+010408*/ /**/ + 0xD801DC09, /*0xD801DC09*/ /*U+010409*/ /*U+010409*/ /**/ + 0xD801DC0A, /*0xD801DC0A*/ /*U+01040A*/ /*U+01040A*/ /**/ + 0xD801DC0B, /*0xD801DC0B*/ /*U+01040B*/ /*U+01040B*/ /**/ + 0xD801DC0C, /*0xD801DC0C*/ /*U+01040C*/ /*U+01040C*/ /**/ + 0xD801DC0D, /*0xD801DC0D*/ /*U+01040D*/ /*U+01040D*/ /**/ + 0xD801DC0E, /*0xD801DC0E*/ /*U+01040E*/ /*U+01040E*/ /**/ + 0xD801DC0F, /*0xD801DC0F*/ /*U+01040F*/ /*U+01040F*/ /**/ + 0xD801DC10, /*0xD801DC10*/ /*U+010410*/ /*U+010410*/ /**/ + 0xD801DC11, /*0xD801DC11*/ /*U+010411*/ /*U+010411*/ /**/ + 0xD801DC12, /*0xD801DC12*/ /*U+010412*/ /*U+010412*/ /**/ + 0xD801DC13, /*0xD801DC13*/ /*U+010413*/ /*U+010413*/ /**/ + 0xD801DC14, /*0xD801DC14*/ /*U+010414*/ /*U+010414*/ /**/ + 0xD801DC15, /*0xD801DC15*/ /*U+010415*/ /*U+010415*/ /**/ + 0xD801DC16, /*0xD801DC16*/ /*U+010416*/ /*U+010416*/ /**/ + 0xD801DC17, /*0xD801DC17*/ /*U+010417*/ /*U+010417*/ /**/ + 0xD801DC18, /*0xD801DC18*/ /*U+010418*/ /*U+010418*/ /**/ + 0xD801DC19, /*0xD801DC19*/ /*U+010419*/ /*U+010419*/ /**/ + 0xD801DC1A, /*0xD801DC1A*/ /*U+01041A*/ /*U+01041A*/ /**/ + 0xD801DC1B, /*0xD801DC1B*/ /*U+01041B*/ /*U+01041B*/ /**/ + 0xD801DC1C, /*0xD801DC1C*/ /*U+01041C*/ /*U+01041C*/ /**/ + 0xD801DC1D, /*0xD801DC1D*/ /*U+01041D*/ /*U+01041D*/ /**/ + 0xD801DC1E, /*0xD801DC1E*/ /*U+01041E*/ /*U+01041E*/ /**/ + 0xD801DC1F, /*0xD801DC1F*/ /*U+01041F*/ /*U+01041F*/ /**/ + 0xD801DC20, /*0xD801DC20*/ /*U+010420*/ /*U+010420*/ /**/ + 0xD801DC21, /*0xD801DC21*/ /*U+010421*/ /*U+010421*/ /**/ + 0xD801DC22, /*0xD801DC22*/ /*U+010422*/ /*U+010422*/ /**/ + 0xD801DC23, /*0xD801DC23*/ /*U+010423*/ /*U+010423*/ /**/ + 0xD801DC24, /*0xD801DC24*/ /*U+010424*/ /*U+010424*/ /**/ + 0xD801DC25, /*0xD801DC25*/ /*U+010425*/ /*U+010425*/ /**/ + 0xD801DC26, /*0xD801DC26*/ /*U+010426*/ /*U+010426*/ /**/ + 0xD801DC27, /*0xD801DC27*/ /*U+010427*/ /*U+010427*/ /**/ + 0xD801DC00, /*0xD801DC28*/ /*U+010400*/ /*U+010428*/ /*DESERET SMALL LETTER LONG I*/ + 0xD801DC01, /*0xD801DC29*/ /*U+010401*/ /*U+010429*/ /*DESERET SMALL LETTER LONG E*/ + 0xD801DC02, /*0xD801DC2A*/ /*U+010402*/ /*U+01042A*/ /*DESERET SMALL LETTER LONG A*/ + 0xD801DC03, /*0xD801DC2B*/ /*U+010403*/ /*U+01042B*/ /*DESERET SMALL LETTER LONG AH*/ + 0xD801DC04, /*0xD801DC2C*/ /*U+010404*/ /*U+01042C*/ /*DESERET SMALL LETTER LONG O*/ + 0xD801DC05, /*0xD801DC2D*/ /*U+010405*/ /*U+01042D*/ /*DESERET SMALL LETTER LONG OO*/ + 0xD801DC06, /*0xD801DC2E*/ /*U+010406*/ /*U+01042E*/ /*DESERET SMALL LETTER SHORT I*/ + 0xD801DC07, /*0xD801DC2F*/ /*U+010407*/ /*U+01042F*/ /*DESERET SMALL LETTER SHORT E*/ + 0xD801DC08, /*0xD801DC30*/ /*U+010408*/ /*U+010430*/ /*DESERET SMALL LETTER SHORT A*/ + 0xD801DC09, /*0xD801DC31*/ /*U+010409*/ /*U+010431*/ /*DESERET SMALL LETTER SHORT AH*/ + 0xD801DC0A, /*0xD801DC32*/ /*U+01040A*/ /*U+010432*/ /*DESERET SMALL LETTER SHORT O*/ + 0xD801DC0B, /*0xD801DC33*/ /*U+01040B*/ /*U+010433*/ /*DESERET SMALL LETTER SHORT OO*/ + 0xD801DC0C, /*0xD801DC34*/ /*U+01040C*/ /*U+010434*/ /*DESERET SMALL LETTER AY*/ + 0xD801DC0D, /*0xD801DC35*/ /*U+01040D*/ /*U+010435*/ /*DESERET SMALL LETTER OW*/ + 0xD801DC0E, /*0xD801DC36*/ /*U+01040E*/ /*U+010436*/ /*DESERET SMALL LETTER WU*/ + 0xD801DC0F, /*0xD801DC37*/ /*U+01040F*/ /*U+010437*/ /*DESERET SMALL LETTER YEE*/ + 0xD801DC10, /*0xD801DC38*/ /*U+010410*/ /*U+010438*/ /*DESERET SMALL LETTER H*/ + 0xD801DC11, /*0xD801DC39*/ /*U+010411*/ /*U+010439*/ /*DESERET SMALL LETTER PEE*/ + 0xD801DC12, /*0xD801DC3A*/ /*U+010412*/ /*U+01043A*/ /*DESERET SMALL LETTER BEE*/ + 0xD801DC13, /*0xD801DC3B*/ /*U+010413*/ /*U+01043B*/ /*DESERET SMALL LETTER TEE*/ + 0xD801DC14, /*0xD801DC3C*/ /*U+010414*/ /*U+01043C*/ /*DESERET SMALL LETTER DEE*/ + 0xD801DC15, /*0xD801DC3D*/ /*U+010415*/ /*U+01043D*/ /*DESERET SMALL LETTER CHEE*/ + 0xD801DC16, /*0xD801DC3E*/ /*U+010416*/ /*U+01043E*/ /*DESERET SMALL LETTER JEE*/ + 0xD801DC17, /*0xD801DC3F*/ /*U+010417*/ /*U+01043F*/ /*DESERET SMALL LETTER KAY*/ + 0xD801DC18, /*0xD801DC40*/ /*U+010418*/ /*U+010440*/ /*DESERET SMALL LETTER GAY*/ + 0xD801DC19, /*0xD801DC41*/ /*U+010419*/ /*U+010441*/ /*DESERET SMALL LETTER EF*/ + 0xD801DC1A, /*0xD801DC42*/ /*U+01041A*/ /*U+010442*/ /*DESERET SMALL LETTER VEE*/ + 0xD801DC1B, /*0xD801DC43*/ /*U+01041B*/ /*U+010443*/ /*DESERET SMALL LETTER ETH*/ + 0xD801DC1C, /*0xD801DC44*/ /*U+01041C*/ /*U+010444*/ /*DESERET SMALL LETTER THEE*/ + 0xD801DC1D, /*0xD801DC45*/ /*U+01041D*/ /*U+010445*/ /*DESERET SMALL LETTER ES*/ + 0xD801DC1E, /*0xD801DC46*/ /*U+01041E*/ /*U+010446*/ /*DESERET SMALL LETTER ZEE*/ + 0xD801DC1F, /*0xD801DC47*/ /*U+01041F*/ /*U+010447*/ /*DESERET SMALL LETTER ESH*/ + 0xD801DC20, /*0xD801DC48*/ /*U+010420*/ /*U+010448*/ /*DESERET SMALL LETTER ZHEE*/ + 0xD801DC21, /*0xD801DC49*/ /*U+010421*/ /*U+010449*/ /*DESERET SMALL LETTER ER*/ + 0xD801DC22, /*0xD801DC4A*/ /*U+010422*/ /*U+01044A*/ /*DESERET SMALL LETTER EL*/ + 0xD801DC23, /*0xD801DC4B*/ /*U+010423*/ /*U+01044B*/ /*DESERET SMALL LETTER EM*/ + 0xD801DC24, /*0xD801DC4C*/ /*U+010424*/ /*U+01044C*/ /*DESERET SMALL LETTER EN*/ + 0xD801DC25, /*0xD801DC4D*/ /*U+010425*/ /*U+01044D*/ /*DESERET SMALL LETTER ENG*/ + 0xD801DC26, /*0xD801DC4E*/ /*U+010426*/ /*U+01044E*/ /*DESERET SMALL LETTER OI*/ + 0xD801DC27, /*0xD801DC4F*/ /*U+010427*/ /*U+01044F*/ /*DESERET SMALL LETTER EW*/ + 0xD801DC50, /*0xD801DC50*/ /*U+010450*/ /*U+010450*/ /**/ + 0xD801DC51, /*0xD801DC51*/ /*U+010451*/ /*U+010451*/ /**/ + 0xD801DC52, /*0xD801DC52*/ /*U+010452*/ /*U+010452*/ /**/ + 0xD801DC53, /*0xD801DC53*/ /*U+010453*/ /*U+010453*/ /**/ + 0xD801DC54, /*0xD801DC54*/ /*U+010454*/ /*U+010454*/ /**/ + 0xD801DC55, /*0xD801DC55*/ /*U+010455*/ /*U+010455*/ /**/ + 0xD801DC56, /*0xD801DC56*/ /*U+010456*/ /*U+010456*/ /**/ + 0xD801DC57, /*0xD801DC57*/ /*U+010457*/ /*U+010457*/ /**/ + 0xD801DC58, /*0xD801DC58*/ /*U+010458*/ /*U+010458*/ /**/ + 0xD801DC59, /*0xD801DC59*/ /*U+010459*/ /*U+010459*/ /**/ + 0xD801DC5A, /*0xD801DC5A*/ /*U+01045A*/ /*U+01045A*/ /**/ + 0xD801DC5B, /*0xD801DC5B*/ /*U+01045B*/ /*U+01045B*/ /**/ + 0xD801DC5C, /*0xD801DC5C*/ /*U+01045C*/ /*U+01045C*/ /**/ + 0xD801DC5D, /*0xD801DC5D*/ /*U+01045D*/ /*U+01045D*/ /**/ + 0xD801DC5E, /*0xD801DC5E*/ /*U+01045E*/ /*U+01045E*/ /**/ + 0xD801DC5F, /*0xD801DC5F*/ /*U+01045F*/ /*U+01045F*/ /**/ + 0xD801DC60, /*0xD801DC60*/ /*U+010460*/ /*U+010460*/ /**/ + 0xD801DC61, /*0xD801DC61*/ /*U+010461*/ /*U+010461*/ /**/ + 0xD801DC62, /*0xD801DC62*/ /*U+010462*/ /*U+010462*/ /**/ + 0xD801DC63, /*0xD801DC63*/ /*U+010463*/ /*U+010463*/ /**/ + 0xD801DC64, /*0xD801DC64*/ /*U+010464*/ /*U+010464*/ /**/ + 0xD801DC65, /*0xD801DC65*/ /*U+010465*/ /*U+010465*/ /**/ + 0xD801DC66, /*0xD801DC66*/ /*U+010466*/ /*U+010466*/ /**/ + 0xD801DC67, /*0xD801DC67*/ /*U+010467*/ /*U+010467*/ /**/ + 0xD801DC68, /*0xD801DC68*/ /*U+010468*/ /*U+010468*/ /**/ + 0xD801DC69, /*0xD801DC69*/ /*U+010469*/ /*U+010469*/ /**/ + 0xD801DC6A, /*0xD801DC6A*/ /*U+01046A*/ /*U+01046A*/ /**/ + 0xD801DC6B, /*0xD801DC6B*/ /*U+01046B*/ /*U+01046B*/ /**/ + 0xD801DC6C, /*0xD801DC6C*/ /*U+01046C*/ /*U+01046C*/ /**/ + 0xD801DC6D, /*0xD801DC6D*/ /*U+01046D*/ /*U+01046D*/ /**/ + 0xD801DC6E, /*0xD801DC6E*/ /*U+01046E*/ /*U+01046E*/ /**/ + 0xD801DC6F, /*0xD801DC6F*/ /*U+01046F*/ /*U+01046F*/ /**/ + 0xD801DC70, /*0xD801DC70*/ /*U+010470*/ /*U+010470*/ /**/ + 0xD801DC71, /*0xD801DC71*/ /*U+010471*/ /*U+010471*/ /**/ + 0xD801DC72, /*0xD801DC72*/ /*U+010472*/ /*U+010472*/ /**/ + 0xD801DC73, /*0xD801DC73*/ /*U+010473*/ /*U+010473*/ /**/ + 0xD801DC74, /*0xD801DC74*/ /*U+010474*/ /*U+010474*/ /**/ + 0xD801DC75, /*0xD801DC75*/ /*U+010475*/ /*U+010475*/ /**/ + 0xD801DC76, /*0xD801DC76*/ /*U+010476*/ /*U+010476*/ /**/ + 0xD801DC77, /*0xD801DC77*/ /*U+010477*/ /*U+010477*/ /**/ + 0xD801DC78, /*0xD801DC78*/ /*U+010478*/ /*U+010478*/ /**/ + 0xD801DC79, /*0xD801DC79*/ /*U+010479*/ /*U+010479*/ /**/ + 0xD801DC7A, /*0xD801DC7A*/ /*U+01047A*/ /*U+01047A*/ /**/ + 0xD801DC7B, /*0xD801DC7B*/ /*U+01047B*/ /*U+01047B*/ /**/ + 0xD801DC7C, /*0xD801DC7C*/ /*U+01047C*/ /*U+01047C*/ /**/ + 0xD801DC7D, /*0xD801DC7D*/ /*U+01047D*/ /*U+01047D*/ /**/ + 0xD801DC7E, /*0xD801DC7E*/ /*U+01047E*/ /*U+01047E*/ /**/ + 0xD801DC7F, /*0xD801DC7F*/ /*U+01047F*/ /*U+01047F*/ /**/ +}; + +static const uint32_t upper_table_sp_2[64] = { + 0xD806DCA0, /*0xD806DCC0*/ /*U+0118A0*/ /*U+0118C0*/ /*WARANG CITI SMALL LETTER NGAA*/ + 0xD806DCA1, /*0xD806DCC1*/ /*U+0118A1*/ /*U+0118C1*/ /*WARANG CITI SMALL LETTER A*/ + 0xD806DCA2, /*0xD806DCC2*/ /*U+0118A2*/ /*U+0118C2*/ /*WARANG CITI SMALL LETTER WI*/ + 0xD806DCA3, /*0xD806DCC3*/ /*U+0118A3*/ /*U+0118C3*/ /*WARANG CITI SMALL LETTER YU*/ + 0xD806DCA4, /*0xD806DCC4*/ /*U+0118A4*/ /*U+0118C4*/ /*WARANG CITI SMALL LETTER YA*/ + 0xD806DCA5, /*0xD806DCC5*/ /*U+0118A5*/ /*U+0118C5*/ /*WARANG CITI SMALL LETTER YO*/ + 0xD806DCA6, /*0xD806DCC6*/ /*U+0118A6*/ /*U+0118C6*/ /*WARANG CITI SMALL LETTER II*/ + 0xD806DCA7, /*0xD806DCC7*/ /*U+0118A7*/ /*U+0118C7*/ /*WARANG CITI SMALL LETTER UU*/ + 0xD806DCA8, /*0xD806DCC8*/ /*U+0118A8*/ /*U+0118C8*/ /*WARANG CITI SMALL LETTER E*/ + 0xD806DCA9, /*0xD806DCC9*/ /*U+0118A9*/ /*U+0118C9*/ /*WARANG CITI SMALL LETTER O*/ + 0xD806DCAA, /*0xD806DCCA*/ /*U+0118AA*/ /*U+0118CA*/ /*WARANG CITI SMALL LETTER ANG*/ + 0xD806DCAB, /*0xD806DCCB*/ /*U+0118AB*/ /*U+0118CB*/ /*WARANG CITI SMALL LETTER GA*/ + 0xD806DCAC, /*0xD806DCCC*/ /*U+0118AC*/ /*U+0118CC*/ /*WARANG CITI SMALL LETTER KO*/ + 0xD806DCAD, /*0xD806DCCD*/ /*U+0118AD*/ /*U+0118CD*/ /*WARANG CITI SMALL LETTER ENY*/ + 0xD806DCAE, /*0xD806DCCE*/ /*U+0118AE*/ /*U+0118CE*/ /*WARANG CITI SMALL LETTER YUJ*/ + 0xD806DCAF, /*0xD806DCCF*/ /*U+0118AF*/ /*U+0118CF*/ /*WARANG CITI SMALL LETTER UC*/ + 0xD806DCB0, /*0xD806DCD0*/ /*U+0118B0*/ /*U+0118D0*/ /*WARANG CITI SMALL LETTER ENN*/ + 0xD806DCB1, /*0xD806DCD1*/ /*U+0118B1*/ /*U+0118D1*/ /*WARANG CITI SMALL LETTER ODD*/ + 0xD806DCB2, /*0xD806DCD2*/ /*U+0118B2*/ /*U+0118D2*/ /*WARANG CITI SMALL LETTER TTE*/ + 0xD806DCB3, /*0xD806DCD3*/ /*U+0118B3*/ /*U+0118D3*/ /*WARANG CITI SMALL LETTER NUNG*/ + 0xD806DCB4, /*0xD806DCD4*/ /*U+0118B4*/ /*U+0118D4*/ /*WARANG CITI SMALL LETTER DA*/ + 0xD806DCB5, /*0xD806DCD5*/ /*U+0118B5*/ /*U+0118D5*/ /*WARANG CITI SMALL LETTER AT*/ + 0xD806DCB6, /*0xD806DCD6*/ /*U+0118B6*/ /*U+0118D6*/ /*WARANG CITI SMALL LETTER AM*/ + 0xD806DCB7, /*0xD806DCD7*/ /*U+0118B7*/ /*U+0118D7*/ /*WARANG CITI SMALL LETTER BU*/ + 0xD806DCB8, /*0xD806DCD8*/ /*U+0118B8*/ /*U+0118D8*/ /*WARANG CITI SMALL LETTER PU*/ + 0xD806DCB9, /*0xD806DCD9*/ /*U+0118B9*/ /*U+0118D9*/ /*WARANG CITI SMALL LETTER HIYO*/ + 0xD806DCBA, /*0xD806DCDA*/ /*U+0118BA*/ /*U+0118DA*/ /*WARANG CITI SMALL LETTER HOLO*/ + 0xD806DCBB, /*0xD806DCDB*/ /*U+0118BB*/ /*U+0118DB*/ /*WARANG CITI SMALL LETTER HORR*/ + 0xD806DCBC, /*0xD806DCDC*/ /*U+0118BC*/ /*U+0118DC*/ /*WARANG CITI SMALL LETTER HAR*/ + 0xD806DCBD, /*0xD806DCDD*/ /*U+0118BD*/ /*U+0118DD*/ /*WARANG CITI SMALL LETTER SSUU*/ + 0xD806DCBE, /*0xD806DCDE*/ /*U+0118BE*/ /*U+0118DE*/ /*WARANG CITI SMALL LETTER SII*/ + 0xD806DCBF, /*0xD806DCDF*/ /*U+0118BF*/ /*U+0118DF*/ /*WARANG CITI SMALL LETTER VIYO*/ + 0xD806DCE0, /*0xD806DCE0*/ /*U+0118E0*/ /*U+0118E0*/ /**/ + 0xD806DCE1, /*0xD806DCE1*/ /*U+0118E1*/ /*U+0118E1*/ /**/ + 0xD806DCE2, /*0xD806DCE2*/ /*U+0118E2*/ /*U+0118E2*/ /**/ + 0xD806DCE3, /*0xD806DCE3*/ /*U+0118E3*/ /*U+0118E3*/ /**/ + 0xD806DCE4, /*0xD806DCE4*/ /*U+0118E4*/ /*U+0118E4*/ /**/ + 0xD806DCE5, /*0xD806DCE5*/ /*U+0118E5*/ /*U+0118E5*/ /**/ + 0xD806DCE6, /*0xD806DCE6*/ /*U+0118E6*/ /*U+0118E6*/ /**/ + 0xD806DCE7, /*0xD806DCE7*/ /*U+0118E7*/ /*U+0118E7*/ /**/ + 0xD806DCE8, /*0xD806DCE8*/ /*U+0118E8*/ /*U+0118E8*/ /**/ + 0xD806DCE9, /*0xD806DCE9*/ /*U+0118E9*/ /*U+0118E9*/ /**/ + 0xD806DCEA, /*0xD806DCEA*/ /*U+0118EA*/ /*U+0118EA*/ /**/ + 0xD806DCEB, /*0xD806DCEB*/ /*U+0118EB*/ /*U+0118EB*/ /**/ + 0xD806DCEC, /*0xD806DCEC*/ /*U+0118EC*/ /*U+0118EC*/ /**/ + 0xD806DCED, /*0xD806DCED*/ /*U+0118ED*/ /*U+0118ED*/ /**/ + 0xD806DCEE, /*0xD806DCEE*/ /*U+0118EE*/ /*U+0118EE*/ /**/ + 0xD806DCEF, /*0xD806DCEF*/ /*U+0118EF*/ /*U+0118EF*/ /**/ + 0xD806DCF0, /*0xD806DCF0*/ /*U+0118F0*/ /*U+0118F0*/ /**/ + 0xD806DCF1, /*0xD806DCF1*/ /*U+0118F1*/ /*U+0118F1*/ /**/ + 0xD806DCF2, /*0xD806DCF2*/ /*U+0118F2*/ /*U+0118F2*/ /**/ + 0xD806DCF3, /*0xD806DCF3*/ /*U+0118F3*/ /*U+0118F3*/ /**/ + 0xD806DCF4, /*0xD806DCF4*/ /*U+0118F4*/ /*U+0118F4*/ /**/ + 0xD806DCF5, /*0xD806DCF5*/ /*U+0118F5*/ /*U+0118F5*/ /**/ + 0xD806DCF6, /*0xD806DCF6*/ /*U+0118F6*/ /*U+0118F6*/ /**/ + 0xD806DCF7, /*0xD806DCF7*/ /*U+0118F7*/ /*U+0118F7*/ /**/ + 0xD806DCF8, /*0xD806DCF8*/ /*U+0118F8*/ /*U+0118F8*/ /**/ + 0xD806DCF9, /*0xD806DCF9*/ /*U+0118F9*/ /*U+0118F9*/ /**/ + 0xD806DCFA, /*0xD806DCFA*/ /*U+0118FA*/ /*U+0118FA*/ /**/ + 0xD806DCFB, /*0xD806DCFB*/ /*U+0118FB*/ /*U+0118FB*/ /**/ + 0xD806DCFC, /*0xD806DCFC*/ /*U+0118FC*/ /*U+0118FC*/ /**/ + 0xD806DCFD, /*0xD806DCFD*/ /*U+0118FD*/ /*U+0118FD*/ /**/ + 0xD806DCFE, /*0xD806DCFE*/ /*U+0118FE*/ /*U+0118FE*/ /**/ + 0xD806DCFF, /*0xD806DCFF*/ /*U+0118FF*/ /*U+0118FF*/ /**/ +}; + +static const uint16_t lower_table_1[128] = { + 0x0000, /*U+0000*/ /**/ + 0x0001, /*U+0001*/ /**/ + 0x0002, /*U+0002*/ /**/ + 0x0003, /*U+0003*/ /**/ + 0x0004, /*U+0004*/ /**/ + 0x0005, /*U+0005*/ /**/ + 0x0006, /*U+0006*/ /**/ + 0x0007, /*U+0007*/ /**/ + 0x0008, /*U+0008*/ /**/ + 0x0009, /*U+0009*/ /**/ + 0x000A, /*U+000A*/ /**/ + 0x000B, /*U+000B*/ /**/ + 0x000C, /*U+000C*/ /**/ + 0x000D, /*U+000D*/ /**/ + 0x000E, /*U+000E*/ /**/ + 0x000F, /*U+000F*/ /**/ + 0x0010, /*U+0010*/ /**/ + 0x0011, /*U+0011*/ /**/ + 0x0012, /*U+0012*/ /**/ + 0x0013, /*U+0013*/ /**/ + 0x0014, /*U+0014*/ /**/ + 0x0015, /*U+0015*/ /**/ + 0x0016, /*U+0016*/ /**/ + 0x0017, /*U+0017*/ /**/ + 0x0018, /*U+0018*/ /**/ + 0x0019, /*U+0019*/ /**/ + 0x001A, /*U+001A*/ /**/ + 0x001B, /*U+001B*/ /**/ + 0x001C, /*U+001C*/ /**/ + 0x001D, /*U+001D*/ /**/ + 0x001E, /*U+001E*/ /**/ + 0x001F, /*U+001F*/ /**/ + 0x0020, /*U+0020*/ /**/ + 0x0021, /*U+0021*/ /**/ + 0x0022, /*U+0022*/ /**/ + 0x0023, /*U+0023*/ /**/ + 0x0024, /*U+0024*/ /**/ + 0x0025, /*U+0025*/ /**/ + 0x0026, /*U+0026*/ /**/ + 0x0027, /*U+0027*/ /**/ + 0x0028, /*U+0028*/ /**/ + 0x0029, /*U+0029*/ /**/ + 0x002A, /*U+002A*/ /**/ + 0x002B, /*U+002B*/ /**/ + 0x002C, /*U+002C*/ /**/ + 0x002D, /*U+002D*/ /**/ + 0x002E, /*U+002E*/ /**/ + 0x002F, /*U+002F*/ /**/ + 0x0030, /*U+0030*/ /**/ + 0x0031, /*U+0031*/ /**/ + 0x0032, /*U+0032*/ /**/ + 0x0033, /*U+0033*/ /**/ + 0x0034, /*U+0034*/ /**/ + 0x0035, /*U+0035*/ /**/ + 0x0036, /*U+0036*/ /**/ + 0x0037, /*U+0037*/ /**/ + 0x0038, /*U+0038*/ /**/ + 0x0039, /*U+0039*/ /**/ + 0x003A, /*U+003A*/ /**/ + 0x003B, /*U+003B*/ /**/ + 0x003C, /*U+003C*/ /**/ + 0x003D, /*U+003D*/ /**/ + 0x003E, /*U+003E*/ /**/ + 0x003F, /*U+003F*/ /**/ + 0x0040, /*U+0040*/ /**/ + 0x0061, /*U+0041*/ /*LATIN CAPITAL LETTER A*/ + 0x0062, /*U+0042*/ /*LATIN CAPITAL LETTER B*/ + 0x0063, /*U+0043*/ /*LATIN CAPITAL LETTER C*/ + 0x0064, /*U+0044*/ /*LATIN CAPITAL LETTER D*/ + 0x0065, /*U+0045*/ /*LATIN CAPITAL LETTER E*/ + 0x0066, /*U+0046*/ /*LATIN CAPITAL LETTER F*/ + 0x0067, /*U+0047*/ /*LATIN CAPITAL LETTER G*/ + 0x0068, /*U+0048*/ /*LATIN CAPITAL LETTER H*/ + 0x0069, /*U+0049*/ /*LATIN CAPITAL LETTER I*/ + 0x006A, /*U+004A*/ /*LATIN CAPITAL LETTER J*/ + 0x006B, /*U+004B*/ /*LATIN CAPITAL LETTER K*/ + 0x006C, /*U+004C*/ /*LATIN CAPITAL LETTER L*/ + 0x006D, /*U+004D*/ /*LATIN CAPITAL LETTER M*/ + 0x006E, /*U+004E*/ /*LATIN CAPITAL LETTER N*/ + 0x006F, /*U+004F*/ /*LATIN CAPITAL LETTER O*/ + 0x0070, /*U+0050*/ /*LATIN CAPITAL LETTER P*/ + 0x0071, /*U+0051*/ /*LATIN CAPITAL LETTER Q*/ + 0x0072, /*U+0052*/ /*LATIN CAPITAL LETTER R*/ + 0x0073, /*U+0053*/ /*LATIN CAPITAL LETTER S*/ + 0x0074, /*U+0054*/ /*LATIN CAPITAL LETTER T*/ + 0x0075, /*U+0055*/ /*LATIN CAPITAL LETTER U*/ + 0x0076, /*U+0056*/ /*LATIN CAPITAL LETTER V*/ + 0x0077, /*U+0057*/ /*LATIN CAPITAL LETTER W*/ + 0x0078, /*U+0058*/ /*LATIN CAPITAL LETTER X*/ + 0x0079, /*U+0059*/ /*LATIN CAPITAL LETTER Y*/ + 0x007A, /*U+005A*/ /*LATIN CAPITAL LETTER Z*/ + 0x005B, /*U+005B*/ /**/ + 0x005C, /*U+005C*/ /**/ + 0x005D, /*U+005D*/ /**/ + 0x005E, /*U+005E*/ /**/ + 0x005F, /*U+005F*/ /**/ + 0x0060, /*U+0060*/ /**/ + 0x0061, /*U+0061*/ /**/ + 0x0062, /*U+0062*/ /**/ + 0x0063, /*U+0063*/ /**/ + 0x0064, /*U+0064*/ /**/ + 0x0065, /*U+0065*/ /**/ + 0x0066, /*U+0066*/ /**/ + 0x0067, /*U+0067*/ /**/ + 0x0068, /*U+0068*/ /**/ + 0x0069, /*U+0069*/ /**/ + 0x006A, /*U+006A*/ /**/ + 0x006B, /*U+006B*/ /**/ + 0x006C, /*U+006C*/ /**/ + 0x006D, /*U+006D*/ /**/ + 0x006E, /*U+006E*/ /**/ + 0x006F, /*U+006F*/ /**/ + 0x0070, /*U+0070*/ /**/ + 0x0071, /*U+0071*/ /**/ + 0x0072, /*U+0072*/ /**/ + 0x0073, /*U+0073*/ /**/ + 0x0074, /*U+0074*/ /**/ + 0x0075, /*U+0075*/ /**/ + 0x0076, /*U+0076*/ /**/ + 0x0077, /*U+0077*/ /**/ + 0x0078, /*U+0078*/ /**/ + 0x0079, /*U+0079*/ /**/ + 0x007A, /*U+007A*/ /**/ + 0x007B, /*U+007B*/ /**/ + 0x007C, /*U+007C*/ /**/ + 0x007D, /*U+007D*/ /**/ + 0x007E, /*U+007E*/ /**/ + 0x007F, /*U+007F*/ /**/ +}; + +static const uint16_t lower_table_2[448] = { + 0x00E0, /*U+00C0*/ /*LATIN CAPITAL LETTER A WITH GRAVE*/ + 0x00E1, /*U+00C1*/ /*LATIN CAPITAL LETTER A WITH ACUTE*/ + 0x00E2, /*U+00C2*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX*/ + 0x00E3, /*U+00C3*/ /*LATIN CAPITAL LETTER A WITH TILDE*/ + 0x00E4, /*U+00C4*/ /*LATIN CAPITAL LETTER A WITH DIAERESIS*/ + 0x00E5, /*U+00C5*/ /*LATIN CAPITAL LETTER A WITH RING ABOVE*/ + 0x00E6, /*U+00C6*/ /*LATIN CAPITAL LETTER AE*/ + 0x00E7, /*U+00C7*/ /*LATIN CAPITAL LETTER C WITH CEDILLA*/ + 0x00E8, /*U+00C8*/ /*LATIN CAPITAL LETTER E WITH GRAVE*/ + 0x00E9, /*U+00C9*/ /*LATIN CAPITAL LETTER E WITH ACUTE*/ + 0x00EA, /*U+00CA*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX*/ + 0x00EB, /*U+00CB*/ /*LATIN CAPITAL LETTER E WITH DIAERESIS*/ + 0x00EC, /*U+00CC*/ /*LATIN CAPITAL LETTER I WITH GRAVE*/ + 0x00ED, /*U+00CD*/ /*LATIN CAPITAL LETTER I WITH ACUTE*/ + 0x00EE, /*U+00CE*/ /*LATIN CAPITAL LETTER I WITH CIRCUMFLEX*/ + 0x00EF, /*U+00CF*/ /*LATIN CAPITAL LETTER I WITH DIAERESIS*/ + 0x00F0, /*U+00D0*/ /*LATIN CAPITAL LETTER ETH*/ + 0x00F1, /*U+00D1*/ /*LATIN CAPITAL LETTER N WITH TILDE*/ + 0x00F2, /*U+00D2*/ /*LATIN CAPITAL LETTER O WITH GRAVE*/ + 0x00F3, /*U+00D3*/ /*LATIN CAPITAL LETTER O WITH ACUTE*/ + 0x00F4, /*U+00D4*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX*/ + 0x00F5, /*U+00D5*/ /*LATIN CAPITAL LETTER O WITH TILDE*/ + 0x00F6, /*U+00D6*/ /*LATIN CAPITAL LETTER O WITH DIAERESIS*/ + 0x00D7, /*U+00D7*/ /**/ + 0x00F8, /*U+00D8*/ /*LATIN CAPITAL LETTER O WITH STROKE*/ + 0x00F9, /*U+00D9*/ /*LATIN CAPITAL LETTER U WITH GRAVE*/ + 0x00FA, /*U+00DA*/ /*LATIN CAPITAL LETTER U WITH ACUTE*/ + 0x00FB, /*U+00DB*/ /*LATIN CAPITAL LETTER U WITH CIRCUMFLEX*/ + 0x00FC, /*U+00DC*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS*/ + 0x00FD, /*U+00DD*/ /*LATIN CAPITAL LETTER Y WITH ACUTE*/ + 0x00FE, /*U+00DE*/ /*LATIN CAPITAL LETTER THORN*/ + 0x00DF, /*U+00DF*/ /**/ + 0x00E0, /*U+00E0*/ /**/ + 0x00E1, /*U+00E1*/ /**/ + 0x00E2, /*U+00E2*/ /**/ + 0x00E3, /*U+00E3*/ /**/ + 0x00E4, /*U+00E4*/ /**/ + 0x00E5, /*U+00E5*/ /**/ + 0x00E6, /*U+00E6*/ /**/ + 0x00E7, /*U+00E7*/ /**/ + 0x00E8, /*U+00E8*/ /**/ + 0x00E9, /*U+00E9*/ /**/ + 0x00EA, /*U+00EA*/ /**/ + 0x00EB, /*U+00EB*/ /**/ + 0x00EC, /*U+00EC*/ /**/ + 0x00ED, /*U+00ED*/ /**/ + 0x00EE, /*U+00EE*/ /**/ + 0x00EF, /*U+00EF*/ /**/ + 0x00F0, /*U+00F0*/ /**/ + 0x00F1, /*U+00F1*/ /**/ + 0x00F2, /*U+00F2*/ /**/ + 0x00F3, /*U+00F3*/ /**/ + 0x00F4, /*U+00F4*/ /**/ + 0x00F5, /*U+00F5*/ /**/ + 0x00F6, /*U+00F6*/ /**/ + 0x00F7, /*U+00F7*/ /**/ + 0x00F8, /*U+00F8*/ /**/ + 0x00F9, /*U+00F9*/ /**/ + 0x00FA, /*U+00FA*/ /**/ + 0x00FB, /*U+00FB*/ /**/ + 0x00FC, /*U+00FC*/ /**/ + 0x00FD, /*U+00FD*/ /**/ + 0x00FE, /*U+00FE*/ /**/ + 0x00FF, /*U+00FF*/ /**/ + 0x0101, /*U+0100*/ /*LATIN CAPITAL LETTER A WITH MACRON*/ + 0x0101, /*U+0101*/ /**/ + 0x0103, /*U+0102*/ /*LATIN CAPITAL LETTER A WITH BREVE*/ + 0x0103, /*U+0103*/ /**/ + 0x0105, /*U+0104*/ /*LATIN CAPITAL LETTER A WITH OGONEK*/ + 0x0105, /*U+0105*/ /**/ + 0x0107, /*U+0106*/ /*LATIN CAPITAL LETTER C WITH ACUTE*/ + 0x0107, /*U+0107*/ /**/ + 0x0109, /*U+0108*/ /*LATIN CAPITAL LETTER C WITH CIRCUMFLEX*/ + 0x0109, /*U+0109*/ /**/ + 0x010B, /*U+010A*/ /*LATIN CAPITAL LETTER C WITH DOT ABOVE*/ + 0x010B, /*U+010B*/ /**/ + 0x010D, /*U+010C*/ /*LATIN CAPITAL LETTER C WITH CARON*/ + 0x010D, /*U+010D*/ /**/ + 0x010F, /*U+010E*/ /*LATIN CAPITAL LETTER D WITH CARON*/ + 0x010F, /*U+010F*/ /**/ + 0x0111, /*U+0110*/ /*LATIN CAPITAL LETTER D WITH STROKE*/ + 0x0111, /*U+0111*/ /**/ + 0x0113, /*U+0112*/ /*LATIN CAPITAL LETTER E WITH MACRON*/ + 0x0113, /*U+0113*/ /**/ + 0x0115, /*U+0114*/ /*LATIN CAPITAL LETTER E WITH BREVE*/ + 0x0115, /*U+0115*/ /**/ + 0x0117, /*U+0116*/ /*LATIN CAPITAL LETTER E WITH DOT ABOVE*/ + 0x0117, /*U+0117*/ /**/ + 0x0119, /*U+0118*/ /*LATIN CAPITAL LETTER E WITH OGONEK*/ + 0x0119, /*U+0119*/ /**/ + 0x011B, /*U+011A*/ /*LATIN CAPITAL LETTER E WITH CARON*/ + 0x011B, /*U+011B*/ /**/ + 0x011D, /*U+011C*/ /*LATIN CAPITAL LETTER G WITH CIRCUMFLEX*/ + 0x011D, /*U+011D*/ /**/ + 0x011F, /*U+011E*/ /*LATIN CAPITAL LETTER G WITH BREVE*/ + 0x011F, /*U+011F*/ /**/ + 0x0121, /*U+0120*/ /*LATIN CAPITAL LETTER G WITH DOT ABOVE*/ + 0x0121, /*U+0121*/ /**/ + 0x0123, /*U+0122*/ /*LATIN CAPITAL LETTER G WITH CEDILLA*/ + 0x0123, /*U+0123*/ /**/ + 0x0125, /*U+0124*/ /*LATIN CAPITAL LETTER H WITH CIRCUMFLEX*/ + 0x0125, /*U+0125*/ /**/ + 0x0127, /*U+0126*/ /*LATIN CAPITAL LETTER H WITH STROKE*/ + 0x0127, /*U+0127*/ /**/ + 0x0129, /*U+0128*/ /*LATIN CAPITAL LETTER I WITH TILDE*/ + 0x0129, /*U+0129*/ /**/ + 0x012B, /*U+012A*/ /*LATIN CAPITAL LETTER I WITH MACRON*/ + 0x012B, /*U+012B*/ /**/ + 0x012D, /*U+012C*/ /*LATIN CAPITAL LETTER I WITH BREVE*/ + 0x012D, /*U+012D*/ /**/ + 0x012F, /*U+012E*/ /*LATIN CAPITAL LETTER I WITH OGONEK*/ + 0x012F, /*U+012F*/ /**/ + 0x0069, /*U+0130*/ /*LATIN CAPITAL LETTER I WITH DOT ABOVE*/ + 0x0131, /*U+0131*/ /**/ + 0x0133, /*U+0132*/ /*LATIN CAPITAL LIGATURE IJ*/ + 0x0133, /*U+0133*/ /**/ + 0x0135, /*U+0134*/ /*LATIN CAPITAL LETTER J WITH CIRCUMFLEX*/ + 0x0135, /*U+0135*/ /**/ + 0x0137, /*U+0136*/ /*LATIN CAPITAL LETTER K WITH CEDILLA*/ + 0x0137, /*U+0137*/ /**/ + 0x0138, /*U+0138*/ /**/ + 0x013A, /*U+0139*/ /*LATIN CAPITAL LETTER L WITH ACUTE*/ + 0x013A, /*U+013A*/ /**/ + 0x013C, /*U+013B*/ /*LATIN CAPITAL LETTER L WITH CEDILLA*/ + 0x013C, /*U+013C*/ /**/ + 0x013E, /*U+013D*/ /*LATIN CAPITAL LETTER L WITH CARON*/ + 0x013E, /*U+013E*/ /**/ + 0x0140, /*U+013F*/ /*LATIN CAPITAL LETTER L WITH MIDDLE DOT*/ + 0x0140, /*U+0140*/ /**/ + 0x0142, /*U+0141*/ /*LATIN CAPITAL LETTER L WITH STROKE*/ + 0x0142, /*U+0142*/ /**/ + 0x0144, /*U+0143*/ /*LATIN CAPITAL LETTER N WITH ACUTE*/ + 0x0144, /*U+0144*/ /**/ + 0x0146, /*U+0145*/ /*LATIN CAPITAL LETTER N WITH CEDILLA*/ + 0x0146, /*U+0146*/ /**/ + 0x0148, /*U+0147*/ /*LATIN CAPITAL LETTER N WITH CARON*/ + 0x0148, /*U+0148*/ /**/ + 0x0149, /*U+0149*/ /**/ + 0x014B, /*U+014A*/ /*LATIN CAPITAL LETTER ENG*/ + 0x014B, /*U+014B*/ /**/ + 0x014D, /*U+014C*/ /*LATIN CAPITAL LETTER O WITH MACRON*/ + 0x014D, /*U+014D*/ /**/ + 0x014F, /*U+014E*/ /*LATIN CAPITAL LETTER O WITH BREVE*/ + 0x014F, /*U+014F*/ /**/ + 0x0151, /*U+0150*/ /*LATIN CAPITAL LETTER O WITH DOUBLE ACUTE*/ + 0x0151, /*U+0151*/ /**/ + 0x0153, /*U+0152*/ /*LATIN CAPITAL LIGATURE OE*/ + 0x0153, /*U+0153*/ /**/ + 0x0155, /*U+0154*/ /*LATIN CAPITAL LETTER R WITH ACUTE*/ + 0x0155, /*U+0155*/ /**/ + 0x0157, /*U+0156*/ /*LATIN CAPITAL LETTER R WITH CEDILLA*/ + 0x0157, /*U+0157*/ /**/ + 0x0159, /*U+0158*/ /*LATIN CAPITAL LETTER R WITH CARON*/ + 0x0159, /*U+0159*/ /**/ + 0x015B, /*U+015A*/ /*LATIN CAPITAL LETTER S WITH ACUTE*/ + 0x015B, /*U+015B*/ /**/ + 0x015D, /*U+015C*/ /*LATIN CAPITAL LETTER S WITH CIRCUMFLEX*/ + 0x015D, /*U+015D*/ /**/ + 0x015F, /*U+015E*/ /*LATIN CAPITAL LETTER S WITH CEDILLA*/ + 0x015F, /*U+015F*/ /**/ + 0x0161, /*U+0160*/ /*LATIN CAPITAL LETTER S WITH CARON*/ + 0x0161, /*U+0161*/ /**/ + 0x0163, /*U+0162*/ /*LATIN CAPITAL LETTER T WITH CEDILLA*/ + 0x0163, /*U+0163*/ /**/ + 0x0165, /*U+0164*/ /*LATIN CAPITAL LETTER T WITH CARON*/ + 0x0165, /*U+0165*/ /**/ + 0x0167, /*U+0166*/ /*LATIN CAPITAL LETTER T WITH STROKE*/ + 0x0167, /*U+0167*/ /**/ + 0x0169, /*U+0168*/ /*LATIN CAPITAL LETTER U WITH TILDE*/ + 0x0169, /*U+0169*/ /**/ + 0x016B, /*U+016A*/ /*LATIN CAPITAL LETTER U WITH MACRON*/ + 0x016B, /*U+016B*/ /**/ + 0x016D, /*U+016C*/ /*LATIN CAPITAL LETTER U WITH BREVE*/ + 0x016D, /*U+016D*/ /**/ + 0x016F, /*U+016E*/ /*LATIN CAPITAL LETTER U WITH RING ABOVE*/ + 0x016F, /*U+016F*/ /**/ + 0x0171, /*U+0170*/ /*LATIN CAPITAL LETTER U WITH DOUBLE ACUTE*/ + 0x0171, /*U+0171*/ /**/ + 0x0173, /*U+0172*/ /*LATIN CAPITAL LETTER U WITH OGONEK*/ + 0x0173, /*U+0173*/ /**/ + 0x0175, /*U+0174*/ /*LATIN CAPITAL LETTER W WITH CIRCUMFLEX*/ + 0x0175, /*U+0175*/ /**/ + 0x0177, /*U+0176*/ /*LATIN CAPITAL LETTER Y WITH CIRCUMFLEX*/ + 0x0177, /*U+0177*/ /**/ + 0x00FF, /*U+0178*/ /*LATIN CAPITAL LETTER Y WITH DIAERESIS*/ + 0x017A, /*U+0179*/ /*LATIN CAPITAL LETTER Z WITH ACUTE*/ + 0x017A, /*U+017A*/ /**/ + 0x017C, /*U+017B*/ /*LATIN CAPITAL LETTER Z WITH DOT ABOVE*/ + 0x017C, /*U+017C*/ /**/ + 0x017E, /*U+017D*/ /*LATIN CAPITAL LETTER Z WITH CARON*/ + 0x017E, /*U+017E*/ /**/ + 0x017F, /*U+017F*/ /**/ + 0x0180, /*U+0180*/ /**/ + 0x0253, /*U+0181*/ /*LATIN CAPITAL LETTER B WITH HOOK*/ + 0x0183, /*U+0182*/ /*LATIN CAPITAL LETTER B WITH TOPBAR*/ + 0x0183, /*U+0183*/ /**/ + 0x0185, /*U+0184*/ /*LATIN CAPITAL LETTER TONE SIX*/ + 0x0185, /*U+0185*/ /**/ + 0x0254, /*U+0186*/ /*LATIN CAPITAL LETTER OPEN O*/ + 0x0188, /*U+0187*/ /*LATIN CAPITAL LETTER C WITH HOOK*/ + 0x0188, /*U+0188*/ /**/ + 0x0256, /*U+0189*/ /*LATIN CAPITAL LETTER AFRICAN D*/ + 0x0257, /*U+018A*/ /*LATIN CAPITAL LETTER D WITH HOOK*/ + 0x018C, /*U+018B*/ /*LATIN CAPITAL LETTER D WITH TOPBAR*/ + 0x018C, /*U+018C*/ /**/ + 0x018D, /*U+018D*/ /**/ + 0x01DD, /*U+018E*/ /*LATIN CAPITAL LETTER REVERSED E*/ + 0x0259, /*U+018F*/ /*LATIN CAPITAL LETTER SCHWA*/ + 0x025B, /*U+0190*/ /*LATIN CAPITAL LETTER OPEN E*/ + 0x0192, /*U+0191*/ /*LATIN CAPITAL LETTER F WITH HOOK*/ + 0x0192, /*U+0192*/ /**/ + 0x0260, /*U+0193*/ /*LATIN CAPITAL LETTER G WITH HOOK*/ + 0x0263, /*U+0194*/ /*LATIN CAPITAL LETTER GAMMA*/ + 0x0195, /*U+0195*/ /**/ + 0x0269, /*U+0196*/ /*LATIN CAPITAL LETTER IOTA*/ + 0x0268, /*U+0197*/ /*LATIN CAPITAL LETTER I WITH STROKE*/ + 0x0199, /*U+0198*/ /*LATIN CAPITAL LETTER K WITH HOOK*/ + 0x0199, /*U+0199*/ /**/ + 0x019A, /*U+019A*/ /**/ + 0x019B, /*U+019B*/ /**/ + 0x026F, /*U+019C*/ /*LATIN CAPITAL LETTER TURNED M*/ + 0x0272, /*U+019D*/ /*LATIN CAPITAL LETTER N WITH LEFT HOOK*/ + 0x019E, /*U+019E*/ /**/ + 0x0275, /*U+019F*/ /*LATIN CAPITAL LETTER O WITH MIDDLE TILDE*/ + 0x01A1, /*U+01A0*/ /*LATIN CAPITAL LETTER O WITH HORN*/ + 0x01A1, /*U+01A1*/ /**/ + 0x01A3, /*U+01A2*/ /*LATIN CAPITAL LETTER OI*/ + 0x01A3, /*U+01A3*/ /**/ + 0x01A5, /*U+01A4*/ /*LATIN CAPITAL LETTER P WITH HOOK*/ + 0x01A5, /*U+01A5*/ /**/ + 0x0280, /*U+01A6*/ /*LATIN LETTER YR*/ + 0x01A8, /*U+01A7*/ /*LATIN CAPITAL LETTER TONE TWO*/ + 0x01A8, /*U+01A8*/ /**/ + 0x0283, /*U+01A9*/ /*LATIN CAPITAL LETTER ESH*/ + 0x01AA, /*U+01AA*/ /**/ + 0x01AB, /*U+01AB*/ /**/ + 0x01AD, /*U+01AC*/ /*LATIN CAPITAL LETTER T WITH HOOK*/ + 0x01AD, /*U+01AD*/ /**/ + 0x0288, /*U+01AE*/ /*LATIN CAPITAL LETTER T WITH RETROFLEX HOOK*/ + 0x01B0, /*U+01AF*/ /*LATIN CAPITAL LETTER U WITH HORN*/ + 0x01B0, /*U+01B0*/ /**/ + 0x028A, /*U+01B1*/ /*LATIN CAPITAL LETTER UPSILON*/ + 0x028B, /*U+01B2*/ /*LATIN CAPITAL LETTER V WITH HOOK*/ + 0x01B4, /*U+01B3*/ /*LATIN CAPITAL LETTER Y WITH HOOK*/ + 0x01B4, /*U+01B4*/ /**/ + 0x01B6, /*U+01B5*/ /*LATIN CAPITAL LETTER Z WITH STROKE*/ + 0x01B6, /*U+01B6*/ /**/ + 0x0292, /*U+01B7*/ /*LATIN CAPITAL LETTER EZH*/ + 0x01B9, /*U+01B8*/ /*LATIN CAPITAL LETTER EZH REVERSED*/ + 0x01B9, /*U+01B9*/ /**/ + 0x01BA, /*U+01BA*/ /**/ + 0x01BB, /*U+01BB*/ /**/ + 0x01BD, /*U+01BC*/ /*LATIN CAPITAL LETTER TONE FIVE*/ + 0x01BD, /*U+01BD*/ /**/ + 0x01BE, /*U+01BE*/ /**/ + 0x01BF, /*U+01BF*/ /**/ + 0x01C0, /*U+01C0*/ /**/ + 0x01C1, /*U+01C1*/ /**/ + 0x01C2, /*U+01C2*/ /**/ + 0x01C3, /*U+01C3*/ /**/ + 0x01C6, /*U+01C4*/ /*LATIN CAPITAL LETTER DZ WITH CARON*/ + 0x01C6, /*U+01C5*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON*/ + 0x01C6, /*U+01C6*/ /**/ + 0x01C9, /*U+01C7*/ /*LATIN CAPITAL LETTER LJ*/ + 0x01C9, /*U+01C8*/ /*LATIN CAPITAL LETTER L WITH SMALL LETTER J*/ + 0x01C9, /*U+01C9*/ /**/ + 0x01CC, /*U+01CA*/ /*LATIN CAPITAL LETTER NJ*/ + 0x01CC, /*U+01CB*/ /*LATIN CAPITAL LETTER N WITH SMALL LETTER J*/ + 0x01CC, /*U+01CC*/ /**/ + 0x01CE, /*U+01CD*/ /*LATIN CAPITAL LETTER A WITH CARON*/ + 0x01CE, /*U+01CE*/ /**/ + 0x01D0, /*U+01CF*/ /*LATIN CAPITAL LETTER I WITH CARON*/ + 0x01D0, /*U+01D0*/ /**/ + 0x01D2, /*U+01D1*/ /*LATIN CAPITAL LETTER O WITH CARON*/ + 0x01D2, /*U+01D2*/ /**/ + 0x01D4, /*U+01D3*/ /*LATIN CAPITAL LETTER U WITH CARON*/ + 0x01D4, /*U+01D4*/ /**/ + 0x01D6, /*U+01D5*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON*/ + 0x01D6, /*U+01D6*/ /**/ + 0x01D8, /*U+01D7*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE*/ + 0x01D8, /*U+01D8*/ /**/ + 0x01DA, /*U+01D9*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON*/ + 0x01DA, /*U+01DA*/ /**/ + 0x01DC, /*U+01DB*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE*/ + 0x01DC, /*U+01DC*/ /**/ + 0x01DD, /*U+01DD*/ /**/ + 0x01DF, /*U+01DE*/ /*LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON*/ + 0x01DF, /*U+01DF*/ /**/ + 0x01E1, /*U+01E0*/ /*LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON*/ + 0x01E1, /*U+01E1*/ /**/ + 0x01E3, /*U+01E2*/ /*LATIN CAPITAL LETTER AE WITH MACRON*/ + 0x01E3, /*U+01E3*/ /**/ + 0x01E5, /*U+01E4*/ /*LATIN CAPITAL LETTER G WITH STROKE*/ + 0x01E5, /*U+01E5*/ /**/ + 0x01E7, /*U+01E6*/ /*LATIN CAPITAL LETTER G WITH CARON*/ + 0x01E7, /*U+01E7*/ /**/ + 0x01E9, /*U+01E8*/ /*LATIN CAPITAL LETTER K WITH CARON*/ + 0x01E9, /*U+01E9*/ /**/ + 0x01EB, /*U+01EA*/ /*LATIN CAPITAL LETTER O WITH OGONEK*/ + 0x01EB, /*U+01EB*/ /**/ + 0x01ED, /*U+01EC*/ /*LATIN CAPITAL LETTER O WITH OGONEK AND MACRON*/ + 0x01ED, /*U+01ED*/ /**/ + 0x01EF, /*U+01EE*/ /*LATIN CAPITAL LETTER EZH WITH CARON*/ + 0x01EF, /*U+01EF*/ /**/ + 0x01F0, /*U+01F0*/ /**/ + 0x01F3, /*U+01F1*/ /*LATIN CAPITAL LETTER DZ*/ + 0x01F3, /*U+01F2*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z*/ + 0x01F3, /*U+01F3*/ /**/ + 0x01F5, /*U+01F4*/ /*LATIN CAPITAL LETTER G WITH ACUTE*/ + 0x01F5, /*U+01F5*/ /**/ + 0x0195, /*U+01F6*/ /*LATIN CAPITAL LETTER HWAIR*/ + 0x01BF, /*U+01F7*/ /*LATIN CAPITAL LETTER WYNN*/ + 0x01F9, /*U+01F8*/ /*LATIN CAPITAL LETTER N WITH GRAVE*/ + 0x01F9, /*U+01F9*/ /**/ + 0x01FB, /*U+01FA*/ /*LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE*/ + 0x01FB, /*U+01FB*/ /**/ + 0x01FD, /*U+01FC*/ /*LATIN CAPITAL LETTER AE WITH ACUTE*/ + 0x01FD, /*U+01FD*/ /**/ + 0x01FF, /*U+01FE*/ /*LATIN CAPITAL LETTER O WITH STROKE AND ACUTE*/ + 0x01FF, /*U+01FF*/ /**/ + 0x0201, /*U+0200*/ /*LATIN CAPITAL LETTER A WITH DOUBLE GRAVE*/ + 0x0201, /*U+0201*/ /**/ + 0x0203, /*U+0202*/ /*LATIN CAPITAL LETTER A WITH INVERTED BREVE*/ + 0x0203, /*U+0203*/ /**/ + 0x0205, /*U+0204*/ /*LATIN CAPITAL LETTER E WITH DOUBLE GRAVE*/ + 0x0205, /*U+0205*/ /**/ + 0x0207, /*U+0206*/ /*LATIN CAPITAL LETTER E WITH INVERTED BREVE*/ + 0x0207, /*U+0207*/ /**/ + 0x0209, /*U+0208*/ /*LATIN CAPITAL LETTER I WITH DOUBLE GRAVE*/ + 0x0209, /*U+0209*/ /**/ + 0x020B, /*U+020A*/ /*LATIN CAPITAL LETTER I WITH INVERTED BREVE*/ + 0x020B, /*U+020B*/ /**/ + 0x020D, /*U+020C*/ /*LATIN CAPITAL LETTER O WITH DOUBLE GRAVE*/ + 0x020D, /*U+020D*/ /**/ + 0x020F, /*U+020E*/ /*LATIN CAPITAL LETTER O WITH INVERTED BREVE*/ + 0x020F, /*U+020F*/ /**/ + 0x0211, /*U+0210*/ /*LATIN CAPITAL LETTER R WITH DOUBLE GRAVE*/ + 0x0211, /*U+0211*/ /**/ + 0x0213, /*U+0212*/ /*LATIN CAPITAL LETTER R WITH INVERTED BREVE*/ + 0x0213, /*U+0213*/ /**/ + 0x0215, /*U+0214*/ /*LATIN CAPITAL LETTER U WITH DOUBLE GRAVE*/ + 0x0215, /*U+0215*/ /**/ + 0x0217, /*U+0216*/ /*LATIN CAPITAL LETTER U WITH INVERTED BREVE*/ + 0x0217, /*U+0217*/ /**/ + 0x0219, /*U+0218*/ /*LATIN CAPITAL LETTER S WITH COMMA BELOW*/ + 0x0219, /*U+0219*/ /**/ + 0x021B, /*U+021A*/ /*LATIN CAPITAL LETTER T WITH COMMA BELOW*/ + 0x021B, /*U+021B*/ /**/ + 0x021D, /*U+021C*/ /*LATIN CAPITAL LETTER YOGH*/ + 0x021D, /*U+021D*/ /**/ + 0x021F, /*U+021E*/ /*LATIN CAPITAL LETTER H WITH CARON*/ + 0x021F, /*U+021F*/ /**/ + 0x019E, /*U+0220*/ /*LATIN CAPITAL LETTER N WITH LONG RIGHT LEG*/ + 0x0221, /*U+0221*/ /**/ + 0x0223, /*U+0222*/ /*LATIN CAPITAL LETTER OU*/ + 0x0223, /*U+0223*/ /**/ + 0x0225, /*U+0224*/ /*LATIN CAPITAL LETTER Z WITH HOOK*/ + 0x0225, /*U+0225*/ /**/ + 0x0227, /*U+0226*/ /*LATIN CAPITAL LETTER A WITH DOT ABOVE*/ + 0x0227, /*U+0227*/ /**/ + 0x0229, /*U+0228*/ /*LATIN CAPITAL LETTER E WITH CEDILLA*/ + 0x0229, /*U+0229*/ /**/ + 0x022B, /*U+022A*/ /*LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON*/ + 0x022B, /*U+022B*/ /**/ + 0x022D, /*U+022C*/ /*LATIN CAPITAL LETTER O WITH TILDE AND MACRON*/ + 0x022D, /*U+022D*/ /**/ + 0x022F, /*U+022E*/ /*LATIN CAPITAL LETTER O WITH DOT ABOVE*/ + 0x022F, /*U+022F*/ /**/ + 0x0231, /*U+0230*/ /*LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON*/ + 0x0231, /*U+0231*/ /**/ + 0x0233, /*U+0232*/ /*LATIN CAPITAL LETTER Y WITH MACRON*/ + 0x0233, /*U+0233*/ /**/ + 0x0234, /*U+0234*/ /**/ + 0x0235, /*U+0235*/ /**/ + 0x0236, /*U+0236*/ /**/ + 0x0237, /*U+0237*/ /**/ + 0x0238, /*U+0238*/ /**/ + 0x0239, /*U+0239*/ /**/ + 0x2C65, /*U+023A*/ /*LATIN CAPITAL LETTER A WITH STROKE*/ + 0x023C, /*U+023B*/ /*LATIN CAPITAL LETTER C WITH STROKE*/ + 0x023C, /*U+023C*/ /**/ + 0x019A, /*U+023D*/ /*LATIN CAPITAL LETTER L WITH BAR*/ + 0x2C66, /*U+023E*/ /*LATIN CAPITAL LETTER T WITH DIAGONAL STROKE*/ + 0x023F, /*U+023F*/ /**/ + 0x0240, /*U+0240*/ /**/ + 0x0242, /*U+0241*/ /*LATIN CAPITAL LETTER GLOTTAL STOP*/ + 0x0242, /*U+0242*/ /**/ + 0x0180, /*U+0243*/ /*LATIN CAPITAL LETTER B WITH STROKE*/ + 0x0289, /*U+0244*/ /*LATIN CAPITAL LETTER U BAR*/ + 0x028C, /*U+0245*/ /*LATIN CAPITAL LETTER TURNED V*/ + 0x0247, /*U+0246*/ /*LATIN CAPITAL LETTER E WITH STROKE*/ + 0x0247, /*U+0247*/ /**/ + 0x0249, /*U+0248*/ /*LATIN CAPITAL LETTER J WITH STROKE*/ + 0x0249, /*U+0249*/ /**/ + 0x024B, /*U+024A*/ /*LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL*/ + 0x024B, /*U+024B*/ /**/ + 0x024D, /*U+024C*/ /*LATIN CAPITAL LETTER R WITH STROKE*/ + 0x024D, /*U+024D*/ /**/ + 0x024F, /*U+024E*/ /*LATIN CAPITAL LETTER Y WITH STROKE*/ + 0x024F, /*U+024F*/ /**/ + 0x0250, /*U+0250*/ /**/ + 0x0251, /*U+0251*/ /**/ + 0x0252, /*U+0252*/ /**/ + 0x0253, /*U+0253*/ /**/ + 0x0254, /*U+0254*/ /**/ + 0x0255, /*U+0255*/ /**/ + 0x0256, /*U+0256*/ /**/ + 0x0257, /*U+0257*/ /**/ + 0x0258, /*U+0258*/ /**/ + 0x0259, /*U+0259*/ /**/ + 0x025A, /*U+025A*/ /**/ + 0x025B, /*U+025B*/ /**/ + 0x025C, /*U+025C*/ /**/ + 0x025D, /*U+025D*/ /**/ + 0x025E, /*U+025E*/ /**/ + 0x025F, /*U+025F*/ /**/ + 0x0260, /*U+0260*/ /**/ + 0x0261, /*U+0261*/ /**/ + 0x0262, /*U+0262*/ /**/ + 0x0263, /*U+0263*/ /**/ + 0x0264, /*U+0264*/ /**/ + 0x0265, /*U+0265*/ /**/ + 0x0266, /*U+0266*/ /**/ + 0x0267, /*U+0267*/ /**/ + 0x0268, /*U+0268*/ /**/ + 0x0269, /*U+0269*/ /**/ + 0x026A, /*U+026A*/ /**/ + 0x026B, /*U+026B*/ /**/ + 0x026C, /*U+026C*/ /**/ + 0x026D, /*U+026D*/ /**/ + 0x026E, /*U+026E*/ /**/ + 0x026F, /*U+026F*/ /**/ + 0x0270, /*U+0270*/ /**/ + 0x0271, /*U+0271*/ /**/ + 0x0272, /*U+0272*/ /**/ + 0x0273, /*U+0273*/ /**/ + 0x0274, /*U+0274*/ /**/ + 0x0275, /*U+0275*/ /**/ + 0x0276, /*U+0276*/ /**/ + 0x0277, /*U+0277*/ /**/ + 0x0278, /*U+0278*/ /**/ + 0x0279, /*U+0279*/ /**/ + 0x027A, /*U+027A*/ /**/ + 0x027B, /*U+027B*/ /**/ + 0x027C, /*U+027C*/ /**/ + 0x027D, /*U+027D*/ /**/ + 0x027E, /*U+027E*/ /**/ + 0x027F, /*U+027F*/ /**/ +}; + +static const uint16_t lower_table_3[576] = { + 0x0340, /*U+0340*/ /**/ + 0x0341, /*U+0341*/ /**/ + 0x0342, /*U+0342*/ /**/ + 0x0343, /*U+0343*/ /**/ + 0x0344, /*U+0344*/ /**/ + 0x0345, /*U+0345*/ /**/ + 0x0346, /*U+0346*/ /**/ + 0x0347, /*U+0347*/ /**/ + 0x0348, /*U+0348*/ /**/ + 0x0349, /*U+0349*/ /**/ + 0x034A, /*U+034A*/ /**/ + 0x034B, /*U+034B*/ /**/ + 0x034C, /*U+034C*/ /**/ + 0x034D, /*U+034D*/ /**/ + 0x034E, /*U+034E*/ /**/ + 0x034F, /*U+034F*/ /**/ + 0x0350, /*U+0350*/ /**/ + 0x0351, /*U+0351*/ /**/ + 0x0352, /*U+0352*/ /**/ + 0x0353, /*U+0353*/ /**/ + 0x0354, /*U+0354*/ /**/ + 0x0355, /*U+0355*/ /**/ + 0x0356, /*U+0356*/ /**/ + 0x0357, /*U+0357*/ /**/ + 0x0358, /*U+0358*/ /**/ + 0x0359, /*U+0359*/ /**/ + 0x035A, /*U+035A*/ /**/ + 0x035B, /*U+035B*/ /**/ + 0x035C, /*U+035C*/ /**/ + 0x035D, /*U+035D*/ /**/ + 0x035E, /*U+035E*/ /**/ + 0x035F, /*U+035F*/ /**/ + 0x0360, /*U+0360*/ /**/ + 0x0361, /*U+0361*/ /**/ + 0x0362, /*U+0362*/ /**/ + 0x0363, /*U+0363*/ /**/ + 0x0364, /*U+0364*/ /**/ + 0x0365, /*U+0365*/ /**/ + 0x0366, /*U+0366*/ /**/ + 0x0367, /*U+0367*/ /**/ + 0x0368, /*U+0368*/ /**/ + 0x0369, /*U+0369*/ /**/ + 0x036A, /*U+036A*/ /**/ + 0x036B, /*U+036B*/ /**/ + 0x036C, /*U+036C*/ /**/ + 0x036D, /*U+036D*/ /**/ + 0x036E, /*U+036E*/ /**/ + 0x036F, /*U+036F*/ /**/ + 0x0371, /*U+0370*/ /*GREEK CAPITAL LETTER HETA*/ + 0x0371, /*U+0371*/ /**/ + 0x0373, /*U+0372*/ /*GREEK CAPITAL LETTER ARCHAIC SAMPI*/ + 0x0373, /*U+0373*/ /**/ + 0x0374, /*U+0374*/ /**/ + 0x0375, /*U+0375*/ /**/ + 0x0377, /*U+0376*/ /*GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA*/ + 0x0377, /*U+0377*/ /**/ + 0x0378, /*U+0378*/ /**/ + 0x0379, /*U+0379*/ /**/ + 0x037A, /*U+037A*/ /**/ + 0x037B, /*U+037B*/ /**/ + 0x037C, /*U+037C*/ /**/ + 0x037D, /*U+037D*/ /**/ + 0x037E, /*U+037E*/ /**/ + 0x03F3, /*U+037F*/ /*GREEK CAPITAL LETTER YOT*/ + 0x0380, /*U+0380*/ /**/ + 0x0381, /*U+0381*/ /**/ + 0x0382, /*U+0382*/ /**/ + 0x0383, /*U+0383*/ /**/ + 0x0384, /*U+0384*/ /**/ + 0x0385, /*U+0385*/ /**/ + 0x03AC, /*U+0386*/ /*GREEK CAPITAL LETTER ALPHA WITH TONOS*/ + 0x0387, /*U+0387*/ /**/ + 0x03AD, /*U+0388*/ /*GREEK CAPITAL LETTER EPSILON WITH TONOS*/ + 0x03AE, /*U+0389*/ /*GREEK CAPITAL LETTER ETA WITH TONOS*/ + 0x03AF, /*U+038A*/ /*GREEK CAPITAL LETTER IOTA WITH TONOS*/ + 0x038B, /*U+038B*/ /**/ + 0x03CC, /*U+038C*/ /*GREEK CAPITAL LETTER OMICRON WITH TONOS*/ + 0x038D, /*U+038D*/ /**/ + 0x03CD, /*U+038E*/ /*GREEK CAPITAL LETTER UPSILON WITH TONOS*/ + 0x03CE, /*U+038F*/ /*GREEK CAPITAL LETTER OMEGA WITH TONOS*/ + 0x0390, /*U+0390*/ /**/ + 0x03B1, /*U+0391*/ /*GREEK CAPITAL LETTER ALPHA*/ + 0x03B2, /*U+0392*/ /*GREEK CAPITAL LETTER BETA*/ + 0x03B3, /*U+0393*/ /*GREEK CAPITAL LETTER GAMMA*/ + 0x03B4, /*U+0394*/ /*GREEK CAPITAL LETTER DELTA*/ + 0x03B5, /*U+0395*/ /*GREEK CAPITAL LETTER EPSILON*/ + 0x03B6, /*U+0396*/ /*GREEK CAPITAL LETTER ZETA*/ + 0x03B7, /*U+0397*/ /*GREEK CAPITAL LETTER ETA*/ + 0x03B8, /*U+0398*/ /*GREEK CAPITAL LETTER THETA*/ + 0x03B9, /*U+0399*/ /*GREEK CAPITAL LETTER IOTA*/ + 0x03BA, /*U+039A*/ /*GREEK CAPITAL LETTER KAPPA*/ + 0x03BB, /*U+039B*/ /*GREEK CAPITAL LETTER LAMDA*/ + 0x03BC, /*U+039C*/ /*GREEK CAPITAL LETTER MU*/ + 0x03BD, /*U+039D*/ /*GREEK CAPITAL LETTER NU*/ + 0x03BE, /*U+039E*/ /*GREEK CAPITAL LETTER XI*/ + 0x03BF, /*U+039F*/ /*GREEK CAPITAL LETTER OMICRON*/ + 0x03C0, /*U+03A0*/ /*GREEK CAPITAL LETTER PI*/ + 0x03C1, /*U+03A1*/ /*GREEK CAPITAL LETTER RHO*/ + 0x03A2, /*U+03A2*/ /**/ + 0x03C3, /*U+03A3*/ /*GREEK CAPITAL LETTER SIGMA*/ + 0x03C4, /*U+03A4*/ /*GREEK CAPITAL LETTER TAU*/ + 0x03C5, /*U+03A5*/ /*GREEK CAPITAL LETTER UPSILON*/ + 0x03C6, /*U+03A6*/ /*GREEK CAPITAL LETTER PHI*/ + 0x03C7, /*U+03A7*/ /*GREEK CAPITAL LETTER CHI*/ + 0x03C8, /*U+03A8*/ /*GREEK CAPITAL LETTER PSI*/ + 0x03C9, /*U+03A9*/ /*GREEK CAPITAL LETTER OMEGA*/ + 0x03CA, /*U+03AA*/ /*GREEK CAPITAL LETTER IOTA WITH DIALYTIKA*/ + 0x03CB, /*U+03AB*/ /*GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA*/ + 0x03AC, /*U+03AC*/ /**/ + 0x03AD, /*U+03AD*/ /**/ + 0x03AE, /*U+03AE*/ /**/ + 0x03AF, /*U+03AF*/ /**/ + 0x03B0, /*U+03B0*/ /**/ + 0x03B1, /*U+03B1*/ /**/ + 0x03B2, /*U+03B2*/ /**/ + 0x03B3, /*U+03B3*/ /**/ + 0x03B4, /*U+03B4*/ /**/ + 0x03B5, /*U+03B5*/ /**/ + 0x03B6, /*U+03B6*/ /**/ + 0x03B7, /*U+03B7*/ /**/ + 0x03B8, /*U+03B8*/ /**/ + 0x03B9, /*U+03B9*/ /**/ + 0x03BA, /*U+03BA*/ /**/ + 0x03BB, /*U+03BB*/ /**/ + 0x03BC, /*U+03BC*/ /**/ + 0x03BD, /*U+03BD*/ /**/ + 0x03BE, /*U+03BE*/ /**/ + 0x03BF, /*U+03BF*/ /**/ + 0x03C0, /*U+03C0*/ /**/ + 0x03C1, /*U+03C1*/ /**/ + 0x03C2, /*U+03C2*/ /**/ + 0x03C3, /*U+03C3*/ /**/ + 0x03C4, /*U+03C4*/ /**/ + 0x03C5, /*U+03C5*/ /**/ + 0x03C6, /*U+03C6*/ /**/ + 0x03C7, /*U+03C7*/ /**/ + 0x03C8, /*U+03C8*/ /**/ + 0x03C9, /*U+03C9*/ /**/ + 0x03CA, /*U+03CA*/ /**/ + 0x03CB, /*U+03CB*/ /**/ + 0x03CC, /*U+03CC*/ /**/ + 0x03CD, /*U+03CD*/ /**/ + 0x03CE, /*U+03CE*/ /**/ + 0x03D7, /*U+03CF*/ /*GREEK CAPITAL KAI SYMBOL*/ + 0x03D0, /*U+03D0*/ /**/ + 0x03D1, /*U+03D1*/ /**/ + 0x03D2, /*U+03D2*/ /**/ + 0x03D3, /*U+03D3*/ /**/ + 0x03D4, /*U+03D4*/ /**/ + 0x03D5, /*U+03D5*/ /**/ + 0x03D6, /*U+03D6*/ /**/ + 0x03D7, /*U+03D7*/ /**/ + 0x03D9, /*U+03D8*/ /*GREEK LETTER ARCHAIC KOPPA*/ + 0x03D9, /*U+03D9*/ /**/ + 0x03DB, /*U+03DA*/ /*GREEK LETTER STIGMA*/ + 0x03DB, /*U+03DB*/ /**/ + 0x03DD, /*U+03DC*/ /*GREEK LETTER DIGAMMA*/ + 0x03DD, /*U+03DD*/ /**/ + 0x03DF, /*U+03DE*/ /*GREEK LETTER KOPPA*/ + 0x03DF, /*U+03DF*/ /**/ + 0x03E1, /*U+03E0*/ /*GREEK LETTER SAMPI*/ + 0x03E1, /*U+03E1*/ /**/ + 0x03E3, /*U+03E2*/ /*COPTIC CAPITAL LETTER SHEI*/ + 0x03E3, /*U+03E3*/ /**/ + 0x03E5, /*U+03E4*/ /*COPTIC CAPITAL LETTER FEI*/ + 0x03E5, /*U+03E5*/ /**/ + 0x03E7, /*U+03E6*/ /*COPTIC CAPITAL LETTER KHEI*/ + 0x03E7, /*U+03E7*/ /**/ + 0x03E9, /*U+03E8*/ /*COPTIC CAPITAL LETTER HORI*/ + 0x03E9, /*U+03E9*/ /**/ + 0x03EB, /*U+03EA*/ /*COPTIC CAPITAL LETTER GANGIA*/ + 0x03EB, /*U+03EB*/ /**/ + 0x03ED, /*U+03EC*/ /*COPTIC CAPITAL LETTER SHIMA*/ + 0x03ED, /*U+03ED*/ /**/ + 0x03EF, /*U+03EE*/ /*COPTIC CAPITAL LETTER DEI*/ + 0x03EF, /*U+03EF*/ /**/ + 0x03F0, /*U+03F0*/ /**/ + 0x03F1, /*U+03F1*/ /**/ + 0x03F2, /*U+03F2*/ /**/ + 0x03F3, /*U+03F3*/ /**/ + 0x03B8, /*U+03F4*/ /*GREEK CAPITAL THETA SYMBOL*/ + 0x03F5, /*U+03F5*/ /**/ + 0x03F6, /*U+03F6*/ /**/ + 0x03F8, /*U+03F7*/ /*GREEK CAPITAL LETTER SHO*/ + 0x03F8, /*U+03F8*/ /**/ + 0x03F2, /*U+03F9*/ /*GREEK CAPITAL LUNATE SIGMA SYMBOL*/ + 0x03FB, /*U+03FA*/ /*GREEK CAPITAL LETTER SAN*/ + 0x03FB, /*U+03FB*/ /**/ + 0x03FC, /*U+03FC*/ /**/ + 0x037B, /*U+03FD*/ /*GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL*/ + 0x037C, /*U+03FE*/ /*GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL*/ + 0x037D, /*U+03FF*/ /*GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL*/ + 0x0450, /*U+0400*/ /*CYRILLIC CAPITAL LETTER IE WITH GRAVE*/ + 0x0451, /*U+0401*/ /*CYRILLIC CAPITAL LETTER IO*/ + 0x0452, /*U+0402*/ /*CYRILLIC CAPITAL LETTER DJE*/ + 0x0453, /*U+0403*/ /*CYRILLIC CAPITAL LETTER GJE*/ + 0x0454, /*U+0404*/ /*CYRILLIC CAPITAL LETTER UKRAINIAN IE*/ + 0x0455, /*U+0405*/ /*CYRILLIC CAPITAL LETTER DZE*/ + 0x0456, /*U+0406*/ /*CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I*/ + 0x0457, /*U+0407*/ /*CYRILLIC CAPITAL LETTER YI*/ + 0x0458, /*U+0408*/ /*CYRILLIC CAPITAL LETTER JE*/ + 0x0459, /*U+0409*/ /*CYRILLIC CAPITAL LETTER LJE*/ + 0x045A, /*U+040A*/ /*CYRILLIC CAPITAL LETTER NJE*/ + 0x045B, /*U+040B*/ /*CYRILLIC CAPITAL LETTER TSHE*/ + 0x045C, /*U+040C*/ /*CYRILLIC CAPITAL LETTER KJE*/ + 0x045D, /*U+040D*/ /*CYRILLIC CAPITAL LETTER I WITH GRAVE*/ + 0x045E, /*U+040E*/ /*CYRILLIC CAPITAL LETTER SHORT U*/ + 0x045F, /*U+040F*/ /*CYRILLIC CAPITAL LETTER DZHE*/ + 0x0430, /*U+0410*/ /*CYRILLIC CAPITAL LETTER A*/ + 0x0431, /*U+0411*/ /*CYRILLIC CAPITAL LETTER BE*/ + 0x0432, /*U+0412*/ /*CYRILLIC CAPITAL LETTER VE*/ + 0x0433, /*U+0413*/ /*CYRILLIC CAPITAL LETTER GHE*/ + 0x0434, /*U+0414*/ /*CYRILLIC CAPITAL LETTER DE*/ + 0x0435, /*U+0415*/ /*CYRILLIC CAPITAL LETTER IE*/ + 0x0436, /*U+0416*/ /*CYRILLIC CAPITAL LETTER ZHE*/ + 0x0437, /*U+0417*/ /*CYRILLIC CAPITAL LETTER ZE*/ + 0x0438, /*U+0418*/ /*CYRILLIC CAPITAL LETTER I*/ + 0x0439, /*U+0419*/ /*CYRILLIC CAPITAL LETTER SHORT I*/ + 0x043A, /*U+041A*/ /*CYRILLIC CAPITAL LETTER KA*/ + 0x043B, /*U+041B*/ /*CYRILLIC CAPITAL LETTER EL*/ + 0x043C, /*U+041C*/ /*CYRILLIC CAPITAL LETTER EM*/ + 0x043D, /*U+041D*/ /*CYRILLIC CAPITAL LETTER EN*/ + 0x043E, /*U+041E*/ /*CYRILLIC CAPITAL LETTER O*/ + 0x043F, /*U+041F*/ /*CYRILLIC CAPITAL LETTER PE*/ + 0x0440, /*U+0420*/ /*CYRILLIC CAPITAL LETTER ER*/ + 0x0441, /*U+0421*/ /*CYRILLIC CAPITAL LETTER ES*/ + 0x0442, /*U+0422*/ /*CYRILLIC CAPITAL LETTER TE*/ + 0x0443, /*U+0423*/ /*CYRILLIC CAPITAL LETTER U*/ + 0x0444, /*U+0424*/ /*CYRILLIC CAPITAL LETTER EF*/ + 0x0445, /*U+0425*/ /*CYRILLIC CAPITAL LETTER HA*/ + 0x0446, /*U+0426*/ /*CYRILLIC CAPITAL LETTER TSE*/ + 0x0447, /*U+0427*/ /*CYRILLIC CAPITAL LETTER CHE*/ + 0x0448, /*U+0428*/ /*CYRILLIC CAPITAL LETTER SHA*/ + 0x0449, /*U+0429*/ /*CYRILLIC CAPITAL LETTER SHCHA*/ + 0x044A, /*U+042A*/ /*CYRILLIC CAPITAL LETTER HARD SIGN*/ + 0x044B, /*U+042B*/ /*CYRILLIC CAPITAL LETTER YERU*/ + 0x044C, /*U+042C*/ /*CYRILLIC CAPITAL LETTER SOFT SIGN*/ + 0x044D, /*U+042D*/ /*CYRILLIC CAPITAL LETTER E*/ + 0x044E, /*U+042E*/ /*CYRILLIC CAPITAL LETTER YU*/ + 0x044F, /*U+042F*/ /*CYRILLIC CAPITAL LETTER YA*/ + 0x0430, /*U+0430*/ /**/ + 0x0431, /*U+0431*/ /**/ + 0x0432, /*U+0432*/ /**/ + 0x0433, /*U+0433*/ /**/ + 0x0434, /*U+0434*/ /**/ + 0x0435, /*U+0435*/ /**/ + 0x0436, /*U+0436*/ /**/ + 0x0437, /*U+0437*/ /**/ + 0x0438, /*U+0438*/ /**/ + 0x0439, /*U+0439*/ /**/ + 0x043A, /*U+043A*/ /**/ + 0x043B, /*U+043B*/ /**/ + 0x043C, /*U+043C*/ /**/ + 0x043D, /*U+043D*/ /**/ + 0x043E, /*U+043E*/ /**/ + 0x043F, /*U+043F*/ /**/ + 0x0440, /*U+0440*/ /**/ + 0x0441, /*U+0441*/ /**/ + 0x0442, /*U+0442*/ /**/ + 0x0443, /*U+0443*/ /**/ + 0x0444, /*U+0444*/ /**/ + 0x0445, /*U+0445*/ /**/ + 0x0446, /*U+0446*/ /**/ + 0x0447, /*U+0447*/ /**/ + 0x0448, /*U+0448*/ /**/ + 0x0449, /*U+0449*/ /**/ + 0x044A, /*U+044A*/ /**/ + 0x044B, /*U+044B*/ /**/ + 0x044C, /*U+044C*/ /**/ + 0x044D, /*U+044D*/ /**/ + 0x044E, /*U+044E*/ /**/ + 0x044F, /*U+044F*/ /**/ + 0x0450, /*U+0450*/ /**/ + 0x0451, /*U+0451*/ /**/ + 0x0452, /*U+0452*/ /**/ + 0x0453, /*U+0453*/ /**/ + 0x0454, /*U+0454*/ /**/ + 0x0455, /*U+0455*/ /**/ + 0x0456, /*U+0456*/ /**/ + 0x0457, /*U+0457*/ /**/ + 0x0458, /*U+0458*/ /**/ + 0x0459, /*U+0459*/ /**/ + 0x045A, /*U+045A*/ /**/ + 0x045B, /*U+045B*/ /**/ + 0x045C, /*U+045C*/ /**/ + 0x045D, /*U+045D*/ /**/ + 0x045E, /*U+045E*/ /**/ + 0x045F, /*U+045F*/ /**/ + 0x0461, /*U+0460*/ /*CYRILLIC CAPITAL LETTER OMEGA*/ + 0x0461, /*U+0461*/ /**/ + 0x0463, /*U+0462*/ /*CYRILLIC CAPITAL LETTER YAT*/ + 0x0463, /*U+0463*/ /**/ + 0x0465, /*U+0464*/ /*CYRILLIC CAPITAL LETTER IOTIFIED E*/ + 0x0465, /*U+0465*/ /**/ + 0x0467, /*U+0466*/ /*CYRILLIC CAPITAL LETTER LITTLE YUS*/ + 0x0467, /*U+0467*/ /**/ + 0x0469, /*U+0468*/ /*CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS*/ + 0x0469, /*U+0469*/ /**/ + 0x046B, /*U+046A*/ /*CYRILLIC CAPITAL LETTER BIG YUS*/ + 0x046B, /*U+046B*/ /**/ + 0x046D, /*U+046C*/ /*CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS*/ + 0x046D, /*U+046D*/ /**/ + 0x046F, /*U+046E*/ /*CYRILLIC CAPITAL LETTER KSI*/ + 0x046F, /*U+046F*/ /**/ + 0x0471, /*U+0470*/ /*CYRILLIC CAPITAL LETTER PSI*/ + 0x0471, /*U+0471*/ /**/ + 0x0473, /*U+0472*/ /*CYRILLIC CAPITAL LETTER FITA*/ + 0x0473, /*U+0473*/ /**/ + 0x0475, /*U+0474*/ /*CYRILLIC CAPITAL LETTER IZHITSA*/ + 0x0475, /*U+0475*/ /**/ + 0x0477, /*U+0476*/ /*CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT*/ + 0x0477, /*U+0477*/ /**/ + 0x0479, /*U+0478*/ /*CYRILLIC CAPITAL LETTER UK*/ + 0x0479, /*U+0479*/ /**/ + 0x047B, /*U+047A*/ /*CYRILLIC CAPITAL LETTER ROUND OMEGA*/ + 0x047B, /*U+047B*/ /**/ + 0x047D, /*U+047C*/ /*CYRILLIC CAPITAL LETTER OMEGA WITH TITLO*/ + 0x047D, /*U+047D*/ /**/ + 0x047F, /*U+047E*/ /*CYRILLIC CAPITAL LETTER OT*/ + 0x047F, /*U+047F*/ /**/ + 0x0481, /*U+0480*/ /*CYRILLIC CAPITAL LETTER KOPPA*/ + 0x0481, /*U+0481*/ /**/ + 0x0482, /*U+0482*/ /**/ + 0x0483, /*U+0483*/ /**/ + 0x0484, /*U+0484*/ /**/ + 0x0485, /*U+0485*/ /**/ + 0x0486, /*U+0486*/ /**/ + 0x0487, /*U+0487*/ /**/ + 0x0488, /*U+0488*/ /**/ + 0x0489, /*U+0489*/ /**/ + 0x048B, /*U+048A*/ /*CYRILLIC CAPITAL LETTER SHORT I WITH TAIL*/ + 0x048B, /*U+048B*/ /**/ + 0x048D, /*U+048C*/ /*CYRILLIC CAPITAL LETTER SEMISOFT SIGN*/ + 0x048D, /*U+048D*/ /**/ + 0x048F, /*U+048E*/ /*CYRILLIC CAPITAL LETTER ER WITH TICK*/ + 0x048F, /*U+048F*/ /**/ + 0x0491, /*U+0490*/ /*CYRILLIC CAPITAL LETTER GHE WITH UPTURN*/ + 0x0491, /*U+0491*/ /**/ + 0x0493, /*U+0492*/ /*CYRILLIC CAPITAL LETTER GHE WITH STROKE*/ + 0x0493, /*U+0493*/ /**/ + 0x0495, /*U+0494*/ /*CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK*/ + 0x0495, /*U+0495*/ /**/ + 0x0497, /*U+0496*/ /*CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER*/ + 0x0497, /*U+0497*/ /**/ + 0x0499, /*U+0498*/ /*CYRILLIC CAPITAL LETTER ZE WITH DESCENDER*/ + 0x0499, /*U+0499*/ /**/ + 0x049B, /*U+049A*/ /*CYRILLIC CAPITAL LETTER KA WITH DESCENDER*/ + 0x049B, /*U+049B*/ /**/ + 0x049D, /*U+049C*/ /*CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE*/ + 0x049D, /*U+049D*/ /**/ + 0x049F, /*U+049E*/ /*CYRILLIC CAPITAL LETTER KA WITH STROKE*/ + 0x049F, /*U+049F*/ /**/ + 0x04A1, /*U+04A0*/ /*CYRILLIC CAPITAL LETTER BASHKIR KA*/ + 0x04A1, /*U+04A1*/ /**/ + 0x04A3, /*U+04A2*/ /*CYRILLIC CAPITAL LETTER EN WITH DESCENDER*/ + 0x04A3, /*U+04A3*/ /**/ + 0x04A5, /*U+04A4*/ /*CYRILLIC CAPITAL LIGATURE EN GHE*/ + 0x04A5, /*U+04A5*/ /**/ + 0x04A7, /*U+04A6*/ /*CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK*/ + 0x04A7, /*U+04A7*/ /**/ + 0x04A9, /*U+04A8*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN HA*/ + 0x04A9, /*U+04A9*/ /**/ + 0x04AB, /*U+04AA*/ /*CYRILLIC CAPITAL LETTER ES WITH DESCENDER*/ + 0x04AB, /*U+04AB*/ /**/ + 0x04AD, /*U+04AC*/ /*CYRILLIC CAPITAL LETTER TE WITH DESCENDER*/ + 0x04AD, /*U+04AD*/ /**/ + 0x04AF, /*U+04AE*/ /*CYRILLIC CAPITAL LETTER STRAIGHT U*/ + 0x04AF, /*U+04AF*/ /**/ + 0x04B1, /*U+04B0*/ /*CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE*/ + 0x04B1, /*U+04B1*/ /**/ + 0x04B3, /*U+04B2*/ /*CYRILLIC CAPITAL LETTER HA WITH DESCENDER*/ + 0x04B3, /*U+04B3*/ /**/ + 0x04B5, /*U+04B4*/ /*CYRILLIC CAPITAL LIGATURE TE TSE*/ + 0x04B5, /*U+04B5*/ /**/ + 0x04B7, /*U+04B6*/ /*CYRILLIC CAPITAL LETTER CHE WITH DESCENDER*/ + 0x04B7, /*U+04B7*/ /**/ + 0x04B9, /*U+04B8*/ /*CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE*/ + 0x04B9, /*U+04B9*/ /**/ + 0x04BB, /*U+04BA*/ /*CYRILLIC CAPITAL LETTER SHHA*/ + 0x04BB, /*U+04BB*/ /**/ + 0x04BD, /*U+04BC*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN CHE*/ + 0x04BD, /*U+04BD*/ /**/ + 0x04BF, /*U+04BE*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER*/ + 0x04BF, /*U+04BF*/ /**/ + 0x04CF, /*U+04C0*/ /*CYRILLIC LETTER PALOCHKA*/ + 0x04C2, /*U+04C1*/ /*CYRILLIC CAPITAL LETTER ZHE WITH BREVE*/ + 0x04C2, /*U+04C2*/ /**/ + 0x04C4, /*U+04C3*/ /*CYRILLIC CAPITAL LETTER KA WITH HOOK*/ + 0x04C4, /*U+04C4*/ /**/ + 0x04C6, /*U+04C5*/ /*CYRILLIC CAPITAL LETTER EL WITH TAIL*/ + 0x04C6, /*U+04C6*/ /**/ + 0x04C8, /*U+04C7*/ /*CYRILLIC CAPITAL LETTER EN WITH HOOK*/ + 0x04C8, /*U+04C8*/ /**/ + 0x04CA, /*U+04C9*/ /*CYRILLIC CAPITAL LETTER EN WITH TAIL*/ + 0x04CA, /*U+04CA*/ /**/ + 0x04CC, /*U+04CB*/ /*CYRILLIC CAPITAL LETTER KHAKASSIAN CHE*/ + 0x04CC, /*U+04CC*/ /**/ + 0x04CE, /*U+04CD*/ /*CYRILLIC CAPITAL LETTER EM WITH TAIL*/ + 0x04CE, /*U+04CE*/ /**/ + 0x04CF, /*U+04CF*/ /**/ + 0x04D1, /*U+04D0*/ /*CYRILLIC CAPITAL LETTER A WITH BREVE*/ + 0x04D1, /*U+04D1*/ /**/ + 0x04D3, /*U+04D2*/ /*CYRILLIC CAPITAL LETTER A WITH DIAERESIS*/ + 0x04D3, /*U+04D3*/ /**/ + 0x04D5, /*U+04D4*/ /*CYRILLIC CAPITAL LIGATURE A IE*/ + 0x04D5, /*U+04D5*/ /**/ + 0x04D7, /*U+04D6*/ /*CYRILLIC CAPITAL LETTER IE WITH BREVE*/ + 0x04D7, /*U+04D7*/ /**/ + 0x04D9, /*U+04D8*/ /*CYRILLIC CAPITAL LETTER SCHWA*/ + 0x04D9, /*U+04D9*/ /**/ + 0x04DB, /*U+04DA*/ /*CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS*/ + 0x04DB, /*U+04DB*/ /**/ + 0x04DD, /*U+04DC*/ /*CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS*/ + 0x04DD, /*U+04DD*/ /**/ + 0x04DF, /*U+04DE*/ /*CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS*/ + 0x04DF, /*U+04DF*/ /**/ + 0x04E1, /*U+04E0*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN DZE*/ + 0x04E1, /*U+04E1*/ /**/ + 0x04E3, /*U+04E2*/ /*CYRILLIC CAPITAL LETTER I WITH MACRON*/ + 0x04E3, /*U+04E3*/ /**/ + 0x04E5, /*U+04E4*/ /*CYRILLIC CAPITAL LETTER I WITH DIAERESIS*/ + 0x04E5, /*U+04E5*/ /**/ + 0x04E7, /*U+04E6*/ /*CYRILLIC CAPITAL LETTER O WITH DIAERESIS*/ + 0x04E7, /*U+04E7*/ /**/ + 0x04E9, /*U+04E8*/ /*CYRILLIC CAPITAL LETTER BARRED O*/ + 0x04E9, /*U+04E9*/ /**/ + 0x04EB, /*U+04EA*/ /*CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS*/ + 0x04EB, /*U+04EB*/ /**/ + 0x04ED, /*U+04EC*/ /*CYRILLIC CAPITAL LETTER E WITH DIAERESIS*/ + 0x04ED, /*U+04ED*/ /**/ + 0x04EF, /*U+04EE*/ /*CYRILLIC CAPITAL LETTER U WITH MACRON*/ + 0x04EF, /*U+04EF*/ /**/ + 0x04F1, /*U+04F0*/ /*CYRILLIC CAPITAL LETTER U WITH DIAERESIS*/ + 0x04F1, /*U+04F1*/ /**/ + 0x04F3, /*U+04F2*/ /*CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE*/ + 0x04F3, /*U+04F3*/ /**/ + 0x04F5, /*U+04F4*/ /*CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS*/ + 0x04F5, /*U+04F5*/ /**/ + 0x04F7, /*U+04F6*/ /*CYRILLIC CAPITAL LETTER GHE WITH DESCENDER*/ + 0x04F7, /*U+04F7*/ /**/ + 0x04F9, /*U+04F8*/ /*CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS*/ + 0x04F9, /*U+04F9*/ /**/ + 0x04FB, /*U+04FA*/ /*CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK*/ + 0x04FB, /*U+04FB*/ /**/ + 0x04FD, /*U+04FC*/ /*CYRILLIC CAPITAL LETTER HA WITH HOOK*/ + 0x04FD, /*U+04FD*/ /**/ + 0x04FF, /*U+04FE*/ /*CYRILLIC CAPITAL LETTER HA WITH STROKE*/ + 0x04FF, /*U+04FF*/ /**/ + 0x0501, /*U+0500*/ /*CYRILLIC CAPITAL LETTER KOMI DE*/ + 0x0501, /*U+0501*/ /**/ + 0x0503, /*U+0502*/ /*CYRILLIC CAPITAL LETTER KOMI DJE*/ + 0x0503, /*U+0503*/ /**/ + 0x0505, /*U+0504*/ /*CYRILLIC CAPITAL LETTER KOMI ZJE*/ + 0x0505, /*U+0505*/ /**/ + 0x0507, /*U+0506*/ /*CYRILLIC CAPITAL LETTER KOMI DZJE*/ + 0x0507, /*U+0507*/ /**/ + 0x0509, /*U+0508*/ /*CYRILLIC CAPITAL LETTER KOMI LJE*/ + 0x0509, /*U+0509*/ /**/ + 0x050B, /*U+050A*/ /*CYRILLIC CAPITAL LETTER KOMI NJE*/ + 0x050B, /*U+050B*/ /**/ + 0x050D, /*U+050C*/ /*CYRILLIC CAPITAL LETTER KOMI SJE*/ + 0x050D, /*U+050D*/ /**/ + 0x050F, /*U+050E*/ /*CYRILLIC CAPITAL LETTER KOMI TJE*/ + 0x050F, /*U+050F*/ /**/ + 0x0511, /*U+0510*/ /*CYRILLIC CAPITAL LETTER REVERSED ZE*/ + 0x0511, /*U+0511*/ /**/ + 0x0513, /*U+0512*/ /*CYRILLIC CAPITAL LETTER EL WITH HOOK*/ + 0x0513, /*U+0513*/ /**/ + 0x0515, /*U+0514*/ /*CYRILLIC CAPITAL LETTER LHA*/ + 0x0515, /*U+0515*/ /**/ + 0x0517, /*U+0516*/ /*CYRILLIC CAPITAL LETTER RHA*/ + 0x0517, /*U+0517*/ /**/ + 0x0519, /*U+0518*/ /*CYRILLIC CAPITAL LETTER YAE*/ + 0x0519, /*U+0519*/ /**/ + 0x051B, /*U+051A*/ /*CYRILLIC CAPITAL LETTER QA*/ + 0x051B, /*U+051B*/ /**/ + 0x051D, /*U+051C*/ /*CYRILLIC CAPITAL LETTER WE*/ + 0x051D, /*U+051D*/ /**/ + 0x051F, /*U+051E*/ /*CYRILLIC CAPITAL LETTER ALEUT KA*/ + 0x051F, /*U+051F*/ /**/ + 0x0521, /*U+0520*/ /*CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK*/ + 0x0521, /*U+0521*/ /**/ + 0x0523, /*U+0522*/ /*CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK*/ + 0x0523, /*U+0523*/ /**/ + 0x0525, /*U+0524*/ /*CYRILLIC CAPITAL LETTER PE WITH DESCENDER*/ + 0x0525, /*U+0525*/ /**/ + 0x0527, /*U+0526*/ /*CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER*/ + 0x0527, /*U+0527*/ /**/ + 0x0529, /*U+0528*/ /*CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK*/ + 0x0529, /*U+0529*/ /**/ + 0x052B, /*U+052A*/ /*CYRILLIC CAPITAL LETTER DZZHE*/ + 0x052B, /*U+052B*/ /**/ + 0x052D, /*U+052C*/ /*CYRILLIC CAPITAL LETTER DCHE*/ + 0x052D, /*U+052D*/ /**/ + 0x052F, /*U+052E*/ /*CYRILLIC CAPITAL LETTER EL WITH DESCENDER*/ + 0x052F, /*U+052F*/ /**/ + 0x0530, /*U+0530*/ /**/ + 0x0561, /*U+0531*/ /*ARMENIAN CAPITAL LETTER AYB*/ + 0x0562, /*U+0532*/ /*ARMENIAN CAPITAL LETTER BEN*/ + 0x0563, /*U+0533*/ /*ARMENIAN CAPITAL LETTER GIM*/ + 0x0564, /*U+0534*/ /*ARMENIAN CAPITAL LETTER DA*/ + 0x0565, /*U+0535*/ /*ARMENIAN CAPITAL LETTER ECH*/ + 0x0566, /*U+0536*/ /*ARMENIAN CAPITAL LETTER ZA*/ + 0x0567, /*U+0537*/ /*ARMENIAN CAPITAL LETTER EH*/ + 0x0568, /*U+0538*/ /*ARMENIAN CAPITAL LETTER ET*/ + 0x0569, /*U+0539*/ /*ARMENIAN CAPITAL LETTER TO*/ + 0x056A, /*U+053A*/ /*ARMENIAN CAPITAL LETTER ZHE*/ + 0x056B, /*U+053B*/ /*ARMENIAN CAPITAL LETTER INI*/ + 0x056C, /*U+053C*/ /*ARMENIAN CAPITAL LETTER LIWN*/ + 0x056D, /*U+053D*/ /*ARMENIAN CAPITAL LETTER XEH*/ + 0x056E, /*U+053E*/ /*ARMENIAN CAPITAL LETTER CA*/ + 0x056F, /*U+053F*/ /*ARMENIAN CAPITAL LETTER KEN*/ + 0x0570, /*U+0540*/ /*ARMENIAN CAPITAL LETTER HO*/ + 0x0571, /*U+0541*/ /*ARMENIAN CAPITAL LETTER JA*/ + 0x0572, /*U+0542*/ /*ARMENIAN CAPITAL LETTER GHAD*/ + 0x0573, /*U+0543*/ /*ARMENIAN CAPITAL LETTER CHEH*/ + 0x0574, /*U+0544*/ /*ARMENIAN CAPITAL LETTER MEN*/ + 0x0575, /*U+0545*/ /*ARMENIAN CAPITAL LETTER YI*/ + 0x0576, /*U+0546*/ /*ARMENIAN CAPITAL LETTER NOW*/ + 0x0577, /*U+0547*/ /*ARMENIAN CAPITAL LETTER SHA*/ + 0x0578, /*U+0548*/ /*ARMENIAN CAPITAL LETTER VO*/ + 0x0579, /*U+0549*/ /*ARMENIAN CAPITAL LETTER CHA*/ + 0x057A, /*U+054A*/ /*ARMENIAN CAPITAL LETTER PEH*/ + 0x057B, /*U+054B*/ /*ARMENIAN CAPITAL LETTER JHEH*/ + 0x057C, /*U+054C*/ /*ARMENIAN CAPITAL LETTER RA*/ + 0x057D, /*U+054D*/ /*ARMENIAN CAPITAL LETTER SEH*/ + 0x057E, /*U+054E*/ /*ARMENIAN CAPITAL LETTER VEW*/ + 0x057F, /*U+054F*/ /*ARMENIAN CAPITAL LETTER TIWN*/ + 0x0580, /*U+0550*/ /*ARMENIAN CAPITAL LETTER REH*/ + 0x0581, /*U+0551*/ /*ARMENIAN CAPITAL LETTER CO*/ + 0x0582, /*U+0552*/ /*ARMENIAN CAPITAL LETTER YIWN*/ + 0x0583, /*U+0553*/ /*ARMENIAN CAPITAL LETTER PIWR*/ + 0x0584, /*U+0554*/ /*ARMENIAN CAPITAL LETTER KEH*/ + 0x0585, /*U+0555*/ /*ARMENIAN CAPITAL LETTER OH*/ + 0x0586, /*U+0556*/ /*ARMENIAN CAPITAL LETTER FEH*/ + 0x0557, /*U+0557*/ /**/ + 0x0558, /*U+0558*/ /**/ + 0x0559, /*U+0559*/ /**/ + 0x055A, /*U+055A*/ /**/ + 0x055B, /*U+055B*/ /**/ + 0x055C, /*U+055C*/ /**/ + 0x055D, /*U+055D*/ /**/ + 0x055E, /*U+055E*/ /**/ + 0x055F, /*U+055F*/ /**/ + 0x0560, /*U+0560*/ /**/ + 0x0561, /*U+0561*/ /**/ + 0x0562, /*U+0562*/ /**/ + 0x0563, /*U+0563*/ /**/ + 0x0564, /*U+0564*/ /**/ + 0x0565, /*U+0565*/ /**/ + 0x0566, /*U+0566*/ /**/ + 0x0567, /*U+0567*/ /**/ + 0x0568, /*U+0568*/ /**/ + 0x0569, /*U+0569*/ /**/ + 0x056A, /*U+056A*/ /**/ + 0x056B, /*U+056B*/ /**/ + 0x056C, /*U+056C*/ /**/ + 0x056D, /*U+056D*/ /**/ + 0x056E, /*U+056E*/ /**/ + 0x056F, /*U+056F*/ /**/ + 0x0570, /*U+0570*/ /**/ + 0x0571, /*U+0571*/ /**/ + 0x0572, /*U+0572*/ /**/ + 0x0573, /*U+0573*/ /**/ + 0x0574, /*U+0574*/ /**/ + 0x0575, /*U+0575*/ /**/ + 0x0576, /*U+0576*/ /**/ + 0x0577, /*U+0577*/ /**/ + 0x0578, /*U+0578*/ /**/ + 0x0579, /*U+0579*/ /**/ + 0x057A, /*U+057A*/ /**/ + 0x057B, /*U+057B*/ /**/ + 0x057C, /*U+057C*/ /**/ + 0x057D, /*U+057D*/ /**/ + 0x057E, /*U+057E*/ /**/ + 0x057F, /*U+057F*/ /**/ +}; + +static const uint16_t lower_table_4[128] = { + 0x1080, /*U+1080*/ /**/ + 0x1081, /*U+1081*/ /**/ + 0x1082, /*U+1082*/ /**/ + 0x1083, /*U+1083*/ /**/ + 0x1084, /*U+1084*/ /**/ + 0x1085, /*U+1085*/ /**/ + 0x1086, /*U+1086*/ /**/ + 0x1087, /*U+1087*/ /**/ + 0x1088, /*U+1088*/ /**/ + 0x1089, /*U+1089*/ /**/ + 0x108A, /*U+108A*/ /**/ + 0x108B, /*U+108B*/ /**/ + 0x108C, /*U+108C*/ /**/ + 0x108D, /*U+108D*/ /**/ + 0x108E, /*U+108E*/ /**/ + 0x108F, /*U+108F*/ /**/ + 0x1090, /*U+1090*/ /**/ + 0x1091, /*U+1091*/ /**/ + 0x1092, /*U+1092*/ /**/ + 0x1093, /*U+1093*/ /**/ + 0x1094, /*U+1094*/ /**/ + 0x1095, /*U+1095*/ /**/ + 0x1096, /*U+1096*/ /**/ + 0x1097, /*U+1097*/ /**/ + 0x1098, /*U+1098*/ /**/ + 0x1099, /*U+1099*/ /**/ + 0x109A, /*U+109A*/ /**/ + 0x109B, /*U+109B*/ /**/ + 0x109C, /*U+109C*/ /**/ + 0x109D, /*U+109D*/ /**/ + 0x109E, /*U+109E*/ /**/ + 0x109F, /*U+109F*/ /**/ + 0x2D00, /*U+10A0*/ /*GEORGIAN CAPITAL LETTER AN*/ + 0x2D01, /*U+10A1*/ /*GEORGIAN CAPITAL LETTER BAN*/ + 0x2D02, /*U+10A2*/ /*GEORGIAN CAPITAL LETTER GAN*/ + 0x2D03, /*U+10A3*/ /*GEORGIAN CAPITAL LETTER DON*/ + 0x2D04, /*U+10A4*/ /*GEORGIAN CAPITAL LETTER EN*/ + 0x2D05, /*U+10A5*/ /*GEORGIAN CAPITAL LETTER VIN*/ + 0x2D06, /*U+10A6*/ /*GEORGIAN CAPITAL LETTER ZEN*/ + 0x2D07, /*U+10A7*/ /*GEORGIAN CAPITAL LETTER TAN*/ + 0x2D08, /*U+10A8*/ /*GEORGIAN CAPITAL LETTER IN*/ + 0x2D09, /*U+10A9*/ /*GEORGIAN CAPITAL LETTER KAN*/ + 0x2D0A, /*U+10AA*/ /*GEORGIAN CAPITAL LETTER LAS*/ + 0x2D0B, /*U+10AB*/ /*GEORGIAN CAPITAL LETTER MAN*/ + 0x2D0C, /*U+10AC*/ /*GEORGIAN CAPITAL LETTER NAR*/ + 0x2D0D, /*U+10AD*/ /*GEORGIAN CAPITAL LETTER ON*/ + 0x2D0E, /*U+10AE*/ /*GEORGIAN CAPITAL LETTER PAR*/ + 0x2D0F, /*U+10AF*/ /*GEORGIAN CAPITAL LETTER ZHAR*/ + 0x2D10, /*U+10B0*/ /*GEORGIAN CAPITAL LETTER RAE*/ + 0x2D11, /*U+10B1*/ /*GEORGIAN CAPITAL LETTER SAN*/ + 0x2D12, /*U+10B2*/ /*GEORGIAN CAPITAL LETTER TAR*/ + 0x2D13, /*U+10B3*/ /*GEORGIAN CAPITAL LETTER UN*/ + 0x2D14, /*U+10B4*/ /*GEORGIAN CAPITAL LETTER PHAR*/ + 0x2D15, /*U+10B5*/ /*GEORGIAN CAPITAL LETTER KHAR*/ + 0x2D16, /*U+10B6*/ /*GEORGIAN CAPITAL LETTER GHAN*/ + 0x2D17, /*U+10B7*/ /*GEORGIAN CAPITAL LETTER QAR*/ + 0x2D18, /*U+10B8*/ /*GEORGIAN CAPITAL LETTER SHIN*/ + 0x2D19, /*U+10B9*/ /*GEORGIAN CAPITAL LETTER CHIN*/ + 0x2D1A, /*U+10BA*/ /*GEORGIAN CAPITAL LETTER CAN*/ + 0x2D1B, /*U+10BB*/ /*GEORGIAN CAPITAL LETTER JIL*/ + 0x2D1C, /*U+10BC*/ /*GEORGIAN CAPITAL LETTER CIL*/ + 0x2D1D, /*U+10BD*/ /*GEORGIAN CAPITAL LETTER CHAR*/ + 0x2D1E, /*U+10BE*/ /*GEORGIAN CAPITAL LETTER XAN*/ + 0x2D1F, /*U+10BF*/ /*GEORGIAN CAPITAL LETTER JHAN*/ + 0x2D20, /*U+10C0*/ /*GEORGIAN CAPITAL LETTER HAE*/ + 0x2D21, /*U+10C1*/ /*GEORGIAN CAPITAL LETTER HE*/ + 0x2D22, /*U+10C2*/ /*GEORGIAN CAPITAL LETTER HIE*/ + 0x2D23, /*U+10C3*/ /*GEORGIAN CAPITAL LETTER WE*/ + 0x2D24, /*U+10C4*/ /*GEORGIAN CAPITAL LETTER HAR*/ + 0x2D25, /*U+10C5*/ /*GEORGIAN CAPITAL LETTER HOE*/ + 0x10C6, /*U+10C6*/ /**/ + 0x2D27, /*U+10C7*/ /*GEORGIAN CAPITAL LETTER YN*/ + 0x10C8, /*U+10C8*/ /**/ + 0x10C9, /*U+10C9*/ /**/ + 0x10CA, /*U+10CA*/ /**/ + 0x10CB, /*U+10CB*/ /**/ + 0x10CC, /*U+10CC*/ /**/ + 0x2D2D, /*U+10CD*/ /*GEORGIAN CAPITAL LETTER AEN*/ + 0x10CE, /*U+10CE*/ /**/ + 0x10CF, /*U+10CF*/ /**/ + 0x10D0, /*U+10D0*/ /**/ + 0x10D1, /*U+10D1*/ /**/ + 0x10D2, /*U+10D2*/ /**/ + 0x10D3, /*U+10D3*/ /**/ + 0x10D4, /*U+10D4*/ /**/ + 0x10D5, /*U+10D5*/ /**/ + 0x10D6, /*U+10D6*/ /**/ + 0x10D7, /*U+10D7*/ /**/ + 0x10D8, /*U+10D8*/ /**/ + 0x10D9, /*U+10D9*/ /**/ + 0x10DA, /*U+10DA*/ /**/ + 0x10DB, /*U+10DB*/ /**/ + 0x10DC, /*U+10DC*/ /**/ + 0x10DD, /*U+10DD*/ /**/ + 0x10DE, /*U+10DE*/ /**/ + 0x10DF, /*U+10DF*/ /**/ + 0x10E0, /*U+10E0*/ /**/ + 0x10E1, /*U+10E1*/ /**/ + 0x10E2, /*U+10E2*/ /**/ + 0x10E3, /*U+10E3*/ /**/ + 0x10E4, /*U+10E4*/ /**/ + 0x10E5, /*U+10E5*/ /**/ + 0x10E6, /*U+10E6*/ /**/ + 0x10E7, /*U+10E7*/ /**/ + 0x10E8, /*U+10E8*/ /**/ + 0x10E9, /*U+10E9*/ /**/ + 0x10EA, /*U+10EA*/ /**/ + 0x10EB, /*U+10EB*/ /**/ + 0x10EC, /*U+10EC*/ /**/ + 0x10ED, /*U+10ED*/ /**/ + 0x10EE, /*U+10EE*/ /**/ + 0x10EF, /*U+10EF*/ /**/ + 0x10F0, /*U+10F0*/ /**/ + 0x10F1, /*U+10F1*/ /**/ + 0x10F2, /*U+10F2*/ /**/ + 0x10F3, /*U+10F3*/ /**/ + 0x10F4, /*U+10F4*/ /**/ + 0x10F5, /*U+10F5*/ /**/ + 0x10F6, /*U+10F6*/ /**/ + 0x10F7, /*U+10F7*/ /**/ + 0x10F8, /*U+10F8*/ /**/ + 0x10F9, /*U+10F9*/ /**/ + 0x10FA, /*U+10FA*/ /**/ + 0x10FB, /*U+10FB*/ /**/ + 0x10FC, /*U+10FC*/ /**/ + 0x10FD, /*U+10FD*/ /**/ + 0x10FE, /*U+10FE*/ /**/ + 0x10FF, /*U+10FF*/ /**/ +}; + +static const uint16_t lower_table_5[512] = { + 0x1E01, /*U+1E00*/ /*LATIN CAPITAL LETTER A WITH RING BELOW*/ + 0x1E01, /*U+1E01*/ /**/ + 0x1E03, /*U+1E02*/ /*LATIN CAPITAL LETTER B WITH DOT ABOVE*/ + 0x1E03, /*U+1E03*/ /**/ + 0x1E05, /*U+1E04*/ /*LATIN CAPITAL LETTER B WITH DOT BELOW*/ + 0x1E05, /*U+1E05*/ /**/ + 0x1E07, /*U+1E06*/ /*LATIN CAPITAL LETTER B WITH LINE BELOW*/ + 0x1E07, /*U+1E07*/ /**/ + 0x1E09, /*U+1E08*/ /*LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE*/ + 0x1E09, /*U+1E09*/ /**/ + 0x1E0B, /*U+1E0A*/ /*LATIN CAPITAL LETTER D WITH DOT ABOVE*/ + 0x1E0B, /*U+1E0B*/ /**/ + 0x1E0D, /*U+1E0C*/ /*LATIN CAPITAL LETTER D WITH DOT BELOW*/ + 0x1E0D, /*U+1E0D*/ /**/ + 0x1E0F, /*U+1E0E*/ /*LATIN CAPITAL LETTER D WITH LINE BELOW*/ + 0x1E0F, /*U+1E0F*/ /**/ + 0x1E11, /*U+1E10*/ /*LATIN CAPITAL LETTER D WITH CEDILLA*/ + 0x1E11, /*U+1E11*/ /**/ + 0x1E13, /*U+1E12*/ /*LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW*/ + 0x1E13, /*U+1E13*/ /**/ + 0x1E15, /*U+1E14*/ /*LATIN CAPITAL LETTER E WITH MACRON AND GRAVE*/ + 0x1E15, /*U+1E15*/ /**/ + 0x1E17, /*U+1E16*/ /*LATIN CAPITAL LETTER E WITH MACRON AND ACUTE*/ + 0x1E17, /*U+1E17*/ /**/ + 0x1E19, /*U+1E18*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW*/ + 0x1E19, /*U+1E19*/ /**/ + 0x1E1B, /*U+1E1A*/ /*LATIN CAPITAL LETTER E WITH TILDE BELOW*/ + 0x1E1B, /*U+1E1B*/ /**/ + 0x1E1D, /*U+1E1C*/ /*LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE*/ + 0x1E1D, /*U+1E1D*/ /**/ + 0x1E1F, /*U+1E1E*/ /*LATIN CAPITAL LETTER F WITH DOT ABOVE*/ + 0x1E1F, /*U+1E1F*/ /**/ + 0x1E21, /*U+1E20*/ /*LATIN CAPITAL LETTER G WITH MACRON*/ + 0x1E21, /*U+1E21*/ /**/ + 0x1E23, /*U+1E22*/ /*LATIN CAPITAL LETTER H WITH DOT ABOVE*/ + 0x1E23, /*U+1E23*/ /**/ + 0x1E25, /*U+1E24*/ /*LATIN CAPITAL LETTER H WITH DOT BELOW*/ + 0x1E25, /*U+1E25*/ /**/ + 0x1E27, /*U+1E26*/ /*LATIN CAPITAL LETTER H WITH DIAERESIS*/ + 0x1E27, /*U+1E27*/ /**/ + 0x1E29, /*U+1E28*/ /*LATIN CAPITAL LETTER H WITH CEDILLA*/ + 0x1E29, /*U+1E29*/ /**/ + 0x1E2B, /*U+1E2A*/ /*LATIN CAPITAL LETTER H WITH BREVE BELOW*/ + 0x1E2B, /*U+1E2B*/ /**/ + 0x1E2D, /*U+1E2C*/ /*LATIN CAPITAL LETTER I WITH TILDE BELOW*/ + 0x1E2D, /*U+1E2D*/ /**/ + 0x1E2F, /*U+1E2E*/ /*LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE*/ + 0x1E2F, /*U+1E2F*/ /**/ + 0x1E31, /*U+1E30*/ /*LATIN CAPITAL LETTER K WITH ACUTE*/ + 0x1E31, /*U+1E31*/ /**/ + 0x1E33, /*U+1E32*/ /*LATIN CAPITAL LETTER K WITH DOT BELOW*/ + 0x1E33, /*U+1E33*/ /**/ + 0x1E35, /*U+1E34*/ /*LATIN CAPITAL LETTER K WITH LINE BELOW*/ + 0x1E35, /*U+1E35*/ /**/ + 0x1E37, /*U+1E36*/ /*LATIN CAPITAL LETTER L WITH DOT BELOW*/ + 0x1E37, /*U+1E37*/ /**/ + 0x1E39, /*U+1E38*/ /*LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON*/ + 0x1E39, /*U+1E39*/ /**/ + 0x1E3B, /*U+1E3A*/ /*LATIN CAPITAL LETTER L WITH LINE BELOW*/ + 0x1E3B, /*U+1E3B*/ /**/ + 0x1E3D, /*U+1E3C*/ /*LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW*/ + 0x1E3D, /*U+1E3D*/ /**/ + 0x1E3F, /*U+1E3E*/ /*LATIN CAPITAL LETTER M WITH ACUTE*/ + 0x1E3F, /*U+1E3F*/ /**/ + 0x1E41, /*U+1E40*/ /*LATIN CAPITAL LETTER M WITH DOT ABOVE*/ + 0x1E41, /*U+1E41*/ /**/ + 0x1E43, /*U+1E42*/ /*LATIN CAPITAL LETTER M WITH DOT BELOW*/ + 0x1E43, /*U+1E43*/ /**/ + 0x1E45, /*U+1E44*/ /*LATIN CAPITAL LETTER N WITH DOT ABOVE*/ + 0x1E45, /*U+1E45*/ /**/ + 0x1E47, /*U+1E46*/ /*LATIN CAPITAL LETTER N WITH DOT BELOW*/ + 0x1E47, /*U+1E47*/ /**/ + 0x1E49, /*U+1E48*/ /*LATIN CAPITAL LETTER N WITH LINE BELOW*/ + 0x1E49, /*U+1E49*/ /**/ + 0x1E4B, /*U+1E4A*/ /*LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW*/ + 0x1E4B, /*U+1E4B*/ /**/ + 0x1E4D, /*U+1E4C*/ /*LATIN CAPITAL LETTER O WITH TILDE AND ACUTE*/ + 0x1E4D, /*U+1E4D*/ /**/ + 0x1E4F, /*U+1E4E*/ /*LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS*/ + 0x1E4F, /*U+1E4F*/ /**/ + 0x1E51, /*U+1E50*/ /*LATIN CAPITAL LETTER O WITH MACRON AND GRAVE*/ + 0x1E51, /*U+1E51*/ /**/ + 0x1E53, /*U+1E52*/ /*LATIN CAPITAL LETTER O WITH MACRON AND ACUTE*/ + 0x1E53, /*U+1E53*/ /**/ + 0x1E55, /*U+1E54*/ /*LATIN CAPITAL LETTER P WITH ACUTE*/ + 0x1E55, /*U+1E55*/ /**/ + 0x1E57, /*U+1E56*/ /*LATIN CAPITAL LETTER P WITH DOT ABOVE*/ + 0x1E57, /*U+1E57*/ /**/ + 0x1E59, /*U+1E58*/ /*LATIN CAPITAL LETTER R WITH DOT ABOVE*/ + 0x1E59, /*U+1E59*/ /**/ + 0x1E5B, /*U+1E5A*/ /*LATIN CAPITAL LETTER R WITH DOT BELOW*/ + 0x1E5B, /*U+1E5B*/ /**/ + 0x1E5D, /*U+1E5C*/ /*LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON*/ + 0x1E5D, /*U+1E5D*/ /**/ + 0x1E5F, /*U+1E5E*/ /*LATIN CAPITAL LETTER R WITH LINE BELOW*/ + 0x1E5F, /*U+1E5F*/ /**/ + 0x1E61, /*U+1E60*/ /*LATIN CAPITAL LETTER S WITH DOT ABOVE*/ + 0x1E61, /*U+1E61*/ /**/ + 0x1E63, /*U+1E62*/ /*LATIN CAPITAL LETTER S WITH DOT BELOW*/ + 0x1E63, /*U+1E63*/ /**/ + 0x1E65, /*U+1E64*/ /*LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE*/ + 0x1E65, /*U+1E65*/ /**/ + 0x1E67, /*U+1E66*/ /*LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE*/ + 0x1E67, /*U+1E67*/ /**/ + 0x1E69, /*U+1E68*/ /*LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE*/ + 0x1E69, /*U+1E69*/ /**/ + 0x1E6B, /*U+1E6A*/ /*LATIN CAPITAL LETTER T WITH DOT ABOVE*/ + 0x1E6B, /*U+1E6B*/ /**/ + 0x1E6D, /*U+1E6C*/ /*LATIN CAPITAL LETTER T WITH DOT BELOW*/ + 0x1E6D, /*U+1E6D*/ /**/ + 0x1E6F, /*U+1E6E*/ /*LATIN CAPITAL LETTER T WITH LINE BELOW*/ + 0x1E6F, /*U+1E6F*/ /**/ + 0x1E71, /*U+1E70*/ /*LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW*/ + 0x1E71, /*U+1E71*/ /**/ + 0x1E73, /*U+1E72*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS BELOW*/ + 0x1E73, /*U+1E73*/ /**/ + 0x1E75, /*U+1E74*/ /*LATIN CAPITAL LETTER U WITH TILDE BELOW*/ + 0x1E75, /*U+1E75*/ /**/ + 0x1E77, /*U+1E76*/ /*LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW*/ + 0x1E77, /*U+1E77*/ /**/ + 0x1E79, /*U+1E78*/ /*LATIN CAPITAL LETTER U WITH TILDE AND ACUTE*/ + 0x1E79, /*U+1E79*/ /**/ + 0x1E7B, /*U+1E7A*/ /*LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS*/ + 0x1E7B, /*U+1E7B*/ /**/ + 0x1E7D, /*U+1E7C*/ /*LATIN CAPITAL LETTER V WITH TILDE*/ + 0x1E7D, /*U+1E7D*/ /**/ + 0x1E7F, /*U+1E7E*/ /*LATIN CAPITAL LETTER V WITH DOT BELOW*/ + 0x1E7F, /*U+1E7F*/ /**/ + 0x1E81, /*U+1E80*/ /*LATIN CAPITAL LETTER W WITH GRAVE*/ + 0x1E81, /*U+1E81*/ /**/ + 0x1E83, /*U+1E82*/ /*LATIN CAPITAL LETTER W WITH ACUTE*/ + 0x1E83, /*U+1E83*/ /**/ + 0x1E85, /*U+1E84*/ /*LATIN CAPITAL LETTER W WITH DIAERESIS*/ + 0x1E85, /*U+1E85*/ /**/ + 0x1E87, /*U+1E86*/ /*LATIN CAPITAL LETTER W WITH DOT ABOVE*/ + 0x1E87, /*U+1E87*/ /**/ + 0x1E89, /*U+1E88*/ /*LATIN CAPITAL LETTER W WITH DOT BELOW*/ + 0x1E89, /*U+1E89*/ /**/ + 0x1E8B, /*U+1E8A*/ /*LATIN CAPITAL LETTER X WITH DOT ABOVE*/ + 0x1E8B, /*U+1E8B*/ /**/ + 0x1E8D, /*U+1E8C*/ /*LATIN CAPITAL LETTER X WITH DIAERESIS*/ + 0x1E8D, /*U+1E8D*/ /**/ + 0x1E8F, /*U+1E8E*/ /*LATIN CAPITAL LETTER Y WITH DOT ABOVE*/ + 0x1E8F, /*U+1E8F*/ /**/ + 0x1E91, /*U+1E90*/ /*LATIN CAPITAL LETTER Z WITH CIRCUMFLEX*/ + 0x1E91, /*U+1E91*/ /**/ + 0x1E93, /*U+1E92*/ /*LATIN CAPITAL LETTER Z WITH DOT BELOW*/ + 0x1E93, /*U+1E93*/ /**/ + 0x1E95, /*U+1E94*/ /*LATIN CAPITAL LETTER Z WITH LINE BELOW*/ + 0x1E95, /*U+1E95*/ /**/ + 0x1E96, /*U+1E96*/ /**/ + 0x1E97, /*U+1E97*/ /**/ + 0x1E98, /*U+1E98*/ /**/ + 0x1E99, /*U+1E99*/ /**/ + 0x1E9A, /*U+1E9A*/ /**/ + 0x1E9B, /*U+1E9B*/ /**/ + 0x1E9C, /*U+1E9C*/ /**/ + 0x1E9D, /*U+1E9D*/ /**/ + 0x00DF, /*U+1E9E*/ /*LATIN CAPITAL LETTER SHARP S*/ + 0x1E9F, /*U+1E9F*/ /**/ + 0x1EA1, /*U+1EA0*/ /*LATIN CAPITAL LETTER A WITH DOT BELOW*/ + 0x1EA1, /*U+1EA1*/ /**/ + 0x1EA3, /*U+1EA2*/ /*LATIN CAPITAL LETTER A WITH HOOK ABOVE*/ + 0x1EA3, /*U+1EA3*/ /**/ + 0x1EA5, /*U+1EA4*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE*/ + 0x1EA5, /*U+1EA5*/ /**/ + 0x1EA7, /*U+1EA6*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE*/ + 0x1EA7, /*U+1EA7*/ /**/ + 0x1EA9, /*U+1EA8*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE*/ + 0x1EA9, /*U+1EA9*/ /**/ + 0x1EAB, /*U+1EAA*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE*/ + 0x1EAB, /*U+1EAB*/ /**/ + 0x1EAD, /*U+1EAC*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW*/ + 0x1EAD, /*U+1EAD*/ /**/ + 0x1EAF, /*U+1EAE*/ /*LATIN CAPITAL LETTER A WITH BREVE AND ACUTE*/ + 0x1EAF, /*U+1EAF*/ /**/ + 0x1EB1, /*U+1EB0*/ /*LATIN CAPITAL LETTER A WITH BREVE AND GRAVE*/ + 0x1EB1, /*U+1EB1*/ /**/ + 0x1EB3, /*U+1EB2*/ /*LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE*/ + 0x1EB3, /*U+1EB3*/ /**/ + 0x1EB5, /*U+1EB4*/ /*LATIN CAPITAL LETTER A WITH BREVE AND TILDE*/ + 0x1EB5, /*U+1EB5*/ /**/ + 0x1EB7, /*U+1EB6*/ /*LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW*/ + 0x1EB7, /*U+1EB7*/ /**/ + 0x1EB9, /*U+1EB8*/ /*LATIN CAPITAL LETTER E WITH DOT BELOW*/ + 0x1EB9, /*U+1EB9*/ /**/ + 0x1EBB, /*U+1EBA*/ /*LATIN CAPITAL LETTER E WITH HOOK ABOVE*/ + 0x1EBB, /*U+1EBB*/ /**/ + 0x1EBD, /*U+1EBC*/ /*LATIN CAPITAL LETTER E WITH TILDE*/ + 0x1EBD, /*U+1EBD*/ /**/ + 0x1EBF, /*U+1EBE*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE*/ + 0x1EBF, /*U+1EBF*/ /**/ + 0x1EC1, /*U+1EC0*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE*/ + 0x1EC1, /*U+1EC1*/ /**/ + 0x1EC3, /*U+1EC2*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE*/ + 0x1EC3, /*U+1EC3*/ /**/ + 0x1EC5, /*U+1EC4*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE*/ + 0x1EC5, /*U+1EC5*/ /**/ + 0x1EC7, /*U+1EC6*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW*/ + 0x1EC7, /*U+1EC7*/ /**/ + 0x1EC9, /*U+1EC8*/ /*LATIN CAPITAL LETTER I WITH HOOK ABOVE*/ + 0x1EC9, /*U+1EC9*/ /**/ + 0x1ECB, /*U+1ECA*/ /*LATIN CAPITAL LETTER I WITH DOT BELOW*/ + 0x1ECB, /*U+1ECB*/ /**/ + 0x1ECD, /*U+1ECC*/ /*LATIN CAPITAL LETTER O WITH DOT BELOW*/ + 0x1ECD, /*U+1ECD*/ /**/ + 0x1ECF, /*U+1ECE*/ /*LATIN CAPITAL LETTER O WITH HOOK ABOVE*/ + 0x1ECF, /*U+1ECF*/ /**/ + 0x1ED1, /*U+1ED0*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE*/ + 0x1ED1, /*U+1ED1*/ /**/ + 0x1ED3, /*U+1ED2*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE*/ + 0x1ED3, /*U+1ED3*/ /**/ + 0x1ED5, /*U+1ED4*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE*/ + 0x1ED5, /*U+1ED5*/ /**/ + 0x1ED7, /*U+1ED6*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE*/ + 0x1ED7, /*U+1ED7*/ /**/ + 0x1ED9, /*U+1ED8*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW*/ + 0x1ED9, /*U+1ED9*/ /**/ + 0x1EDB, /*U+1EDA*/ /*LATIN CAPITAL LETTER O WITH HORN AND ACUTE*/ + 0x1EDB, /*U+1EDB*/ /**/ + 0x1EDD, /*U+1EDC*/ /*LATIN CAPITAL LETTER O WITH HORN AND GRAVE*/ + 0x1EDD, /*U+1EDD*/ /**/ + 0x1EDF, /*U+1EDE*/ /*LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE*/ + 0x1EDF, /*U+1EDF*/ /**/ + 0x1EE1, /*U+1EE0*/ /*LATIN CAPITAL LETTER O WITH HORN AND TILDE*/ + 0x1EE1, /*U+1EE1*/ /**/ + 0x1EE3, /*U+1EE2*/ /*LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW*/ + 0x1EE3, /*U+1EE3*/ /**/ + 0x1EE5, /*U+1EE4*/ /*LATIN CAPITAL LETTER U WITH DOT BELOW*/ + 0x1EE5, /*U+1EE5*/ /**/ + 0x1EE7, /*U+1EE6*/ /*LATIN CAPITAL LETTER U WITH HOOK ABOVE*/ + 0x1EE7, /*U+1EE7*/ /**/ + 0x1EE9, /*U+1EE8*/ /*LATIN CAPITAL LETTER U WITH HORN AND ACUTE*/ + 0x1EE9, /*U+1EE9*/ /**/ + 0x1EEB, /*U+1EEA*/ /*LATIN CAPITAL LETTER U WITH HORN AND GRAVE*/ + 0x1EEB, /*U+1EEB*/ /**/ + 0x1EED, /*U+1EEC*/ /*LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE*/ + 0x1EED, /*U+1EED*/ /**/ + 0x1EEF, /*U+1EEE*/ /*LATIN CAPITAL LETTER U WITH HORN AND TILDE*/ + 0x1EEF, /*U+1EEF*/ /**/ + 0x1EF1, /*U+1EF0*/ /*LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW*/ + 0x1EF1, /*U+1EF1*/ /**/ + 0x1EF3, /*U+1EF2*/ /*LATIN CAPITAL LETTER Y WITH GRAVE*/ + 0x1EF3, /*U+1EF3*/ /**/ + 0x1EF5, /*U+1EF4*/ /*LATIN CAPITAL LETTER Y WITH DOT BELOW*/ + 0x1EF5, /*U+1EF5*/ /**/ + 0x1EF7, /*U+1EF6*/ /*LATIN CAPITAL LETTER Y WITH HOOK ABOVE*/ + 0x1EF7, /*U+1EF7*/ /**/ + 0x1EF9, /*U+1EF8*/ /*LATIN CAPITAL LETTER Y WITH TILDE*/ + 0x1EF9, /*U+1EF9*/ /**/ + 0x1EFB, /*U+1EFA*/ /*LATIN CAPITAL LETTER MIDDLE-WELSH LL*/ + 0x1EFB, /*U+1EFB*/ /**/ + 0x1EFD, /*U+1EFC*/ /*LATIN CAPITAL LETTER MIDDLE-WELSH V*/ + 0x1EFD, /*U+1EFD*/ /**/ + 0x1EFF, /*U+1EFE*/ /*LATIN CAPITAL LETTER Y WITH LOOP*/ + 0x1EFF, /*U+1EFF*/ /**/ + 0x1F00, /*U+1F00*/ /**/ + 0x1F01, /*U+1F01*/ /**/ + 0x1F02, /*U+1F02*/ /**/ + 0x1F03, /*U+1F03*/ /**/ + 0x1F04, /*U+1F04*/ /**/ + 0x1F05, /*U+1F05*/ /**/ + 0x1F06, /*U+1F06*/ /**/ + 0x1F07, /*U+1F07*/ /**/ + 0x1F00, /*U+1F08*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI*/ + 0x1F01, /*U+1F09*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA*/ + 0x1F02, /*U+1F0A*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA*/ + 0x1F03, /*U+1F0B*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA*/ + 0x1F04, /*U+1F0C*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA*/ + 0x1F05, /*U+1F0D*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA*/ + 0x1F06, /*U+1F0E*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI*/ + 0x1F07, /*U+1F0F*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI*/ + 0x1F10, /*U+1F10*/ /**/ + 0x1F11, /*U+1F11*/ /**/ + 0x1F12, /*U+1F12*/ /**/ + 0x1F13, /*U+1F13*/ /**/ + 0x1F14, /*U+1F14*/ /**/ + 0x1F15, /*U+1F15*/ /**/ + 0x1F16, /*U+1F16*/ /**/ + 0x1F17, /*U+1F17*/ /**/ + 0x1F10, /*U+1F18*/ /*GREEK CAPITAL LETTER EPSILON WITH PSILI*/ + 0x1F11, /*U+1F19*/ /*GREEK CAPITAL LETTER EPSILON WITH DASIA*/ + 0x1F12, /*U+1F1A*/ /*GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA*/ + 0x1F13, /*U+1F1B*/ /*GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA*/ + 0x1F14, /*U+1F1C*/ /*GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA*/ + 0x1F15, /*U+1F1D*/ /*GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA*/ + 0x1F1E, /*U+1F1E*/ /**/ + 0x1F1F, /*U+1F1F*/ /**/ + 0x1F20, /*U+1F20*/ /**/ + 0x1F21, /*U+1F21*/ /**/ + 0x1F22, /*U+1F22*/ /**/ + 0x1F23, /*U+1F23*/ /**/ + 0x1F24, /*U+1F24*/ /**/ + 0x1F25, /*U+1F25*/ /**/ + 0x1F26, /*U+1F26*/ /**/ + 0x1F27, /*U+1F27*/ /**/ + 0x1F20, /*U+1F28*/ /*GREEK CAPITAL LETTER ETA WITH PSILI*/ + 0x1F21, /*U+1F29*/ /*GREEK CAPITAL LETTER ETA WITH DASIA*/ + 0x1F22, /*U+1F2A*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA*/ + 0x1F23, /*U+1F2B*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA*/ + 0x1F24, /*U+1F2C*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA*/ + 0x1F25, /*U+1F2D*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA*/ + 0x1F26, /*U+1F2E*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI*/ + 0x1F27, /*U+1F2F*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI*/ + 0x1F30, /*U+1F30*/ /**/ + 0x1F31, /*U+1F31*/ /**/ + 0x1F32, /*U+1F32*/ /**/ + 0x1F33, /*U+1F33*/ /**/ + 0x1F34, /*U+1F34*/ /**/ + 0x1F35, /*U+1F35*/ /**/ + 0x1F36, /*U+1F36*/ /**/ + 0x1F37, /*U+1F37*/ /**/ + 0x1F30, /*U+1F38*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI*/ + 0x1F31, /*U+1F39*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA*/ + 0x1F32, /*U+1F3A*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA*/ + 0x1F33, /*U+1F3B*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA*/ + 0x1F34, /*U+1F3C*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA*/ + 0x1F35, /*U+1F3D*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA*/ + 0x1F36, /*U+1F3E*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI*/ + 0x1F37, /*U+1F3F*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI*/ + 0x1F40, /*U+1F40*/ /**/ + 0x1F41, /*U+1F41*/ /**/ + 0x1F42, /*U+1F42*/ /**/ + 0x1F43, /*U+1F43*/ /**/ + 0x1F44, /*U+1F44*/ /**/ + 0x1F45, /*U+1F45*/ /**/ + 0x1F46, /*U+1F46*/ /**/ + 0x1F47, /*U+1F47*/ /**/ + 0x1F40, /*U+1F48*/ /*GREEK CAPITAL LETTER OMICRON WITH PSILI*/ + 0x1F41, /*U+1F49*/ /*GREEK CAPITAL LETTER OMICRON WITH DASIA*/ + 0x1F42, /*U+1F4A*/ /*GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA*/ + 0x1F43, /*U+1F4B*/ /*GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA*/ + 0x1F44, /*U+1F4C*/ /*GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA*/ + 0x1F45, /*U+1F4D*/ /*GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA*/ + 0x1F4E, /*U+1F4E*/ /**/ + 0x1F4F, /*U+1F4F*/ /**/ + 0x1F50, /*U+1F50*/ /**/ + 0x1F51, /*U+1F51*/ /**/ + 0x1F52, /*U+1F52*/ /**/ + 0x1F53, /*U+1F53*/ /**/ + 0x1F54, /*U+1F54*/ /**/ + 0x1F55, /*U+1F55*/ /**/ + 0x1F56, /*U+1F56*/ /**/ + 0x1F57, /*U+1F57*/ /**/ + 0x1F58, /*U+1F58*/ /**/ + 0x1F51, /*U+1F59*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA*/ + 0x1F5A, /*U+1F5A*/ /**/ + 0x1F53, /*U+1F5B*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA*/ + 0x1F5C, /*U+1F5C*/ /**/ + 0x1F55, /*U+1F5D*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA*/ + 0x1F5E, /*U+1F5E*/ /**/ + 0x1F57, /*U+1F5F*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI*/ + 0x1F60, /*U+1F60*/ /**/ + 0x1F61, /*U+1F61*/ /**/ + 0x1F62, /*U+1F62*/ /**/ + 0x1F63, /*U+1F63*/ /**/ + 0x1F64, /*U+1F64*/ /**/ + 0x1F65, /*U+1F65*/ /**/ + 0x1F66, /*U+1F66*/ /**/ + 0x1F67, /*U+1F67*/ /**/ + 0x1F60, /*U+1F68*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI*/ + 0x1F61, /*U+1F69*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA*/ + 0x1F62, /*U+1F6A*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA*/ + 0x1F63, /*U+1F6B*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA*/ + 0x1F64, /*U+1F6C*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA*/ + 0x1F65, /*U+1F6D*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA*/ + 0x1F66, /*U+1F6E*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI*/ + 0x1F67, /*U+1F6F*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI*/ + 0x1F70, /*U+1F70*/ /**/ + 0x1F71, /*U+1F71*/ /**/ + 0x1F72, /*U+1F72*/ /**/ + 0x1F73, /*U+1F73*/ /**/ + 0x1F74, /*U+1F74*/ /**/ + 0x1F75, /*U+1F75*/ /**/ + 0x1F76, /*U+1F76*/ /**/ + 0x1F77, /*U+1F77*/ /**/ + 0x1F78, /*U+1F78*/ /**/ + 0x1F79, /*U+1F79*/ /**/ + 0x1F7A, /*U+1F7A*/ /**/ + 0x1F7B, /*U+1F7B*/ /**/ + 0x1F7C, /*U+1F7C*/ /**/ + 0x1F7D, /*U+1F7D*/ /**/ + 0x1F7E, /*U+1F7E*/ /**/ + 0x1F7F, /*U+1F7F*/ /**/ + 0x1F80, /*U+1F80*/ /**/ + 0x1F81, /*U+1F81*/ /**/ + 0x1F82, /*U+1F82*/ /**/ + 0x1F83, /*U+1F83*/ /**/ + 0x1F84, /*U+1F84*/ /**/ + 0x1F85, /*U+1F85*/ /**/ + 0x1F86, /*U+1F86*/ /**/ + 0x1F87, /*U+1F87*/ /**/ + 0x1F80, /*U+1F88*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI*/ + 0x1F81, /*U+1F89*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI*/ + 0x1F82, /*U+1F8A*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI*/ + 0x1F83, /*U+1F8B*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI*/ + 0x1F84, /*U+1F8C*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI*/ + 0x1F85, /*U+1F8D*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI*/ + 0x1F86, /*U+1F8E*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI*/ + 0x1F87, /*U+1F8F*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI*/ + 0x1F90, /*U+1F90*/ /**/ + 0x1F91, /*U+1F91*/ /**/ + 0x1F92, /*U+1F92*/ /**/ + 0x1F93, /*U+1F93*/ /**/ + 0x1F94, /*U+1F94*/ /**/ + 0x1F95, /*U+1F95*/ /**/ + 0x1F96, /*U+1F96*/ /**/ + 0x1F97, /*U+1F97*/ /**/ + 0x1F90, /*U+1F98*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI*/ + 0x1F91, /*U+1F99*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI*/ + 0x1F92, /*U+1F9A*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI*/ + 0x1F93, /*U+1F9B*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI*/ + 0x1F94, /*U+1F9C*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI*/ + 0x1F95, /*U+1F9D*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI*/ + 0x1F96, /*U+1F9E*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI*/ + 0x1F97, /*U+1F9F*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI*/ + 0x1FA0, /*U+1FA0*/ /**/ + 0x1FA1, /*U+1FA1*/ /**/ + 0x1FA2, /*U+1FA2*/ /**/ + 0x1FA3, /*U+1FA3*/ /**/ + 0x1FA4, /*U+1FA4*/ /**/ + 0x1FA5, /*U+1FA5*/ /**/ + 0x1FA6, /*U+1FA6*/ /**/ + 0x1FA7, /*U+1FA7*/ /**/ + 0x1FA0, /*U+1FA8*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI*/ + 0x1FA1, /*U+1FA9*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI*/ + 0x1FA2, /*U+1FAA*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI*/ + 0x1FA3, /*U+1FAB*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI*/ + 0x1FA4, /*U+1FAC*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI*/ + 0x1FA5, /*U+1FAD*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI*/ + 0x1FA6, /*U+1FAE*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI*/ + 0x1FA7, /*U+1FAF*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI*/ + 0x1FB0, /*U+1FB0*/ /**/ + 0x1FB1, /*U+1FB1*/ /**/ + 0x1FB2, /*U+1FB2*/ /**/ + 0x1FB3, /*U+1FB3*/ /**/ + 0x1FB4, /*U+1FB4*/ /**/ + 0x1FB5, /*U+1FB5*/ /**/ + 0x1FB6, /*U+1FB6*/ /**/ + 0x1FB7, /*U+1FB7*/ /**/ + 0x1FB0, /*U+1FB8*/ /*GREEK CAPITAL LETTER ALPHA WITH VRACHY*/ + 0x1FB1, /*U+1FB9*/ /*GREEK CAPITAL LETTER ALPHA WITH MACRON*/ + 0x1F70, /*U+1FBA*/ /*GREEK CAPITAL LETTER ALPHA WITH VARIA*/ + 0x1F71, /*U+1FBB*/ /*GREEK CAPITAL LETTER ALPHA WITH OXIA*/ + 0x1FB3, /*U+1FBC*/ /*GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI*/ + 0x1FBD, /*U+1FBD*/ /**/ + 0x1FBE, /*U+1FBE*/ /**/ + 0x1FBF, /*U+1FBF*/ /**/ + 0x1FC0, /*U+1FC0*/ /**/ + 0x1FC1, /*U+1FC1*/ /**/ + 0x1FC2, /*U+1FC2*/ /**/ + 0x1FC3, /*U+1FC3*/ /**/ + 0x1FC4, /*U+1FC4*/ /**/ + 0x1FC5, /*U+1FC5*/ /**/ + 0x1FC6, /*U+1FC6*/ /**/ + 0x1FC7, /*U+1FC7*/ /**/ + 0x1F72, /*U+1FC8*/ /*GREEK CAPITAL LETTER EPSILON WITH VARIA*/ + 0x1F73, /*U+1FC9*/ /*GREEK CAPITAL LETTER EPSILON WITH OXIA*/ + 0x1F74, /*U+1FCA*/ /*GREEK CAPITAL LETTER ETA WITH VARIA*/ + 0x1F75, /*U+1FCB*/ /*GREEK CAPITAL LETTER ETA WITH OXIA*/ + 0x1FC3, /*U+1FCC*/ /*GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI*/ + 0x1FCD, /*U+1FCD*/ /**/ + 0x1FCE, /*U+1FCE*/ /**/ + 0x1FCF, /*U+1FCF*/ /**/ + 0x1FD0, /*U+1FD0*/ /**/ + 0x1FD1, /*U+1FD1*/ /**/ + 0x1FD2, /*U+1FD2*/ /**/ + 0x1FD3, /*U+1FD3*/ /**/ + 0x1FD4, /*U+1FD4*/ /**/ + 0x1FD5, /*U+1FD5*/ /**/ + 0x1FD6, /*U+1FD6*/ /**/ + 0x1FD7, /*U+1FD7*/ /**/ + 0x1FD0, /*U+1FD8*/ /*GREEK CAPITAL LETTER IOTA WITH VRACHY*/ + 0x1FD1, /*U+1FD9*/ /*GREEK CAPITAL LETTER IOTA WITH MACRON*/ + 0x1F76, /*U+1FDA*/ /*GREEK CAPITAL LETTER IOTA WITH VARIA*/ + 0x1F77, /*U+1FDB*/ /*GREEK CAPITAL LETTER IOTA WITH OXIA*/ + 0x1FDC, /*U+1FDC*/ /**/ + 0x1FDD, /*U+1FDD*/ /**/ + 0x1FDE, /*U+1FDE*/ /**/ + 0x1FDF, /*U+1FDF*/ /**/ + 0x1FE0, /*U+1FE0*/ /**/ + 0x1FE1, /*U+1FE1*/ /**/ + 0x1FE2, /*U+1FE2*/ /**/ + 0x1FE3, /*U+1FE3*/ /**/ + 0x1FE4, /*U+1FE4*/ /**/ + 0x1FE5, /*U+1FE5*/ /**/ + 0x1FE6, /*U+1FE6*/ /**/ + 0x1FE7, /*U+1FE7*/ /**/ + 0x1FE0, /*U+1FE8*/ /*GREEK CAPITAL LETTER UPSILON WITH VRACHY*/ + 0x1FE1, /*U+1FE9*/ /*GREEK CAPITAL LETTER UPSILON WITH MACRON*/ + 0x1F7A, /*U+1FEA*/ /*GREEK CAPITAL LETTER UPSILON WITH VARIA*/ + 0x1F7B, /*U+1FEB*/ /*GREEK CAPITAL LETTER UPSILON WITH OXIA*/ + 0x1FE5, /*U+1FEC*/ /*GREEK CAPITAL LETTER RHO WITH DASIA*/ + 0x1FED, /*U+1FED*/ /**/ + 0x1FEE, /*U+1FEE*/ /**/ + 0x1FEF, /*U+1FEF*/ /**/ + 0x1FF0, /*U+1FF0*/ /**/ + 0x1FF1, /*U+1FF1*/ /**/ + 0x1FF2, /*U+1FF2*/ /**/ + 0x1FF3, /*U+1FF3*/ /**/ + 0x1FF4, /*U+1FF4*/ /**/ + 0x1FF5, /*U+1FF5*/ /**/ + 0x1FF6, /*U+1FF6*/ /**/ + 0x1FF7, /*U+1FF7*/ /**/ + 0x1F78, /*U+1FF8*/ /*GREEK CAPITAL LETTER OMICRON WITH VARIA*/ + 0x1F79, /*U+1FF9*/ /*GREEK CAPITAL LETTER OMICRON WITH OXIA*/ + 0x1F7C, /*U+1FFA*/ /*GREEK CAPITAL LETTER OMEGA WITH VARIA*/ + 0x1F7D, /*U+1FFB*/ /*GREEK CAPITAL LETTER OMEGA WITH OXIA*/ + 0x1FF3, /*U+1FFC*/ /*GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI*/ + 0x1FFD, /*U+1FFD*/ /**/ + 0x1FFE, /*U+1FFE*/ /**/ + 0x1FFF, /*U+1FFF*/ /**/ +}; + +static const uint16_t lower_table_6[192] = { + 0x2100, /*U+2100*/ /**/ + 0x2101, /*U+2101*/ /**/ + 0x2102, /*U+2102*/ /**/ + 0x2103, /*U+2103*/ /**/ + 0x2104, /*U+2104*/ /**/ + 0x2105, /*U+2105*/ /**/ + 0x2106, /*U+2106*/ /**/ + 0x2107, /*U+2107*/ /**/ + 0x2108, /*U+2108*/ /**/ + 0x2109, /*U+2109*/ /**/ + 0x210A, /*U+210A*/ /**/ + 0x210B, /*U+210B*/ /**/ + 0x210C, /*U+210C*/ /**/ + 0x210D, /*U+210D*/ /**/ + 0x210E, /*U+210E*/ /**/ + 0x210F, /*U+210F*/ /**/ + 0x2110, /*U+2110*/ /**/ + 0x2111, /*U+2111*/ /**/ + 0x2112, /*U+2112*/ /**/ + 0x2113, /*U+2113*/ /**/ + 0x2114, /*U+2114*/ /**/ + 0x2115, /*U+2115*/ /**/ + 0x2116, /*U+2116*/ /**/ + 0x2117, /*U+2117*/ /**/ + 0x2118, /*U+2118*/ /**/ + 0x2119, /*U+2119*/ /**/ + 0x211A, /*U+211A*/ /**/ + 0x211B, /*U+211B*/ /**/ + 0x211C, /*U+211C*/ /**/ + 0x211D, /*U+211D*/ /**/ + 0x211E, /*U+211E*/ /**/ + 0x211F, /*U+211F*/ /**/ + 0x2120, /*U+2120*/ /**/ + 0x2121, /*U+2121*/ /**/ + 0x2122, /*U+2122*/ /**/ + 0x2123, /*U+2123*/ /**/ + 0x2124, /*U+2124*/ /**/ + 0x2125, /*U+2125*/ /**/ + 0x03C9, /*U+2126*/ /*OHM SIGN*/ + 0x2127, /*U+2127*/ /**/ + 0x2128, /*U+2128*/ /**/ + 0x2129, /*U+2129*/ /**/ + 0x006B, /*U+212A*/ /*KELVIN SIGN*/ + 0x00E5, /*U+212B*/ /*ANGSTROM SIGN*/ + 0x212C, /*U+212C*/ /**/ + 0x212D, /*U+212D*/ /**/ + 0x212E, /*U+212E*/ /**/ + 0x212F, /*U+212F*/ /**/ + 0x2130, /*U+2130*/ /**/ + 0x2131, /*U+2131*/ /**/ + 0x214E, /*U+2132*/ /*TURNED CAPITAL F*/ + 0x2133, /*U+2133*/ /**/ + 0x2134, /*U+2134*/ /**/ + 0x2135, /*U+2135*/ /**/ + 0x2136, /*U+2136*/ /**/ + 0x2137, /*U+2137*/ /**/ + 0x2138, /*U+2138*/ /**/ + 0x2139, /*U+2139*/ /**/ + 0x213A, /*U+213A*/ /**/ + 0x213B, /*U+213B*/ /**/ + 0x213C, /*U+213C*/ /**/ + 0x213D, /*U+213D*/ /**/ + 0x213E, /*U+213E*/ /**/ + 0x213F, /*U+213F*/ /**/ + 0x2140, /*U+2140*/ /**/ + 0x2141, /*U+2141*/ /**/ + 0x2142, /*U+2142*/ /**/ + 0x2143, /*U+2143*/ /**/ + 0x2144, /*U+2144*/ /**/ + 0x2145, /*U+2145*/ /**/ + 0x2146, /*U+2146*/ /**/ + 0x2147, /*U+2147*/ /**/ + 0x2148, /*U+2148*/ /**/ + 0x2149, /*U+2149*/ /**/ + 0x214A, /*U+214A*/ /**/ + 0x214B, /*U+214B*/ /**/ + 0x214C, /*U+214C*/ /**/ + 0x214D, /*U+214D*/ /**/ + 0x214E, /*U+214E*/ /**/ + 0x214F, /*U+214F*/ /**/ + 0x2150, /*U+2150*/ /**/ + 0x2151, /*U+2151*/ /**/ + 0x2152, /*U+2152*/ /**/ + 0x2153, /*U+2153*/ /**/ + 0x2154, /*U+2154*/ /**/ + 0x2155, /*U+2155*/ /**/ + 0x2156, /*U+2156*/ /**/ + 0x2157, /*U+2157*/ /**/ + 0x2158, /*U+2158*/ /**/ + 0x2159, /*U+2159*/ /**/ + 0x215A, /*U+215A*/ /**/ + 0x215B, /*U+215B*/ /**/ + 0x215C, /*U+215C*/ /**/ + 0x215D, /*U+215D*/ /**/ + 0x215E, /*U+215E*/ /**/ + 0x215F, /*U+215F*/ /**/ + 0x2170, /*U+2160*/ /*ROMAN NUMERAL ONE*/ + 0x2171, /*U+2161*/ /*ROMAN NUMERAL TWO*/ + 0x2172, /*U+2162*/ /*ROMAN NUMERAL THREE*/ + 0x2173, /*U+2163*/ /*ROMAN NUMERAL FOUR*/ + 0x2174, /*U+2164*/ /*ROMAN NUMERAL FIVE*/ + 0x2175, /*U+2165*/ /*ROMAN NUMERAL SIX*/ + 0x2176, /*U+2166*/ /*ROMAN NUMERAL SEVEN*/ + 0x2177, /*U+2167*/ /*ROMAN NUMERAL EIGHT*/ + 0x2178, /*U+2168*/ /*ROMAN NUMERAL NINE*/ + 0x2179, /*U+2169*/ /*ROMAN NUMERAL TEN*/ + 0x217A, /*U+216A*/ /*ROMAN NUMERAL ELEVEN*/ + 0x217B, /*U+216B*/ /*ROMAN NUMERAL TWELVE*/ + 0x217C, /*U+216C*/ /*ROMAN NUMERAL FIFTY*/ + 0x217D, /*U+216D*/ /*ROMAN NUMERAL ONE HUNDRED*/ + 0x217E, /*U+216E*/ /*ROMAN NUMERAL FIVE HUNDRED*/ + 0x217F, /*U+216F*/ /*ROMAN NUMERAL ONE THOUSAND*/ + 0x2170, /*U+2170*/ /**/ + 0x2171, /*U+2171*/ /**/ + 0x2172, /*U+2172*/ /**/ + 0x2173, /*U+2173*/ /**/ + 0x2174, /*U+2174*/ /**/ + 0x2175, /*U+2175*/ /**/ + 0x2176, /*U+2176*/ /**/ + 0x2177, /*U+2177*/ /**/ + 0x2178, /*U+2178*/ /**/ + 0x2179, /*U+2179*/ /**/ + 0x217A, /*U+217A*/ /**/ + 0x217B, /*U+217B*/ /**/ + 0x217C, /*U+217C*/ /**/ + 0x217D, /*U+217D*/ /**/ + 0x217E, /*U+217E*/ /**/ + 0x217F, /*U+217F*/ /**/ + 0x2180, /*U+2180*/ /**/ + 0x2181, /*U+2181*/ /**/ + 0x2182, /*U+2182*/ /**/ + 0x2184, /*U+2183*/ /*ROMAN NUMERAL REVERSED ONE HUNDRED*/ + 0x2184, /*U+2184*/ /**/ + 0x2185, /*U+2185*/ /**/ + 0x2186, /*U+2186*/ /**/ + 0x2187, /*U+2187*/ /**/ + 0x2188, /*U+2188*/ /**/ + 0x2189, /*U+2189*/ /**/ + 0x218A, /*U+218A*/ /**/ + 0x218B, /*U+218B*/ /**/ + 0x218C, /*U+218C*/ /**/ + 0x218D, /*U+218D*/ /**/ + 0x218E, /*U+218E*/ /**/ + 0x218F, /*U+218F*/ /**/ + 0x2190, /*U+2190*/ /**/ + 0x2191, /*U+2191*/ /**/ + 0x2192, /*U+2192*/ /**/ + 0x2193, /*U+2193*/ /**/ + 0x2194, /*U+2194*/ /**/ + 0x2195, /*U+2195*/ /**/ + 0x2196, /*U+2196*/ /**/ + 0x2197, /*U+2197*/ /**/ + 0x2198, /*U+2198*/ /**/ + 0x2199, /*U+2199*/ /**/ + 0x219A, /*U+219A*/ /**/ + 0x219B, /*U+219B*/ /**/ + 0x219C, /*U+219C*/ /**/ + 0x219D, /*U+219D*/ /**/ + 0x219E, /*U+219E*/ /**/ + 0x219F, /*U+219F*/ /**/ + 0x21A0, /*U+21A0*/ /**/ + 0x21A1, /*U+21A1*/ /**/ + 0x21A2, /*U+21A2*/ /**/ + 0x21A3, /*U+21A3*/ /**/ + 0x21A4, /*U+21A4*/ /**/ + 0x21A5, /*U+21A5*/ /**/ + 0x21A6, /*U+21A6*/ /**/ + 0x21A7, /*U+21A7*/ /**/ + 0x21A8, /*U+21A8*/ /**/ + 0x21A9, /*U+21A9*/ /**/ + 0x21AA, /*U+21AA*/ /**/ + 0x21AB, /*U+21AB*/ /**/ + 0x21AC, /*U+21AC*/ /**/ + 0x21AD, /*U+21AD*/ /**/ + 0x21AE, /*U+21AE*/ /**/ + 0x21AF, /*U+21AF*/ /**/ + 0x21B0, /*U+21B0*/ /**/ + 0x21B1, /*U+21B1*/ /**/ + 0x21B2, /*U+21B2*/ /**/ + 0x21B3, /*U+21B3*/ /**/ + 0x21B4, /*U+21B4*/ /**/ + 0x21B5, /*U+21B5*/ /**/ + 0x21B6, /*U+21B6*/ /**/ + 0x21B7, /*U+21B7*/ /**/ + 0x21B8, /*U+21B8*/ /**/ + 0x21B9, /*U+21B9*/ /**/ + 0x21BA, /*U+21BA*/ /**/ + 0x21BB, /*U+21BB*/ /**/ + 0x21BC, /*U+21BC*/ /**/ + 0x21BD, /*U+21BD*/ /**/ + 0x21BE, /*U+21BE*/ /**/ + 0x21BF, /*U+21BF*/ /**/ +}; + +static const uint16_t lower_table_7[128] = { + 0x2480, /*U+2480*/ /**/ + 0x2481, /*U+2481*/ /**/ + 0x2482, /*U+2482*/ /**/ + 0x2483, /*U+2483*/ /**/ + 0x2484, /*U+2484*/ /**/ + 0x2485, /*U+2485*/ /**/ + 0x2486, /*U+2486*/ /**/ + 0x2487, /*U+2487*/ /**/ + 0x2488, /*U+2488*/ /**/ + 0x2489, /*U+2489*/ /**/ + 0x248A, /*U+248A*/ /**/ + 0x248B, /*U+248B*/ /**/ + 0x248C, /*U+248C*/ /**/ + 0x248D, /*U+248D*/ /**/ + 0x248E, /*U+248E*/ /**/ + 0x248F, /*U+248F*/ /**/ + 0x2490, /*U+2490*/ /**/ + 0x2491, /*U+2491*/ /**/ + 0x2492, /*U+2492*/ /**/ + 0x2493, /*U+2493*/ /**/ + 0x2494, /*U+2494*/ /**/ + 0x2495, /*U+2495*/ /**/ + 0x2496, /*U+2496*/ /**/ + 0x2497, /*U+2497*/ /**/ + 0x2498, /*U+2498*/ /**/ + 0x2499, /*U+2499*/ /**/ + 0x249A, /*U+249A*/ /**/ + 0x249B, /*U+249B*/ /**/ + 0x249C, /*U+249C*/ /**/ + 0x249D, /*U+249D*/ /**/ + 0x249E, /*U+249E*/ /**/ + 0x249F, /*U+249F*/ /**/ + 0x24A0, /*U+24A0*/ /**/ + 0x24A1, /*U+24A1*/ /**/ + 0x24A2, /*U+24A2*/ /**/ + 0x24A3, /*U+24A3*/ /**/ + 0x24A4, /*U+24A4*/ /**/ + 0x24A5, /*U+24A5*/ /**/ + 0x24A6, /*U+24A6*/ /**/ + 0x24A7, /*U+24A7*/ /**/ + 0x24A8, /*U+24A8*/ /**/ + 0x24A9, /*U+24A9*/ /**/ + 0x24AA, /*U+24AA*/ /**/ + 0x24AB, /*U+24AB*/ /**/ + 0x24AC, /*U+24AC*/ /**/ + 0x24AD, /*U+24AD*/ /**/ + 0x24AE, /*U+24AE*/ /**/ + 0x24AF, /*U+24AF*/ /**/ + 0x24B0, /*U+24B0*/ /**/ + 0x24B1, /*U+24B1*/ /**/ + 0x24B2, /*U+24B2*/ /**/ + 0x24B3, /*U+24B3*/ /**/ + 0x24B4, /*U+24B4*/ /**/ + 0x24B5, /*U+24B5*/ /**/ + 0x24D0, /*U+24B6*/ /*CIRCLED LATIN CAPITAL LETTER A*/ + 0x24D1, /*U+24B7*/ /*CIRCLED LATIN CAPITAL LETTER B*/ + 0x24D2, /*U+24B8*/ /*CIRCLED LATIN CAPITAL LETTER C*/ + 0x24D3, /*U+24B9*/ /*CIRCLED LATIN CAPITAL LETTER D*/ + 0x24D4, /*U+24BA*/ /*CIRCLED LATIN CAPITAL LETTER E*/ + 0x24D5, /*U+24BB*/ /*CIRCLED LATIN CAPITAL LETTER F*/ + 0x24D6, /*U+24BC*/ /*CIRCLED LATIN CAPITAL LETTER G*/ + 0x24D7, /*U+24BD*/ /*CIRCLED LATIN CAPITAL LETTER H*/ + 0x24D8, /*U+24BE*/ /*CIRCLED LATIN CAPITAL LETTER I*/ + 0x24D9, /*U+24BF*/ /*CIRCLED LATIN CAPITAL LETTER J*/ + 0x24DA, /*U+24C0*/ /*CIRCLED LATIN CAPITAL LETTER K*/ + 0x24DB, /*U+24C1*/ /*CIRCLED LATIN CAPITAL LETTER L*/ + 0x24DC, /*U+24C2*/ /*CIRCLED LATIN CAPITAL LETTER M*/ + 0x24DD, /*U+24C3*/ /*CIRCLED LATIN CAPITAL LETTER N*/ + 0x24DE, /*U+24C4*/ /*CIRCLED LATIN CAPITAL LETTER O*/ + 0x24DF, /*U+24C5*/ /*CIRCLED LATIN CAPITAL LETTER P*/ + 0x24E0, /*U+24C6*/ /*CIRCLED LATIN CAPITAL LETTER Q*/ + 0x24E1, /*U+24C7*/ /*CIRCLED LATIN CAPITAL LETTER R*/ + 0x24E2, /*U+24C8*/ /*CIRCLED LATIN CAPITAL LETTER S*/ + 0x24E3, /*U+24C9*/ /*CIRCLED LATIN CAPITAL LETTER T*/ + 0x24E4, /*U+24CA*/ /*CIRCLED LATIN CAPITAL LETTER U*/ + 0x24E5, /*U+24CB*/ /*CIRCLED LATIN CAPITAL LETTER V*/ + 0x24E6, /*U+24CC*/ /*CIRCLED LATIN CAPITAL LETTER W*/ + 0x24E7, /*U+24CD*/ /*CIRCLED LATIN CAPITAL LETTER X*/ + 0x24E8, /*U+24CE*/ /*CIRCLED LATIN CAPITAL LETTER Y*/ + 0x24E9, /*U+24CF*/ /*CIRCLED LATIN CAPITAL LETTER Z*/ + 0x24D0, /*U+24D0*/ /**/ + 0x24D1, /*U+24D1*/ /**/ + 0x24D2, /*U+24D2*/ /**/ + 0x24D3, /*U+24D3*/ /**/ + 0x24D4, /*U+24D4*/ /**/ + 0x24D5, /*U+24D5*/ /**/ + 0x24D6, /*U+24D6*/ /**/ + 0x24D7, /*U+24D7*/ /**/ + 0x24D8, /*U+24D8*/ /**/ + 0x24D9, /*U+24D9*/ /**/ + 0x24DA, /*U+24DA*/ /**/ + 0x24DB, /*U+24DB*/ /**/ + 0x24DC, /*U+24DC*/ /**/ + 0x24DD, /*U+24DD*/ /**/ + 0x24DE, /*U+24DE*/ /**/ + 0x24DF, /*U+24DF*/ /**/ + 0x24E0, /*U+24E0*/ /**/ + 0x24E1, /*U+24E1*/ /**/ + 0x24E2, /*U+24E2*/ /**/ + 0x24E3, /*U+24E3*/ /**/ + 0x24E4, /*U+24E4*/ /**/ + 0x24E5, /*U+24E5*/ /**/ + 0x24E6, /*U+24E6*/ /**/ + 0x24E7, /*U+24E7*/ /**/ + 0x24E8, /*U+24E8*/ /**/ + 0x24E9, /*U+24E9*/ /**/ + 0x24EA, /*U+24EA*/ /**/ + 0x24EB, /*U+24EB*/ /**/ + 0x24EC, /*U+24EC*/ /**/ + 0x24ED, /*U+24ED*/ /**/ + 0x24EE, /*U+24EE*/ /**/ + 0x24EF, /*U+24EF*/ /**/ + 0x24F0, /*U+24F0*/ /**/ + 0x24F1, /*U+24F1*/ /**/ + 0x24F2, /*U+24F2*/ /**/ + 0x24F3, /*U+24F3*/ /**/ + 0x24F4, /*U+24F4*/ /**/ + 0x24F5, /*U+24F5*/ /**/ + 0x24F6, /*U+24F6*/ /**/ + 0x24F7, /*U+24F7*/ /**/ + 0x24F8, /*U+24F8*/ /**/ + 0x24F9, /*U+24F9*/ /**/ + 0x24FA, /*U+24FA*/ /**/ + 0x24FB, /*U+24FB*/ /**/ + 0x24FC, /*U+24FC*/ /**/ + 0x24FD, /*U+24FD*/ /**/ + 0x24FE, /*U+24FE*/ /**/ + 0x24FF, /*U+24FF*/ /**/ +}; + +static const uint16_t lower_table_8[256] = { + 0x2C30, /*U+2C00*/ /*GLAGOLITIC CAPITAL LETTER AZU*/ + 0x2C31, /*U+2C01*/ /*GLAGOLITIC CAPITAL LETTER BUKY*/ + 0x2C32, /*U+2C02*/ /*GLAGOLITIC CAPITAL LETTER VEDE*/ + 0x2C33, /*U+2C03*/ /*GLAGOLITIC CAPITAL LETTER GLAGOLI*/ + 0x2C34, /*U+2C04*/ /*GLAGOLITIC CAPITAL LETTER DOBRO*/ + 0x2C35, /*U+2C05*/ /*GLAGOLITIC CAPITAL LETTER YESTU*/ + 0x2C36, /*U+2C06*/ /*GLAGOLITIC CAPITAL LETTER ZHIVETE*/ + 0x2C37, /*U+2C07*/ /*GLAGOLITIC CAPITAL LETTER DZELO*/ + 0x2C38, /*U+2C08*/ /*GLAGOLITIC CAPITAL LETTER ZEMLJA*/ + 0x2C39, /*U+2C09*/ /*GLAGOLITIC CAPITAL LETTER IZHE*/ + 0x2C3A, /*U+2C0A*/ /*GLAGOLITIC CAPITAL LETTER INITIAL IZHE*/ + 0x2C3B, /*U+2C0B*/ /*GLAGOLITIC CAPITAL LETTER I*/ + 0x2C3C, /*U+2C0C*/ /*GLAGOLITIC CAPITAL LETTER DJERVI*/ + 0x2C3D, /*U+2C0D*/ /*GLAGOLITIC CAPITAL LETTER KAKO*/ + 0x2C3E, /*U+2C0E*/ /*GLAGOLITIC CAPITAL LETTER LJUDIJE*/ + 0x2C3F, /*U+2C0F*/ /*GLAGOLITIC CAPITAL LETTER MYSLITE*/ + 0x2C40, /*U+2C10*/ /*GLAGOLITIC CAPITAL LETTER NASHI*/ + 0x2C41, /*U+2C11*/ /*GLAGOLITIC CAPITAL LETTER ONU*/ + 0x2C42, /*U+2C12*/ /*GLAGOLITIC CAPITAL LETTER POKOJI*/ + 0x2C43, /*U+2C13*/ /*GLAGOLITIC CAPITAL LETTER RITSI*/ + 0x2C44, /*U+2C14*/ /*GLAGOLITIC CAPITAL LETTER SLOVO*/ + 0x2C45, /*U+2C15*/ /*GLAGOLITIC CAPITAL LETTER TVRIDO*/ + 0x2C46, /*U+2C16*/ /*GLAGOLITIC CAPITAL LETTER UKU*/ + 0x2C47, /*U+2C17*/ /*GLAGOLITIC CAPITAL LETTER FRITU*/ + 0x2C48, /*U+2C18*/ /*GLAGOLITIC CAPITAL LETTER HERU*/ + 0x2C49, /*U+2C19*/ /*GLAGOLITIC CAPITAL LETTER OTU*/ + 0x2C4A, /*U+2C1A*/ /*GLAGOLITIC CAPITAL LETTER PE*/ + 0x2C4B, /*U+2C1B*/ /*GLAGOLITIC CAPITAL LETTER SHTA*/ + 0x2C4C, /*U+2C1C*/ /*GLAGOLITIC CAPITAL LETTER TSI*/ + 0x2C4D, /*U+2C1D*/ /*GLAGOLITIC CAPITAL LETTER CHRIVI*/ + 0x2C4E, /*U+2C1E*/ /*GLAGOLITIC CAPITAL LETTER SHA*/ + 0x2C4F, /*U+2C1F*/ /*GLAGOLITIC CAPITAL LETTER YERU*/ + 0x2C50, /*U+2C20*/ /*GLAGOLITIC CAPITAL LETTER YERI*/ + 0x2C51, /*U+2C21*/ /*GLAGOLITIC CAPITAL LETTER YATI*/ + 0x2C52, /*U+2C22*/ /*GLAGOLITIC CAPITAL LETTER SPIDERY HA*/ + 0x2C53, /*U+2C23*/ /*GLAGOLITIC CAPITAL LETTER YU*/ + 0x2C54, /*U+2C24*/ /*GLAGOLITIC CAPITAL LETTER SMALL YUS*/ + 0x2C55, /*U+2C25*/ /*GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL*/ + 0x2C56, /*U+2C26*/ /*GLAGOLITIC CAPITAL LETTER YO*/ + 0x2C57, /*U+2C27*/ /*GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS*/ + 0x2C58, /*U+2C28*/ /*GLAGOLITIC CAPITAL LETTER BIG YUS*/ + 0x2C59, /*U+2C29*/ /*GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS*/ + 0x2C5A, /*U+2C2A*/ /*GLAGOLITIC CAPITAL LETTER FITA*/ + 0x2C5B, /*U+2C2B*/ /*GLAGOLITIC CAPITAL LETTER IZHITSA*/ + 0x2C5C, /*U+2C2C*/ /*GLAGOLITIC CAPITAL LETTER SHTAPIC*/ + 0x2C5D, /*U+2C2D*/ /*GLAGOLITIC CAPITAL LETTER TROKUTASTI A*/ + 0x2C5E, /*U+2C2E*/ /*GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE*/ + 0x2C2F, /*U+2C2F*/ /**/ + 0x2C30, /*U+2C30*/ /**/ + 0x2C31, /*U+2C31*/ /**/ + 0x2C32, /*U+2C32*/ /**/ + 0x2C33, /*U+2C33*/ /**/ + 0x2C34, /*U+2C34*/ /**/ + 0x2C35, /*U+2C35*/ /**/ + 0x2C36, /*U+2C36*/ /**/ + 0x2C37, /*U+2C37*/ /**/ + 0x2C38, /*U+2C38*/ /**/ + 0x2C39, /*U+2C39*/ /**/ + 0x2C3A, /*U+2C3A*/ /**/ + 0x2C3B, /*U+2C3B*/ /**/ + 0x2C3C, /*U+2C3C*/ /**/ + 0x2C3D, /*U+2C3D*/ /**/ + 0x2C3E, /*U+2C3E*/ /**/ + 0x2C3F, /*U+2C3F*/ /**/ + 0x2C40, /*U+2C40*/ /**/ + 0x2C41, /*U+2C41*/ /**/ + 0x2C42, /*U+2C42*/ /**/ + 0x2C43, /*U+2C43*/ /**/ + 0x2C44, /*U+2C44*/ /**/ + 0x2C45, /*U+2C45*/ /**/ + 0x2C46, /*U+2C46*/ /**/ + 0x2C47, /*U+2C47*/ /**/ + 0x2C48, /*U+2C48*/ /**/ + 0x2C49, /*U+2C49*/ /**/ + 0x2C4A, /*U+2C4A*/ /**/ + 0x2C4B, /*U+2C4B*/ /**/ + 0x2C4C, /*U+2C4C*/ /**/ + 0x2C4D, /*U+2C4D*/ /**/ + 0x2C4E, /*U+2C4E*/ /**/ + 0x2C4F, /*U+2C4F*/ /**/ + 0x2C50, /*U+2C50*/ /**/ + 0x2C51, /*U+2C51*/ /**/ + 0x2C52, /*U+2C52*/ /**/ + 0x2C53, /*U+2C53*/ /**/ + 0x2C54, /*U+2C54*/ /**/ + 0x2C55, /*U+2C55*/ /**/ + 0x2C56, /*U+2C56*/ /**/ + 0x2C57, /*U+2C57*/ /**/ + 0x2C58, /*U+2C58*/ /**/ + 0x2C59, /*U+2C59*/ /**/ + 0x2C5A, /*U+2C5A*/ /**/ + 0x2C5B, /*U+2C5B*/ /**/ + 0x2C5C, /*U+2C5C*/ /**/ + 0x2C5D, /*U+2C5D*/ /**/ + 0x2C5E, /*U+2C5E*/ /**/ + 0x2C5F, /*U+2C5F*/ /**/ + 0x2C61, /*U+2C60*/ /*LATIN CAPITAL LETTER L WITH DOUBLE BAR*/ + 0x2C61, /*U+2C61*/ /**/ + 0x026B, /*U+2C62*/ /*LATIN CAPITAL LETTER L WITH MIDDLE TILDE*/ + 0x1D7D, /*U+2C63*/ /*LATIN CAPITAL LETTER P WITH STROKE*/ + 0x027D, /*U+2C64*/ /*LATIN CAPITAL LETTER R WITH TAIL*/ + 0x2C65, /*U+2C65*/ /**/ + 0x2C66, /*U+2C66*/ /**/ + 0x2C68, /*U+2C67*/ /*LATIN CAPITAL LETTER H WITH DESCENDER*/ + 0x2C68, /*U+2C68*/ /**/ + 0x2C6A, /*U+2C69*/ /*LATIN CAPITAL LETTER K WITH DESCENDER*/ + 0x2C6A, /*U+2C6A*/ /**/ + 0x2C6C, /*U+2C6B*/ /*LATIN CAPITAL LETTER Z WITH DESCENDER*/ + 0x2C6C, /*U+2C6C*/ /**/ + 0x0251, /*U+2C6D*/ /*LATIN CAPITAL LETTER ALPHA*/ + 0x0271, /*U+2C6E*/ /*LATIN CAPITAL LETTER M WITH HOOK*/ + 0x0250, /*U+2C6F*/ /*LATIN CAPITAL LETTER TURNED A*/ + 0x0252, /*U+2C70*/ /*LATIN CAPITAL LETTER TURNED ALPHA*/ + 0x2C71, /*U+2C71*/ /**/ + 0x2C73, /*U+2C72*/ /*LATIN CAPITAL LETTER W WITH HOOK*/ + 0x2C73, /*U+2C73*/ /**/ + 0x2C74, /*U+2C74*/ /**/ + 0x2C76, /*U+2C75*/ /*LATIN CAPITAL LETTER HALF H*/ + 0x2C76, /*U+2C76*/ /**/ + 0x2C77, /*U+2C77*/ /**/ + 0x2C78, /*U+2C78*/ /**/ + 0x2C79, /*U+2C79*/ /**/ + 0x2C7A, /*U+2C7A*/ /**/ + 0x2C7B, /*U+2C7B*/ /**/ + 0x2C7C, /*U+2C7C*/ /**/ + 0x2C7D, /*U+2C7D*/ /**/ + 0x023F, /*U+2C7E*/ /*LATIN CAPITAL LETTER S WITH SWASH TAIL*/ + 0x0240, /*U+2C7F*/ /*LATIN CAPITAL LETTER Z WITH SWASH TAIL*/ + 0x2C81, /*U+2C80*/ /*COPTIC CAPITAL LETTER ALFA*/ + 0x2C81, /*U+2C81*/ /**/ + 0x2C83, /*U+2C82*/ /*COPTIC CAPITAL LETTER VIDA*/ + 0x2C83, /*U+2C83*/ /**/ + 0x2C85, /*U+2C84*/ /*COPTIC CAPITAL LETTER GAMMA*/ + 0x2C85, /*U+2C85*/ /**/ + 0x2C87, /*U+2C86*/ /*COPTIC CAPITAL LETTER DALDA*/ + 0x2C87, /*U+2C87*/ /**/ + 0x2C89, /*U+2C88*/ /*COPTIC CAPITAL LETTER EIE*/ + 0x2C89, /*U+2C89*/ /**/ + 0x2C8B, /*U+2C8A*/ /*COPTIC CAPITAL LETTER SOU*/ + 0x2C8B, /*U+2C8B*/ /**/ + 0x2C8D, /*U+2C8C*/ /*COPTIC CAPITAL LETTER ZATA*/ + 0x2C8D, /*U+2C8D*/ /**/ + 0x2C8F, /*U+2C8E*/ /*COPTIC CAPITAL LETTER HATE*/ + 0x2C8F, /*U+2C8F*/ /**/ + 0x2C91, /*U+2C90*/ /*COPTIC CAPITAL LETTER THETHE*/ + 0x2C91, /*U+2C91*/ /**/ + 0x2C93, /*U+2C92*/ /*COPTIC CAPITAL LETTER IAUDA*/ + 0x2C93, /*U+2C93*/ /**/ + 0x2C95, /*U+2C94*/ /*COPTIC CAPITAL LETTER KAPA*/ + 0x2C95, /*U+2C95*/ /**/ + 0x2C97, /*U+2C96*/ /*COPTIC CAPITAL LETTER LAULA*/ + 0x2C97, /*U+2C97*/ /**/ + 0x2C99, /*U+2C98*/ /*COPTIC CAPITAL LETTER MI*/ + 0x2C99, /*U+2C99*/ /**/ + 0x2C9B, /*U+2C9A*/ /*COPTIC CAPITAL LETTER NI*/ + 0x2C9B, /*U+2C9B*/ /**/ + 0x2C9D, /*U+2C9C*/ /*COPTIC CAPITAL LETTER KSI*/ + 0x2C9D, /*U+2C9D*/ /**/ + 0x2C9F, /*U+2C9E*/ /*COPTIC CAPITAL LETTER O*/ + 0x2C9F, /*U+2C9F*/ /**/ + 0x2CA1, /*U+2CA0*/ /*COPTIC CAPITAL LETTER PI*/ + 0x2CA1, /*U+2CA1*/ /**/ + 0x2CA3, /*U+2CA2*/ /*COPTIC CAPITAL LETTER RO*/ + 0x2CA3, /*U+2CA3*/ /**/ + 0x2CA5, /*U+2CA4*/ /*COPTIC CAPITAL LETTER SIMA*/ + 0x2CA5, /*U+2CA5*/ /**/ + 0x2CA7, /*U+2CA6*/ /*COPTIC CAPITAL LETTER TAU*/ + 0x2CA7, /*U+2CA7*/ /**/ + 0x2CA9, /*U+2CA8*/ /*COPTIC CAPITAL LETTER UA*/ + 0x2CA9, /*U+2CA9*/ /**/ + 0x2CAB, /*U+2CAA*/ /*COPTIC CAPITAL LETTER FI*/ + 0x2CAB, /*U+2CAB*/ /**/ + 0x2CAD, /*U+2CAC*/ /*COPTIC CAPITAL LETTER KHI*/ + 0x2CAD, /*U+2CAD*/ /**/ + 0x2CAF, /*U+2CAE*/ /*COPTIC CAPITAL LETTER PSI*/ + 0x2CAF, /*U+2CAF*/ /**/ + 0x2CB1, /*U+2CB0*/ /*COPTIC CAPITAL LETTER OOU*/ + 0x2CB1, /*U+2CB1*/ /**/ + 0x2CB3, /*U+2CB2*/ /*COPTIC CAPITAL LETTER DIALECT-P ALEF*/ + 0x2CB3, /*U+2CB3*/ /**/ + 0x2CB5, /*U+2CB4*/ /*COPTIC CAPITAL LETTER OLD COPTIC AIN*/ + 0x2CB5, /*U+2CB5*/ /**/ + 0x2CB7, /*U+2CB6*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE*/ + 0x2CB7, /*U+2CB7*/ /**/ + 0x2CB9, /*U+2CB8*/ /*COPTIC CAPITAL LETTER DIALECT-P KAPA*/ + 0x2CB9, /*U+2CB9*/ /**/ + 0x2CBB, /*U+2CBA*/ /*COPTIC CAPITAL LETTER DIALECT-P NI*/ + 0x2CBB, /*U+2CBB*/ /**/ + 0x2CBD, /*U+2CBC*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI*/ + 0x2CBD, /*U+2CBD*/ /**/ + 0x2CBF, /*U+2CBE*/ /*COPTIC CAPITAL LETTER OLD COPTIC OOU*/ + 0x2CBF, /*U+2CBF*/ /**/ + 0x2CC1, /*U+2CC0*/ /*COPTIC CAPITAL LETTER SAMPI*/ + 0x2CC1, /*U+2CC1*/ /**/ + 0x2CC3, /*U+2CC2*/ /*COPTIC CAPITAL LETTER CROSSED SHEI*/ + 0x2CC3, /*U+2CC3*/ /**/ + 0x2CC5, /*U+2CC4*/ /*COPTIC CAPITAL LETTER OLD COPTIC SHEI*/ + 0x2CC5, /*U+2CC5*/ /**/ + 0x2CC7, /*U+2CC6*/ /*COPTIC CAPITAL LETTER OLD COPTIC ESH*/ + 0x2CC7, /*U+2CC7*/ /**/ + 0x2CC9, /*U+2CC8*/ /*COPTIC CAPITAL LETTER AKHMIMIC KHEI*/ + 0x2CC9, /*U+2CC9*/ /**/ + 0x2CCB, /*U+2CCA*/ /*COPTIC CAPITAL LETTER DIALECT-P HORI*/ + 0x2CCB, /*U+2CCB*/ /**/ + 0x2CCD, /*U+2CCC*/ /*COPTIC CAPITAL LETTER OLD COPTIC HORI*/ + 0x2CCD, /*U+2CCD*/ /**/ + 0x2CCF, /*U+2CCE*/ /*COPTIC CAPITAL LETTER OLD COPTIC HA*/ + 0x2CCF, /*U+2CCF*/ /**/ + 0x2CD1, /*U+2CD0*/ /*COPTIC CAPITAL LETTER L-SHAPED HA*/ + 0x2CD1, /*U+2CD1*/ /**/ + 0x2CD3, /*U+2CD2*/ /*COPTIC CAPITAL LETTER OLD COPTIC HEI*/ + 0x2CD3, /*U+2CD3*/ /**/ + 0x2CD5, /*U+2CD4*/ /*COPTIC CAPITAL LETTER OLD COPTIC HAT*/ + 0x2CD5, /*U+2CD5*/ /**/ + 0x2CD7, /*U+2CD6*/ /*COPTIC CAPITAL LETTER OLD COPTIC GANGIA*/ + 0x2CD7, /*U+2CD7*/ /**/ + 0x2CD9, /*U+2CD8*/ /*COPTIC CAPITAL LETTER OLD COPTIC DJA*/ + 0x2CD9, /*U+2CD9*/ /**/ + 0x2CDB, /*U+2CDA*/ /*COPTIC CAPITAL LETTER OLD COPTIC SHIMA*/ + 0x2CDB, /*U+2CDB*/ /**/ + 0x2CDD, /*U+2CDC*/ /*COPTIC CAPITAL LETTER OLD NUBIAN SHIMA*/ + 0x2CDD, /*U+2CDD*/ /**/ + 0x2CDF, /*U+2CDE*/ /*COPTIC CAPITAL LETTER OLD NUBIAN NGI*/ + 0x2CDF, /*U+2CDF*/ /**/ + 0x2CE1, /*U+2CE0*/ /*COPTIC CAPITAL LETTER OLD NUBIAN NYI*/ + 0x2CE1, /*U+2CE1*/ /**/ + 0x2CE3, /*U+2CE2*/ /*COPTIC CAPITAL LETTER OLD NUBIAN WAU*/ + 0x2CE3, /*U+2CE3*/ /**/ + 0x2CE4, /*U+2CE4*/ /**/ + 0x2CE5, /*U+2CE5*/ /**/ + 0x2CE6, /*U+2CE6*/ /**/ + 0x2CE7, /*U+2CE7*/ /**/ + 0x2CE8, /*U+2CE8*/ /**/ + 0x2CE9, /*U+2CE9*/ /**/ + 0x2CEA, /*U+2CEA*/ /**/ + 0x2CEC, /*U+2CEB*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI*/ + 0x2CEC, /*U+2CEC*/ /**/ + 0x2CEE, /*U+2CED*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA*/ + 0x2CEE, /*U+2CEE*/ /**/ + 0x2CEF, /*U+2CEF*/ /**/ + 0x2CF0, /*U+2CF0*/ /**/ + 0x2CF1, /*U+2CF1*/ /**/ + 0x2CF3, /*U+2CF2*/ /*COPTIC CAPITAL LETTER BOHAIRIC KHEI*/ + 0x2CF3, /*U+2CF3*/ /**/ + 0x2CF4, /*U+2CF4*/ /**/ + 0x2CF5, /*U+2CF5*/ /**/ + 0x2CF6, /*U+2CF6*/ /**/ + 0x2CF7, /*U+2CF7*/ /**/ + 0x2CF8, /*U+2CF8*/ /**/ + 0x2CF9, /*U+2CF9*/ /**/ + 0x2CFA, /*U+2CFA*/ /**/ + 0x2CFB, /*U+2CFB*/ /**/ + 0x2CFC, /*U+2CFC*/ /**/ + 0x2CFD, /*U+2CFD*/ /**/ + 0x2CFE, /*U+2CFE*/ /**/ + 0x2CFF, /*U+2CFF*/ /**/ +}; + +static const uint16_t lower_table_9[128] = { + 0xA641, /*U+A640*/ /*CYRILLIC CAPITAL LETTER ZEMLYA*/ + 0xA641, /*U+A641*/ /**/ + 0xA643, /*U+A642*/ /*CYRILLIC CAPITAL LETTER DZELO*/ + 0xA643, /*U+A643*/ /**/ + 0xA645, /*U+A644*/ /*CYRILLIC CAPITAL LETTER REVERSED DZE*/ + 0xA645, /*U+A645*/ /**/ + 0xA647, /*U+A646*/ /*CYRILLIC CAPITAL LETTER IOTA*/ + 0xA647, /*U+A647*/ /**/ + 0xA649, /*U+A648*/ /*CYRILLIC CAPITAL LETTER DJERV*/ + 0xA649, /*U+A649*/ /**/ + 0xA64B, /*U+A64A*/ /*CYRILLIC CAPITAL LETTER MONOGRAPH UK*/ + 0xA64B, /*U+A64B*/ /**/ + 0xA64D, /*U+A64C*/ /*CYRILLIC CAPITAL LETTER BROAD OMEGA*/ + 0xA64D, /*U+A64D*/ /**/ + 0xA64F, /*U+A64E*/ /*CYRILLIC CAPITAL LETTER NEUTRAL YER*/ + 0xA64F, /*U+A64F*/ /**/ + 0xA651, /*U+A650*/ /*CYRILLIC CAPITAL LETTER YERU WITH BACK YER*/ + 0xA651, /*U+A651*/ /**/ + 0xA653, /*U+A652*/ /*CYRILLIC CAPITAL LETTER IOTIFIED YAT*/ + 0xA653, /*U+A653*/ /**/ + 0xA655, /*U+A654*/ /*CYRILLIC CAPITAL LETTER REVERSED YU*/ + 0xA655, /*U+A655*/ /**/ + 0xA657, /*U+A656*/ /*CYRILLIC CAPITAL LETTER IOTIFIED A*/ + 0xA657, /*U+A657*/ /**/ + 0xA659, /*U+A658*/ /*CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS*/ + 0xA659, /*U+A659*/ /**/ + 0xA65B, /*U+A65A*/ /*CYRILLIC CAPITAL LETTER BLENDED YUS*/ + 0xA65B, /*U+A65B*/ /**/ + 0xA65D, /*U+A65C*/ /*CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS*/ + 0xA65D, /*U+A65D*/ /**/ + 0xA65F, /*U+A65E*/ /*CYRILLIC CAPITAL LETTER YN*/ + 0xA65F, /*U+A65F*/ /**/ + 0xA661, /*U+A660*/ /*CYRILLIC CAPITAL LETTER REVERSED TSE*/ + 0xA661, /*U+A661*/ /**/ + 0xA663, /*U+A662*/ /*CYRILLIC CAPITAL LETTER SOFT DE*/ + 0xA663, /*U+A663*/ /**/ + 0xA665, /*U+A664*/ /*CYRILLIC CAPITAL LETTER SOFT EL*/ + 0xA665, /*U+A665*/ /**/ + 0xA667, /*U+A666*/ /*CYRILLIC CAPITAL LETTER SOFT EM*/ + 0xA667, /*U+A667*/ /**/ + 0xA669, /*U+A668*/ /*CYRILLIC CAPITAL LETTER MONOCULAR O*/ + 0xA669, /*U+A669*/ /**/ + 0xA66B, /*U+A66A*/ /*CYRILLIC CAPITAL LETTER BINOCULAR O*/ + 0xA66B, /*U+A66B*/ /**/ + 0xA66D, /*U+A66C*/ /*CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O*/ + 0xA66D, /*U+A66D*/ /**/ + 0xA66E, /*U+A66E*/ /**/ + 0xA66F, /*U+A66F*/ /**/ + 0xA670, /*U+A670*/ /**/ + 0xA671, /*U+A671*/ /**/ + 0xA672, /*U+A672*/ /**/ + 0xA673, /*U+A673*/ /**/ + 0xA674, /*U+A674*/ /**/ + 0xA675, /*U+A675*/ /**/ + 0xA676, /*U+A676*/ /**/ + 0xA677, /*U+A677*/ /**/ + 0xA678, /*U+A678*/ /**/ + 0xA679, /*U+A679*/ /**/ + 0xA67A, /*U+A67A*/ /**/ + 0xA67B, /*U+A67B*/ /**/ + 0xA67C, /*U+A67C*/ /**/ + 0xA67D, /*U+A67D*/ /**/ + 0xA67E, /*U+A67E*/ /**/ + 0xA67F, /*U+A67F*/ /**/ + 0xA681, /*U+A680*/ /*CYRILLIC CAPITAL LETTER DWE*/ + 0xA681, /*U+A681*/ /**/ + 0xA683, /*U+A682*/ /*CYRILLIC CAPITAL LETTER DZWE*/ + 0xA683, /*U+A683*/ /**/ + 0xA685, /*U+A684*/ /*CYRILLIC CAPITAL LETTER ZHWE*/ + 0xA685, /*U+A685*/ /**/ + 0xA687, /*U+A686*/ /*CYRILLIC CAPITAL LETTER CCHE*/ + 0xA687, /*U+A687*/ /**/ + 0xA689, /*U+A688*/ /*CYRILLIC CAPITAL LETTER DZZE*/ + 0xA689, /*U+A689*/ /**/ + 0xA68B, /*U+A68A*/ /*CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK*/ + 0xA68B, /*U+A68B*/ /**/ + 0xA68D, /*U+A68C*/ /*CYRILLIC CAPITAL LETTER TWE*/ + 0xA68D, /*U+A68D*/ /**/ + 0xA68F, /*U+A68E*/ /*CYRILLIC CAPITAL LETTER TSWE*/ + 0xA68F, /*U+A68F*/ /**/ + 0xA691, /*U+A690*/ /*CYRILLIC CAPITAL LETTER TSSE*/ + 0xA691, /*U+A691*/ /**/ + 0xA693, /*U+A692*/ /*CYRILLIC CAPITAL LETTER TCHE*/ + 0xA693, /*U+A693*/ /**/ + 0xA695, /*U+A694*/ /*CYRILLIC CAPITAL LETTER HWE*/ + 0xA695, /*U+A695*/ /**/ + 0xA697, /*U+A696*/ /*CYRILLIC CAPITAL LETTER SHWE*/ + 0xA697, /*U+A697*/ /**/ + 0xA699, /*U+A698*/ /*CYRILLIC CAPITAL LETTER DOUBLE O*/ + 0xA699, /*U+A699*/ /**/ + 0xA69B, /*U+A69A*/ /*CYRILLIC CAPITAL LETTER CROSSED O*/ + 0xA69B, /*U+A69B*/ /**/ + 0xA69C, /*U+A69C*/ /**/ + 0xA69D, /*U+A69D*/ /**/ + 0xA69E, /*U+A69E*/ /**/ + 0xA69F, /*U+A69F*/ /**/ + 0xA6A0, /*U+A6A0*/ /**/ + 0xA6A1, /*U+A6A1*/ /**/ + 0xA6A2, /*U+A6A2*/ /**/ + 0xA6A3, /*U+A6A3*/ /**/ + 0xA6A4, /*U+A6A4*/ /**/ + 0xA6A5, /*U+A6A5*/ /**/ + 0xA6A6, /*U+A6A6*/ /**/ + 0xA6A7, /*U+A6A7*/ /**/ + 0xA6A8, /*U+A6A8*/ /**/ + 0xA6A9, /*U+A6A9*/ /**/ + 0xA6AA, /*U+A6AA*/ /**/ + 0xA6AB, /*U+A6AB*/ /**/ + 0xA6AC, /*U+A6AC*/ /**/ + 0xA6AD, /*U+A6AD*/ /**/ + 0xA6AE, /*U+A6AE*/ /**/ + 0xA6AF, /*U+A6AF*/ /**/ + 0xA6B0, /*U+A6B0*/ /**/ + 0xA6B1, /*U+A6B1*/ /**/ + 0xA6B2, /*U+A6B2*/ /**/ + 0xA6B3, /*U+A6B3*/ /**/ + 0xA6B4, /*U+A6B4*/ /**/ + 0xA6B5, /*U+A6B5*/ /**/ + 0xA6B6, /*U+A6B6*/ /**/ + 0xA6B7, /*U+A6B7*/ /**/ + 0xA6B8, /*U+A6B8*/ /**/ + 0xA6B9, /*U+A6B9*/ /**/ + 0xA6BA, /*U+A6BA*/ /**/ + 0xA6BB, /*U+A6BB*/ /**/ + 0xA6BC, /*U+A6BC*/ /**/ + 0xA6BD, /*U+A6BD*/ /**/ + 0xA6BE, /*U+A6BE*/ /**/ + 0xA6BF, /*U+A6BF*/ /**/ +}; + +static const uint16_t lower_table_10[192] = { + 0xA700, /*U+A700*/ /**/ + 0xA701, /*U+A701*/ /**/ + 0xA702, /*U+A702*/ /**/ + 0xA703, /*U+A703*/ /**/ + 0xA704, /*U+A704*/ /**/ + 0xA705, /*U+A705*/ /**/ + 0xA706, /*U+A706*/ /**/ + 0xA707, /*U+A707*/ /**/ + 0xA708, /*U+A708*/ /**/ + 0xA709, /*U+A709*/ /**/ + 0xA70A, /*U+A70A*/ /**/ + 0xA70B, /*U+A70B*/ /**/ + 0xA70C, /*U+A70C*/ /**/ + 0xA70D, /*U+A70D*/ /**/ + 0xA70E, /*U+A70E*/ /**/ + 0xA70F, /*U+A70F*/ /**/ + 0xA710, /*U+A710*/ /**/ + 0xA711, /*U+A711*/ /**/ + 0xA712, /*U+A712*/ /**/ + 0xA713, /*U+A713*/ /**/ + 0xA714, /*U+A714*/ /**/ + 0xA715, /*U+A715*/ /**/ + 0xA716, /*U+A716*/ /**/ + 0xA717, /*U+A717*/ /**/ + 0xA718, /*U+A718*/ /**/ + 0xA719, /*U+A719*/ /**/ + 0xA71A, /*U+A71A*/ /**/ + 0xA71B, /*U+A71B*/ /**/ + 0xA71C, /*U+A71C*/ /**/ + 0xA71D, /*U+A71D*/ /**/ + 0xA71E, /*U+A71E*/ /**/ + 0xA71F, /*U+A71F*/ /**/ + 0xA720, /*U+A720*/ /**/ + 0xA721, /*U+A721*/ /**/ + 0xA723, /*U+A722*/ /*LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF*/ + 0xA723, /*U+A723*/ /**/ + 0xA725, /*U+A724*/ /*LATIN CAPITAL LETTER EGYPTOLOGICAL AIN*/ + 0xA725, /*U+A725*/ /**/ + 0xA727, /*U+A726*/ /*LATIN CAPITAL LETTER HENG*/ + 0xA727, /*U+A727*/ /**/ + 0xA729, /*U+A728*/ /*LATIN CAPITAL LETTER TZ*/ + 0xA729, /*U+A729*/ /**/ + 0xA72B, /*U+A72A*/ /*LATIN CAPITAL LETTER TRESILLO*/ + 0xA72B, /*U+A72B*/ /**/ + 0xA72D, /*U+A72C*/ /*LATIN CAPITAL LETTER CUATRILLO*/ + 0xA72D, /*U+A72D*/ /**/ + 0xA72F, /*U+A72E*/ /*LATIN CAPITAL LETTER CUATRILLO WITH COMMA*/ + 0xA72F, /*U+A72F*/ /**/ + 0xA730, /*U+A730*/ /**/ + 0xA731, /*U+A731*/ /**/ + 0xA733, /*U+A732*/ /*LATIN CAPITAL LETTER AA*/ + 0xA733, /*U+A733*/ /**/ + 0xA735, /*U+A734*/ /*LATIN CAPITAL LETTER AO*/ + 0xA735, /*U+A735*/ /**/ + 0xA737, /*U+A736*/ /*LATIN CAPITAL LETTER AU*/ + 0xA737, /*U+A737*/ /**/ + 0xA739, /*U+A738*/ /*LATIN CAPITAL LETTER AV*/ + 0xA739, /*U+A739*/ /**/ + 0xA73B, /*U+A73A*/ /*LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR*/ + 0xA73B, /*U+A73B*/ /**/ + 0xA73D, /*U+A73C*/ /*LATIN CAPITAL LETTER AY*/ + 0xA73D, /*U+A73D*/ /**/ + 0xA73F, /*U+A73E*/ /*LATIN CAPITAL LETTER REVERSED C WITH DOT*/ + 0xA73F, /*U+A73F*/ /**/ + 0xA741, /*U+A740*/ /*LATIN CAPITAL LETTER K WITH STROKE*/ + 0xA741, /*U+A741*/ /**/ + 0xA743, /*U+A742*/ /*LATIN CAPITAL LETTER K WITH DIAGONAL STROKE*/ + 0xA743, /*U+A743*/ /**/ + 0xA745, /*U+A744*/ /*LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE*/ + 0xA745, /*U+A745*/ /**/ + 0xA747, /*U+A746*/ /*LATIN CAPITAL LETTER BROKEN L*/ + 0xA747, /*U+A747*/ /**/ + 0xA749, /*U+A748*/ /*LATIN CAPITAL LETTER L WITH HIGH STROKE*/ + 0xA749, /*U+A749*/ /**/ + 0xA74B, /*U+A74A*/ /*LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY*/ + 0xA74B, /*U+A74B*/ /**/ + 0xA74D, /*U+A74C*/ /*LATIN CAPITAL LETTER O WITH LOOP*/ + 0xA74D, /*U+A74D*/ /**/ + 0xA74F, /*U+A74E*/ /*LATIN CAPITAL LETTER OO*/ + 0xA74F, /*U+A74F*/ /**/ + 0xA751, /*U+A750*/ /*LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER*/ + 0xA751, /*U+A751*/ /**/ + 0xA753, /*U+A752*/ /*LATIN CAPITAL LETTER P WITH FLOURISH*/ + 0xA753, /*U+A753*/ /**/ + 0xA755, /*U+A754*/ /*LATIN CAPITAL LETTER P WITH SQUIRREL TAIL*/ + 0xA755, /*U+A755*/ /**/ + 0xA757, /*U+A756*/ /*LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER*/ + 0xA757, /*U+A757*/ /**/ + 0xA759, /*U+A758*/ /*LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE*/ + 0xA759, /*U+A759*/ /**/ + 0xA75B, /*U+A75A*/ /*LATIN CAPITAL LETTER R ROTUNDA*/ + 0xA75B, /*U+A75B*/ /**/ + 0xA75D, /*U+A75C*/ /*LATIN CAPITAL LETTER RUM ROTUNDA*/ + 0xA75D, /*U+A75D*/ /**/ + 0xA75F, /*U+A75E*/ /*LATIN CAPITAL LETTER V WITH DIAGONAL STROKE*/ + 0xA75F, /*U+A75F*/ /**/ + 0xA761, /*U+A760*/ /*LATIN CAPITAL LETTER VY*/ + 0xA761, /*U+A761*/ /**/ + 0xA763, /*U+A762*/ /*LATIN CAPITAL LETTER VISIGOTHIC Z*/ + 0xA763, /*U+A763*/ /**/ + 0xA765, /*U+A764*/ /*LATIN CAPITAL LETTER THORN WITH STROKE*/ + 0xA765, /*U+A765*/ /**/ + 0xA767, /*U+A766*/ /*LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER*/ + 0xA767, /*U+A767*/ /**/ + 0xA769, /*U+A768*/ /*LATIN CAPITAL LETTER VEND*/ + 0xA769, /*U+A769*/ /**/ + 0xA76B, /*U+A76A*/ /*LATIN CAPITAL LETTER ET*/ + 0xA76B, /*U+A76B*/ /**/ + 0xA76D, /*U+A76C*/ /*LATIN CAPITAL LETTER IS*/ + 0xA76D, /*U+A76D*/ /**/ + 0xA76F, /*U+A76E*/ /*LATIN CAPITAL LETTER CON*/ + 0xA76F, /*U+A76F*/ /**/ + 0xA770, /*U+A770*/ /**/ + 0xA771, /*U+A771*/ /**/ + 0xA772, /*U+A772*/ /**/ + 0xA773, /*U+A773*/ /**/ + 0xA774, /*U+A774*/ /**/ + 0xA775, /*U+A775*/ /**/ + 0xA776, /*U+A776*/ /**/ + 0xA777, /*U+A777*/ /**/ + 0xA778, /*U+A778*/ /**/ + 0xA77A, /*U+A779*/ /*LATIN CAPITAL LETTER INSULAR D*/ + 0xA77A, /*U+A77A*/ /**/ + 0xA77C, /*U+A77B*/ /*LATIN CAPITAL LETTER INSULAR F*/ + 0xA77C, /*U+A77C*/ /**/ + 0x1D79, /*U+A77D*/ /*LATIN CAPITAL LETTER INSULAR G*/ + 0xA77F, /*U+A77E*/ /*LATIN CAPITAL LETTER TURNED INSULAR G*/ + 0xA77F, /*U+A77F*/ /**/ + 0xA781, /*U+A780*/ /*LATIN CAPITAL LETTER TURNED L*/ + 0xA781, /*U+A781*/ /**/ + 0xA783, /*U+A782*/ /*LATIN CAPITAL LETTER INSULAR R*/ + 0xA783, /*U+A783*/ /**/ + 0xA785, /*U+A784*/ /*LATIN CAPITAL LETTER INSULAR S*/ + 0xA785, /*U+A785*/ /**/ + 0xA787, /*U+A786*/ /*LATIN CAPITAL LETTER INSULAR T*/ + 0xA787, /*U+A787*/ /**/ + 0xA788, /*U+A788*/ /**/ + 0xA789, /*U+A789*/ /**/ + 0xA78A, /*U+A78A*/ /**/ + 0xA78C, /*U+A78B*/ /*LATIN CAPITAL LETTER SALTILLO*/ + 0xA78C, /*U+A78C*/ /**/ + 0x0265, /*U+A78D*/ /*LATIN CAPITAL LETTER TURNED H*/ + 0xA78E, /*U+A78E*/ /**/ + 0xA78F, /*U+A78F*/ /**/ + 0xA791, /*U+A790*/ /*LATIN CAPITAL LETTER N WITH DESCENDER*/ + 0xA791, /*U+A791*/ /**/ + 0xA793, /*U+A792*/ /*LATIN CAPITAL LETTER C WITH BAR*/ + 0xA793, /*U+A793*/ /**/ + 0xA794, /*U+A794*/ /**/ + 0xA795, /*U+A795*/ /**/ + 0xA797, /*U+A796*/ /*LATIN CAPITAL LETTER B WITH FLOURISH*/ + 0xA797, /*U+A797*/ /**/ + 0xA799, /*U+A798*/ /*LATIN CAPITAL LETTER F WITH STROKE*/ + 0xA799, /*U+A799*/ /**/ + 0xA79B, /*U+A79A*/ /*LATIN CAPITAL LETTER VOLAPUK AE*/ + 0xA79B, /*U+A79B*/ /**/ + 0xA79D, /*U+A79C*/ /*LATIN CAPITAL LETTER VOLAPUK OE*/ + 0xA79D, /*U+A79D*/ /**/ + 0xA79F, /*U+A79E*/ /*LATIN CAPITAL LETTER VOLAPUK UE*/ + 0xA79F, /*U+A79F*/ /**/ + 0xA7A1, /*U+A7A0*/ /*LATIN CAPITAL LETTER G WITH OBLIQUE STROKE*/ + 0xA7A1, /*U+A7A1*/ /**/ + 0xA7A3, /*U+A7A2*/ /*LATIN CAPITAL LETTER K WITH OBLIQUE STROKE*/ + 0xA7A3, /*U+A7A3*/ /**/ + 0xA7A5, /*U+A7A4*/ /*LATIN CAPITAL LETTER N WITH OBLIQUE STROKE*/ + 0xA7A5, /*U+A7A5*/ /**/ + 0xA7A7, /*U+A7A6*/ /*LATIN CAPITAL LETTER R WITH OBLIQUE STROKE*/ + 0xA7A7, /*U+A7A7*/ /**/ + 0xA7A9, /*U+A7A8*/ /*LATIN CAPITAL LETTER S WITH OBLIQUE STROKE*/ + 0xA7A9, /*U+A7A9*/ /**/ + 0x0266, /*U+A7AA*/ /*LATIN CAPITAL LETTER H WITH HOOK*/ + 0x025C, /*U+A7AB*/ /*LATIN CAPITAL LETTER REVERSED OPEN E*/ + 0x0261, /*U+A7AC*/ /*LATIN CAPITAL LETTER SCRIPT G*/ + 0x026C, /*U+A7AD*/ /*LATIN CAPITAL LETTER L WITH BELT*/ + 0xA7AE, /*U+A7AE*/ /**/ + 0xA7AF, /*U+A7AF*/ /**/ + 0x029E, /*U+A7B0*/ /*LATIN CAPITAL LETTER TURNED K*/ + 0x0287, /*U+A7B1*/ /*LATIN CAPITAL LETTER TURNED T*/ + 0xA7B2, /*U+A7B2*/ /**/ + 0xA7B3, /*U+A7B3*/ /**/ + 0xA7B4, /*U+A7B4*/ /**/ + 0xA7B5, /*U+A7B5*/ /**/ + 0xA7B6, /*U+A7B6*/ /**/ + 0xA7B7, /*U+A7B7*/ /**/ + 0xA7B8, /*U+A7B8*/ /**/ + 0xA7B9, /*U+A7B9*/ /**/ + 0xA7BA, /*U+A7BA*/ /**/ + 0xA7BB, /*U+A7BB*/ /**/ + 0xA7BC, /*U+A7BC*/ /**/ + 0xA7BD, /*U+A7BD*/ /**/ + 0xA7BE, /*U+A7BE*/ /**/ + 0xA7BF, /*U+A7BF*/ /**/ +}; + +static const uint16_t lower_table_11[64] = { + 0xFF00, /*U+FF00*/ /**/ + 0xFF01, /*U+FF01*/ /**/ + 0xFF02, /*U+FF02*/ /**/ + 0xFF03, /*U+FF03*/ /**/ + 0xFF04, /*U+FF04*/ /**/ + 0xFF05, /*U+FF05*/ /**/ + 0xFF06, /*U+FF06*/ /**/ + 0xFF07, /*U+FF07*/ /**/ + 0xFF08, /*U+FF08*/ /**/ + 0xFF09, /*U+FF09*/ /**/ + 0xFF0A, /*U+FF0A*/ /**/ + 0xFF0B, /*U+FF0B*/ /**/ + 0xFF0C, /*U+FF0C*/ /**/ + 0xFF0D, /*U+FF0D*/ /**/ + 0xFF0E, /*U+FF0E*/ /**/ + 0xFF0F, /*U+FF0F*/ /**/ + 0xFF10, /*U+FF10*/ /**/ + 0xFF11, /*U+FF11*/ /**/ + 0xFF12, /*U+FF12*/ /**/ + 0xFF13, /*U+FF13*/ /**/ + 0xFF14, /*U+FF14*/ /**/ + 0xFF15, /*U+FF15*/ /**/ + 0xFF16, /*U+FF16*/ /**/ + 0xFF17, /*U+FF17*/ /**/ + 0xFF18, /*U+FF18*/ /**/ + 0xFF19, /*U+FF19*/ /**/ + 0xFF1A, /*U+FF1A*/ /**/ + 0xFF1B, /*U+FF1B*/ /**/ + 0xFF1C, /*U+FF1C*/ /**/ + 0xFF1D, /*U+FF1D*/ /**/ + 0xFF1E, /*U+FF1E*/ /**/ + 0xFF1F, /*U+FF1F*/ /**/ + 0xFF20, /*U+FF20*/ /**/ + 0xFF41, /*U+FF21*/ /*FULLWIDTH LATIN CAPITAL LETTER A*/ + 0xFF42, /*U+FF22*/ /*FULLWIDTH LATIN CAPITAL LETTER B*/ + 0xFF43, /*U+FF23*/ /*FULLWIDTH LATIN CAPITAL LETTER C*/ + 0xFF44, /*U+FF24*/ /*FULLWIDTH LATIN CAPITAL LETTER D*/ + 0xFF45, /*U+FF25*/ /*FULLWIDTH LATIN CAPITAL LETTER E*/ + 0xFF46, /*U+FF26*/ /*FULLWIDTH LATIN CAPITAL LETTER F*/ + 0xFF47, /*U+FF27*/ /*FULLWIDTH LATIN CAPITAL LETTER G*/ + 0xFF48, /*U+FF28*/ /*FULLWIDTH LATIN CAPITAL LETTER H*/ + 0xFF49, /*U+FF29*/ /*FULLWIDTH LATIN CAPITAL LETTER I*/ + 0xFF4A, /*U+FF2A*/ /*FULLWIDTH LATIN CAPITAL LETTER J*/ + 0xFF4B, /*U+FF2B*/ /*FULLWIDTH LATIN CAPITAL LETTER K*/ + 0xFF4C, /*U+FF2C*/ /*FULLWIDTH LATIN CAPITAL LETTER L*/ + 0xFF4D, /*U+FF2D*/ /*FULLWIDTH LATIN CAPITAL LETTER M*/ + 0xFF4E, /*U+FF2E*/ /*FULLWIDTH LATIN CAPITAL LETTER N*/ + 0xFF4F, /*U+FF2F*/ /*FULLWIDTH LATIN CAPITAL LETTER O*/ + 0xFF50, /*U+FF30*/ /*FULLWIDTH LATIN CAPITAL LETTER P*/ + 0xFF51, /*U+FF31*/ /*FULLWIDTH LATIN CAPITAL LETTER Q*/ + 0xFF52, /*U+FF32*/ /*FULLWIDTH LATIN CAPITAL LETTER R*/ + 0xFF53, /*U+FF33*/ /*FULLWIDTH LATIN CAPITAL LETTER S*/ + 0xFF54, /*U+FF34*/ /*FULLWIDTH LATIN CAPITAL LETTER T*/ + 0xFF55, /*U+FF35*/ /*FULLWIDTH LATIN CAPITAL LETTER U*/ + 0xFF56, /*U+FF36*/ /*FULLWIDTH LATIN CAPITAL LETTER V*/ + 0xFF57, /*U+FF37*/ /*FULLWIDTH LATIN CAPITAL LETTER W*/ + 0xFF58, /*U+FF38*/ /*FULLWIDTH LATIN CAPITAL LETTER X*/ + 0xFF59, /*U+FF39*/ /*FULLWIDTH LATIN CAPITAL LETTER Y*/ + 0xFF5A, /*U+FF3A*/ /*FULLWIDTH LATIN CAPITAL LETTER Z*/ + 0xFF3B, /*U+FF3B*/ /**/ + 0xFF3C, /*U+FF3C*/ /**/ + 0xFF3D, /*U+FF3D*/ /**/ + 0xFF3E, /*U+FF3E*/ /**/ + 0xFF3F, /*U+FF3F*/ /**/ +}; + +static const uint32_t lower_table_sp_1[64] = { + 0xD801DC28, /*0xD801DC00*/ /*U+010428*/ /*U+010400*/ /*DESERET CAPITAL LETTER LONG I*/ + 0xD801DC29, /*0xD801DC01*/ /*U+010429*/ /*U+010401*/ /*DESERET CAPITAL LETTER LONG E*/ + 0xD801DC2A, /*0xD801DC02*/ /*U+01042A*/ /*U+010402*/ /*DESERET CAPITAL LETTER LONG A*/ + 0xD801DC2B, /*0xD801DC03*/ /*U+01042B*/ /*U+010403*/ /*DESERET CAPITAL LETTER LONG AH*/ + 0xD801DC2C, /*0xD801DC04*/ /*U+01042C*/ /*U+010404*/ /*DESERET CAPITAL LETTER LONG O*/ + 0xD801DC2D, /*0xD801DC05*/ /*U+01042D*/ /*U+010405*/ /*DESERET CAPITAL LETTER LONG OO*/ + 0xD801DC2E, /*0xD801DC06*/ /*U+01042E*/ /*U+010406*/ /*DESERET CAPITAL LETTER SHORT I*/ + 0xD801DC2F, /*0xD801DC07*/ /*U+01042F*/ /*U+010407*/ /*DESERET CAPITAL LETTER SHORT E*/ + 0xD801DC30, /*0xD801DC08*/ /*U+010430*/ /*U+010408*/ /*DESERET CAPITAL LETTER SHORT A*/ + 0xD801DC31, /*0xD801DC09*/ /*U+010431*/ /*U+010409*/ /*DESERET CAPITAL LETTER SHORT AH*/ + 0xD801DC32, /*0xD801DC0A*/ /*U+010432*/ /*U+01040A*/ /*DESERET CAPITAL LETTER SHORT O*/ + 0xD801DC33, /*0xD801DC0B*/ /*U+010433*/ /*U+01040B*/ /*DESERET CAPITAL LETTER SHORT OO*/ + 0xD801DC34, /*0xD801DC0C*/ /*U+010434*/ /*U+01040C*/ /*DESERET CAPITAL LETTER AY*/ + 0xD801DC35, /*0xD801DC0D*/ /*U+010435*/ /*U+01040D*/ /*DESERET CAPITAL LETTER OW*/ + 0xD801DC36, /*0xD801DC0E*/ /*U+010436*/ /*U+01040E*/ /*DESERET CAPITAL LETTER WU*/ + 0xD801DC37, /*0xD801DC0F*/ /*U+010437*/ /*U+01040F*/ /*DESERET CAPITAL LETTER YEE*/ + 0xD801DC38, /*0xD801DC10*/ /*U+010438*/ /*U+010410*/ /*DESERET CAPITAL LETTER H*/ + 0xD801DC39, /*0xD801DC11*/ /*U+010439*/ /*U+010411*/ /*DESERET CAPITAL LETTER PEE*/ + 0xD801DC3A, /*0xD801DC12*/ /*U+01043A*/ /*U+010412*/ /*DESERET CAPITAL LETTER BEE*/ + 0xD801DC3B, /*0xD801DC13*/ /*U+01043B*/ /*U+010413*/ /*DESERET CAPITAL LETTER TEE*/ + 0xD801DC3C, /*0xD801DC14*/ /*U+01043C*/ /*U+010414*/ /*DESERET CAPITAL LETTER DEE*/ + 0xD801DC3D, /*0xD801DC15*/ /*U+01043D*/ /*U+010415*/ /*DESERET CAPITAL LETTER CHEE*/ + 0xD801DC3E, /*0xD801DC16*/ /*U+01043E*/ /*U+010416*/ /*DESERET CAPITAL LETTER JEE*/ + 0xD801DC3F, /*0xD801DC17*/ /*U+01043F*/ /*U+010417*/ /*DESERET CAPITAL LETTER KAY*/ + 0xD801DC40, /*0xD801DC18*/ /*U+010440*/ /*U+010418*/ /*DESERET CAPITAL LETTER GAY*/ + 0xD801DC41, /*0xD801DC19*/ /*U+010441*/ /*U+010419*/ /*DESERET CAPITAL LETTER EF*/ + 0xD801DC42, /*0xD801DC1A*/ /*U+010442*/ /*U+01041A*/ /*DESERET CAPITAL LETTER VEE*/ + 0xD801DC43, /*0xD801DC1B*/ /*U+010443*/ /*U+01041B*/ /*DESERET CAPITAL LETTER ETH*/ + 0xD801DC44, /*0xD801DC1C*/ /*U+010444*/ /*U+01041C*/ /*DESERET CAPITAL LETTER THEE*/ + 0xD801DC45, /*0xD801DC1D*/ /*U+010445*/ /*U+01041D*/ /*DESERET CAPITAL LETTER ES*/ + 0xD801DC46, /*0xD801DC1E*/ /*U+010446*/ /*U+01041E*/ /*DESERET CAPITAL LETTER ZEE*/ + 0xD801DC47, /*0xD801DC1F*/ /*U+010447*/ /*U+01041F*/ /*DESERET CAPITAL LETTER ESH*/ + 0xD801DC48, /*0xD801DC20*/ /*U+010448*/ /*U+010420*/ /*DESERET CAPITAL LETTER ZHEE*/ + 0xD801DC49, /*0xD801DC21*/ /*U+010449*/ /*U+010421*/ /*DESERET CAPITAL LETTER ER*/ + 0xD801DC4A, /*0xD801DC22*/ /*U+01044A*/ /*U+010422*/ /*DESERET CAPITAL LETTER EL*/ + 0xD801DC4B, /*0xD801DC23*/ /*U+01044B*/ /*U+010423*/ /*DESERET CAPITAL LETTER EM*/ + 0xD801DC4C, /*0xD801DC24*/ /*U+01044C*/ /*U+010424*/ /*DESERET CAPITAL LETTER EN*/ + 0xD801DC4D, /*0xD801DC25*/ /*U+01044D*/ /*U+010425*/ /*DESERET CAPITAL LETTER ENG*/ + 0xD801DC4E, /*0xD801DC26*/ /*U+01044E*/ /*U+010426*/ /*DESERET CAPITAL LETTER OI*/ + 0xD801DC4F, /*0xD801DC27*/ /*U+01044F*/ /*U+010427*/ /*DESERET CAPITAL LETTER EW*/ + 0xD801DC28, /*0xD801DC28*/ /*U+010428*/ /*U+010428*/ /**/ + 0xD801DC29, /*0xD801DC29*/ /*U+010429*/ /*U+010429*/ /**/ + 0xD801DC2A, /*0xD801DC2A*/ /*U+01042A*/ /*U+01042A*/ /**/ + 0xD801DC2B, /*0xD801DC2B*/ /*U+01042B*/ /*U+01042B*/ /**/ + 0xD801DC2C, /*0xD801DC2C*/ /*U+01042C*/ /*U+01042C*/ /**/ + 0xD801DC2D, /*0xD801DC2D*/ /*U+01042D*/ /*U+01042D*/ /**/ + 0xD801DC2E, /*0xD801DC2E*/ /*U+01042E*/ /*U+01042E*/ /**/ + 0xD801DC2F, /*0xD801DC2F*/ /*U+01042F*/ /*U+01042F*/ /**/ + 0xD801DC30, /*0xD801DC30*/ /*U+010430*/ /*U+010430*/ /**/ + 0xD801DC31, /*0xD801DC31*/ /*U+010431*/ /*U+010431*/ /**/ + 0xD801DC32, /*0xD801DC32*/ /*U+010432*/ /*U+010432*/ /**/ + 0xD801DC33, /*0xD801DC33*/ /*U+010433*/ /*U+010433*/ /**/ + 0xD801DC34, /*0xD801DC34*/ /*U+010434*/ /*U+010434*/ /**/ + 0xD801DC35, /*0xD801DC35*/ /*U+010435*/ /*U+010435*/ /**/ + 0xD801DC36, /*0xD801DC36*/ /*U+010436*/ /*U+010436*/ /**/ + 0xD801DC37, /*0xD801DC37*/ /*U+010437*/ /*U+010437*/ /**/ + 0xD801DC38, /*0xD801DC38*/ /*U+010438*/ /*U+010438*/ /**/ + 0xD801DC39, /*0xD801DC39*/ /*U+010439*/ /*U+010439*/ /**/ + 0xD801DC3A, /*0xD801DC3A*/ /*U+01043A*/ /*U+01043A*/ /**/ + 0xD801DC3B, /*0xD801DC3B*/ /*U+01043B*/ /*U+01043B*/ /**/ + 0xD801DC3C, /*0xD801DC3C*/ /*U+01043C*/ /*U+01043C*/ /**/ + 0xD801DC3D, /*0xD801DC3D*/ /*U+01043D*/ /*U+01043D*/ /**/ + 0xD801DC3E, /*0xD801DC3E*/ /*U+01043E*/ /*U+01043E*/ /**/ + 0xD801DC3F, /*0xD801DC3F*/ /*U+01043F*/ /*U+01043F*/ /**/ +}; + +static const uint32_t lower_table_sp_2[64] = { + 0xD806DC80, /*0xD806DC80*/ /*U+011880*/ /*U+011880*/ /**/ + 0xD806DC81, /*0xD806DC81*/ /*U+011881*/ /*U+011881*/ /**/ + 0xD806DC82, /*0xD806DC82*/ /*U+011882*/ /*U+011882*/ /**/ + 0xD806DC83, /*0xD806DC83*/ /*U+011883*/ /*U+011883*/ /**/ + 0xD806DC84, /*0xD806DC84*/ /*U+011884*/ /*U+011884*/ /**/ + 0xD806DC85, /*0xD806DC85*/ /*U+011885*/ /*U+011885*/ /**/ + 0xD806DC86, /*0xD806DC86*/ /*U+011886*/ /*U+011886*/ /**/ + 0xD806DC87, /*0xD806DC87*/ /*U+011887*/ /*U+011887*/ /**/ + 0xD806DC88, /*0xD806DC88*/ /*U+011888*/ /*U+011888*/ /**/ + 0xD806DC89, /*0xD806DC89*/ /*U+011889*/ /*U+011889*/ /**/ + 0xD806DC8A, /*0xD806DC8A*/ /*U+01188A*/ /*U+01188A*/ /**/ + 0xD806DC8B, /*0xD806DC8B*/ /*U+01188B*/ /*U+01188B*/ /**/ + 0xD806DC8C, /*0xD806DC8C*/ /*U+01188C*/ /*U+01188C*/ /**/ + 0xD806DC8D, /*0xD806DC8D*/ /*U+01188D*/ /*U+01188D*/ /**/ + 0xD806DC8E, /*0xD806DC8E*/ /*U+01188E*/ /*U+01188E*/ /**/ + 0xD806DC8F, /*0xD806DC8F*/ /*U+01188F*/ /*U+01188F*/ /**/ + 0xD806DC90, /*0xD806DC90*/ /*U+011890*/ /*U+011890*/ /**/ + 0xD806DC91, /*0xD806DC91*/ /*U+011891*/ /*U+011891*/ /**/ + 0xD806DC92, /*0xD806DC92*/ /*U+011892*/ /*U+011892*/ /**/ + 0xD806DC93, /*0xD806DC93*/ /*U+011893*/ /*U+011893*/ /**/ + 0xD806DC94, /*0xD806DC94*/ /*U+011894*/ /*U+011894*/ /**/ + 0xD806DC95, /*0xD806DC95*/ /*U+011895*/ /*U+011895*/ /**/ + 0xD806DC96, /*0xD806DC96*/ /*U+011896*/ /*U+011896*/ /**/ + 0xD806DC97, /*0xD806DC97*/ /*U+011897*/ /*U+011897*/ /**/ + 0xD806DC98, /*0xD806DC98*/ /*U+011898*/ /*U+011898*/ /**/ + 0xD806DC99, /*0xD806DC99*/ /*U+011899*/ /*U+011899*/ /**/ + 0xD806DC9A, /*0xD806DC9A*/ /*U+01189A*/ /*U+01189A*/ /**/ + 0xD806DC9B, /*0xD806DC9B*/ /*U+01189B*/ /*U+01189B*/ /**/ + 0xD806DC9C, /*0xD806DC9C*/ /*U+01189C*/ /*U+01189C*/ /**/ + 0xD806DC9D, /*0xD806DC9D*/ /*U+01189D*/ /*U+01189D*/ /**/ + 0xD806DC9E, /*0xD806DC9E*/ /*U+01189E*/ /*U+01189E*/ /**/ + 0xD806DC9F, /*0xD806DC9F*/ /*U+01189F*/ /*U+01189F*/ /**/ + 0xD806DCC0, /*0xD806DCA0*/ /*U+0118C0*/ /*U+0118A0*/ /*WARANG CITI CAPITAL LETTER NGAA*/ + 0xD806DCC1, /*0xD806DCA1*/ /*U+0118C1*/ /*U+0118A1*/ /*WARANG CITI CAPITAL LETTER A*/ + 0xD806DCC2, /*0xD806DCA2*/ /*U+0118C2*/ /*U+0118A2*/ /*WARANG CITI CAPITAL LETTER WI*/ + 0xD806DCC3, /*0xD806DCA3*/ /*U+0118C3*/ /*U+0118A3*/ /*WARANG CITI CAPITAL LETTER YU*/ + 0xD806DCC4, /*0xD806DCA4*/ /*U+0118C4*/ /*U+0118A4*/ /*WARANG CITI CAPITAL LETTER YA*/ + 0xD806DCC5, /*0xD806DCA5*/ /*U+0118C5*/ /*U+0118A5*/ /*WARANG CITI CAPITAL LETTER YO*/ + 0xD806DCC6, /*0xD806DCA6*/ /*U+0118C6*/ /*U+0118A6*/ /*WARANG CITI CAPITAL LETTER II*/ + 0xD806DCC7, /*0xD806DCA7*/ /*U+0118C7*/ /*U+0118A7*/ /*WARANG CITI CAPITAL LETTER UU*/ + 0xD806DCC8, /*0xD806DCA8*/ /*U+0118C8*/ /*U+0118A8*/ /*WARANG CITI CAPITAL LETTER E*/ + 0xD806DCC9, /*0xD806DCA9*/ /*U+0118C9*/ /*U+0118A9*/ /*WARANG CITI CAPITAL LETTER O*/ + 0xD806DCCA, /*0xD806DCAA*/ /*U+0118CA*/ /*U+0118AA*/ /*WARANG CITI CAPITAL LETTER ANG*/ + 0xD806DCCB, /*0xD806DCAB*/ /*U+0118CB*/ /*U+0118AB*/ /*WARANG CITI CAPITAL LETTER GA*/ + 0xD806DCCC, /*0xD806DCAC*/ /*U+0118CC*/ /*U+0118AC*/ /*WARANG CITI CAPITAL LETTER KO*/ + 0xD806DCCD, /*0xD806DCAD*/ /*U+0118CD*/ /*U+0118AD*/ /*WARANG CITI CAPITAL LETTER ENY*/ + 0xD806DCCE, /*0xD806DCAE*/ /*U+0118CE*/ /*U+0118AE*/ /*WARANG CITI CAPITAL LETTER YUJ*/ + 0xD806DCCF, /*0xD806DCAF*/ /*U+0118CF*/ /*U+0118AF*/ /*WARANG CITI CAPITAL LETTER UC*/ + 0xD806DCD0, /*0xD806DCB0*/ /*U+0118D0*/ /*U+0118B0*/ /*WARANG CITI CAPITAL LETTER ENN*/ + 0xD806DCD1, /*0xD806DCB1*/ /*U+0118D1*/ /*U+0118B1*/ /*WARANG CITI CAPITAL LETTER ODD*/ + 0xD806DCD2, /*0xD806DCB2*/ /*U+0118D2*/ /*U+0118B2*/ /*WARANG CITI CAPITAL LETTER TTE*/ + 0xD806DCD3, /*0xD806DCB3*/ /*U+0118D3*/ /*U+0118B3*/ /*WARANG CITI CAPITAL LETTER NUNG*/ + 0xD806DCD4, /*0xD806DCB4*/ /*U+0118D4*/ /*U+0118B4*/ /*WARANG CITI CAPITAL LETTER DA*/ + 0xD806DCD5, /*0xD806DCB5*/ /*U+0118D5*/ /*U+0118B5*/ /*WARANG CITI CAPITAL LETTER AT*/ + 0xD806DCD6, /*0xD806DCB6*/ /*U+0118D6*/ /*U+0118B6*/ /*WARANG CITI CAPITAL LETTER AM*/ + 0xD806DCD7, /*0xD806DCB7*/ /*U+0118D7*/ /*U+0118B7*/ /*WARANG CITI CAPITAL LETTER BU*/ + 0xD806DCD8, /*0xD806DCB8*/ /*U+0118D8*/ /*U+0118B8*/ /*WARANG CITI CAPITAL LETTER PU*/ + 0xD806DCD9, /*0xD806DCB9*/ /*U+0118D9*/ /*U+0118B9*/ /*WARANG CITI CAPITAL LETTER HIYO*/ + 0xD806DCDA, /*0xD806DCBA*/ /*U+0118DA*/ /*U+0118BA*/ /*WARANG CITI CAPITAL LETTER HOLO*/ + 0xD806DCDB, /*0xD806DCBB*/ /*U+0118DB*/ /*U+0118BB*/ /*WARANG CITI CAPITAL LETTER HORR*/ + 0xD806DCDC, /*0xD806DCBC*/ /*U+0118DC*/ /*U+0118BC*/ /*WARANG CITI CAPITAL LETTER HAR*/ + 0xD806DCDD, /*0xD806DCBD*/ /*U+0118DD*/ /*U+0118BD*/ /*WARANG CITI CAPITAL LETTER SSUU*/ + 0xD806DCDE, /*0xD806DCBE*/ /*U+0118DE*/ /*U+0118BE*/ /*WARANG CITI CAPITAL LETTER SII*/ + 0xD806DCDF, /*0xD806DCBF*/ /*U+0118DF*/ /*U+0118BF*/ /*WARANG CITI CAPITAL LETTER VIYO*/ +}; + +/* EOF */ diff --git a/libatalk/unicode/utf8.c b/libatalk/unicode/utf8.c new file mode 100644 index 0000000..04dbb9a --- /dev/null +++ b/libatalk/unicode/utf8.c @@ -0,0 +1,281 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002,2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + From samba 3.0 beta and GNU libiconv-1.8 + It's bad but most of the time we can't use libc iconv service: + - it doesn't round trip for most encoding + - it doesn't know about Apple extension +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include +#include +#include + +#include +#include +#include +#include + +/* Given a trailing UTF-8 byte, get the contribution from it to + * the Unicode scalar value for a particular bit shift amount + */ +#define GETUCVAL(utf8_trailbyte,shift) ((unsigned int) (( utf8_trailbyte & 0x3F) << shift)) + +/* Given a unicode scalar, get a trail UTF-8 byte for a particular bit shift amount */ +#define GETUTF8TRAILBYTE(uc,shift) ((char)( 0x80 | ((uc >> shift) & 0x3F) ) ) + + + +static size_t utf8_pull(void *,char **, size_t *, char **, size_t *); +static size_t utf8_push(void *,char **, size_t *, char **, size_t *); + +struct charset_functions charset_utf8 = +{ + "UTF8", + 0x08000103, + utf8_pull, + utf8_push, + CHARSET_VOLUME | CHARSET_MULTIBYTE | CHARSET_PRECOMPOSED, + NULL, + NULL, NULL +}; + +struct charset_functions charset_utf8_mac = +{ + "UTF8-MAC", + 0x08000103, + utf8_pull, + utf8_push, + CHARSET_VOLUME | CHARSET_CLIENT | CHARSET_MULTIBYTE | CHARSET_DECOMPOSED, + NULL, + NULL, NULL +}; + +/* The Unicode Standard Version 6.2 – Core Specification */ +/* http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf */ +/* */ +/* Scalar Value First Second Third Fourth */ +/* 00000000 0xxxxxxx 0xxxxxxx */ +/* 00000yyy yyxxxxxx 110yyyyy 10xxxxxx */ +/* zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx */ +/* 000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx */ + + +/* ------------------- Convert from UTF-8 to UTF-16 -------------------*/ + +/* Code Points First Second Third Fourth */ +/* U+0000..U+007F 00..7F */ +/* U+0080..U+07FF C2..DF 80..BF */ +/* U+0800..U+0FFF E0 A0..BF 80..BF */ +/* U+1000..U+CFFF E1..EC 80..BF 80..BF */ +/* U+D000..U+D7FF ED 80..9F 80..BF */ +/* U+E000..U+FFFF EE..EF 80..BF 80..BF */ +/* U+10000..U+3FFFF F0 90..BF 80..BF 80..BF */ +/* U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF */ +/* U+100000..U+10FFFF F4 80..8F 80..BF 80..BF */ + +static size_t utf8_pull(void *cd _U_, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + ucs2_t uc = 0; + unsigned int codepoint; + int len; + + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + unsigned char *c = (unsigned char *)*inbuf; + len = 1; + + /* Arrange conditionals in the order of most frequent occurrence + * for users of Latin-based chars */ + if ((c[0] & 0x80) == 0) { /* 0xxx xxxx */ /* 1 byte */ + uc = c[0]; + } else if ((c[0] & 0xe0) == 0xc0) { /* 110y yyyy */ /* 2 bytes */ + if (*inbytesleft < 2) goto inval; + if (c[0] < 0xc2) goto ilseq; /* C2-DF */ + if ((c[1] & 0xc0) != 0x80) goto ilseq; /* 80-BF */ + uc = (ucs2_t) (((c[0] & 0x1f) << 6) | GETUCVAL(c[1],0)) ; + len = 2; + } else if ((c[0] & 0xf0) == 0xe0) { /* 1110 zzzz */ /* 3 bytes */ + if (*inbytesleft < 3) goto inval; + if (!((c[0] == 0xe0 && (c[1] & 0xe0) == 0xa0) || /* E0 A0-BF*/ + (0xe1 <= c[0] && c[0] <= 0xec && (c[1] & 0xc0) == 0x80) || /* E1-EC 80-BF */ + (c[0] == 0xed && (c[1] & 0xe0) == 0x80) || /* ED 80-9F */ + ((c[0] & 0xfe) == 0xee && (c[1] & 0xc0) == 0x80))) /* EE-EF 80-BF */ + goto ilseq; + if ((c[2] & 0xc0) != 0x80) goto ilseq; /* 80-BF */ + uc = (ucs2_t) (((c[0] & 0x0f) << 12) | GETUCVAL(c[1],6) | GETUCVAL(c[2],0)) ; + len = 3; + } else if ((c[0] & 0xf8) == 0xf0) { /* 1111 0uuu */ /* 4 bytes */ + if (*inbytesleft < 4) goto inval; + if (*outbytesleft < 4) goto toobig; + if (c[0] > 0xf4) goto ilseq; /* happens for surrogate pairs only */ + if (!((c[0] == 0xf0 && 0x90 <= c[1] && c[1] <= 0xbf) || /* F0 90-BF */ + (0xf1 <= c[0] && c[0] <= 0xf3 && (c[1] & 0xc0) == 0x80) || /* F1-F3 80-BF */ + (c[0] == 0xf4 && (c[1] & 0xc0) == 0x80))) /* F4 80-8F */ + goto ilseq; + if ((c[2] & 0xc0) != 0x80) goto ilseq; /* 80-BF */ + if ((c[3] & 0xc0) != 0x80) goto ilseq; /* 80-BF */ + codepoint = ((c[0] & 0x07) << 18) | GETUCVAL(c[1],12) | + GETUCVAL(c[2],6) | GETUCVAL(c[3],0); + SSVAL(*outbuf,0,(((codepoint - 0x10000) >> 10) + 0xD800)); /* hi */ + SSVAL(*outbuf,2,(0xDC00 + (codepoint & 0x03FF))); /* low */ + len = 4; + (*inbuf) += 4; + (*inbytesleft) -= 4; + (*outbytesleft) -= 4; + (*outbuf) += 4; + continue; + } else { + goto ilseq; + } + + SSVAL(*outbuf,0,uc); + (*inbuf) += len; + (*inbytesleft) -= len; + (*outbytesleft) -= 2; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + goto toobig; + } + + return 0; + +toobig: + LOG(log_debug, logtype_default, "short ucs-2 write"); + errno = E2BIG; + return -1; + +ilseq: + LOG(log_debug, logtype_default, "malformed utf8 sequence"); + errno = EILSEQ; + return -1; + +inval: + LOG(log_debug, logtype_default, "short utf8 char"); + errno = EINVAL; + return -1; +} + +/* --------------------- Convert from UTF-16 to UTF-8 -----------*/ +static size_t utf8_push(void *cd _U_, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + ucs2_t uc=0; + ucs2_t hi, low; + unsigned int codepoint; + int olen, ilen; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + unsigned char *c = (unsigned char *)*outbuf; + uc = SVAL((*inbuf),0); + olen=1; + ilen=2; + + /* Arrange conditionals in the order of most frequent occurrence for + users of Latin-based chars */ + if (uc < 0x80) { + c[0] = uc; + } else if (uc < 0x800) { + if (*outbytesleft < 2) { + LOG(log_debug, logtype_default, "short utf8 write"); + goto toobig; + } + c[1] = GETUTF8TRAILBYTE(uc, 0); + c[0] = (char)(0xc0 | ((uc >> 6) & 0x1f)); + olen = 2; + } + else if ( uc >= 0x202a && uc <= 0x202e ) { + /* ignore bidi hint characters */ + olen = 0; + } + /* + * A 2-byte uc value represents a stand-alone Unicode character if + * 0 <= uc < 0xd800 or 0xdfff < uc <= 0xffff. + * If 0xd800 <= uc <= 0xdfff, uc itself does not represent a Unicode character. + * Rather, it is just part of a surrogate pair. A surrogate pair consists of + * a high surrogate in the range [0xd800 ... 0xdbff] and a low surrogate in the + * range [0xdc00 ... 0xdfff]. Together the pair maps to a single Unicode character + * whose scalar value is 64K or larger. It is this scalar value that is transformed + * to UTF-8, not the individual surrogates. + * + * See www.unicode.org/faq/utf_bom.html for more info. + */ + + else if ( 0xd800 <= uc && uc <= 0xdfff) { + /* surrogate - needs 4 bytes from input and 4 bytes for output to UTF-8 */ + if (*outbytesleft < 4) { + LOG(log_debug, logtype_default, "short utf8 write"); + goto toobig; + } + if (*inbytesleft < 4) { + errno = EINVAL; + return -1; + } + hi = SVAL((*inbuf),0); + low = SVAL((*inbuf),2); + if ( 0xd800 <= hi && hi <= 0xdbff && 0xdc00 <= low && low <= 0xdfff) { + codepoint = ((hi - 0xd800) << 10) + (low - 0xdc00) + 0x10000; + c[3] = GETUTF8TRAILBYTE(codepoint, 0); + c[2] = GETUTF8TRAILBYTE(codepoint, 6); + c[1] = GETUTF8TRAILBYTE(codepoint, 12); + c[0] = (char)(0xf0 | ((codepoint >> 18) & 0x07)); + ilen = olen = 4; + } else { /* invalid values for surrogate */ + errno = EINVAL; + return -1; + } + } else { + if (*outbytesleft < 3) { + LOG(log_debug, logtype_default, "short utf8 write"); + goto toobig; + } + c[2] = GETUTF8TRAILBYTE(uc, 0); + c[1] = GETUTF8TRAILBYTE(uc, 6); + c[0] = (char)(0xe0 | ((uc >> 12) & 0x0f)); + olen = 3; + } + + (*inbytesleft) -= ilen; + (*outbytesleft) -= olen; + (*inbuf) += ilen; + (*outbuf) += olen; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return 0; + +toobig: + errno = E2BIG; + return -1; +} diff --git a/libatalk/unicode/util_unistr.c b/libatalk/unicode/util_unistr.c new file mode 100644 index 0000000..5108a4c --- /dev/null +++ b/libatalk/unicode/util_unistr.c @@ -0,0 +1,837 @@ +/******************************************************************* + NOTE: + The early netatalk 2.x was based on UCS-2. + UCS-2 don't support chars above U+10000. + Recent netatalk is based on UTF-16. + UTF-16 can support chars above U+10000, using Surrogate Pair. + However, Surrogate Pair is complex, dirty, filthy and disagreeable. + There might still be latent bugs... +********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "precompose.h" + +/******************************************************************* + Convert a string to lower case. + return True if any char is converted +********************************************************************/ +/* surrogate pair support */ + +int strlower_w(ucs2_t *s) +{ + int ret = 0; + + while (*s) { + if ((0xD800 <= *s) && (*s < 0xDC00)) { + if ((0xDC00 <= s[1]) && (s[1] < 0xE000)) { + uint32_t s_sp = (uint32_t)*s << 16 | (uint32_t)s[1]; + uint32_t v_sp = tolower_sp(s_sp); + if (v_sp != s_sp) { + *s = v_sp >> 16; + s++; + *s = v_sp & 0xFFFF; + ret = 1; + } + } + } else { + ucs2_t v = tolower_w(*s); + if (v != *s) { + *s = v; + ret = 1; + } + } + s++; + } + return ret; +} + +/******************************************************************* + Convert a string to upper case. + return True if any char is converted +********************************************************************/ +/* surrogate pair support */ + +int strupper_w(ucs2_t *s) +{ + int ret = 0; + + while (*s) { + if ((0xD800 <= *s) && (*s < 0xDC00)) { + if ((0xDC00 <= s[1]) && (s[1] < 0xE000)) { + uint32_t s_sp = (uint32_t)*s << 16 | (uint32_t)s[1]; + uint32_t v_sp = toupper_sp(s_sp); + if (v_sp != s_sp) { + *s = v_sp >> 16; + s++; + *s = v_sp & 0xFFFF; + ret = 1; + } + } + } else { + ucs2_t v = toupper_w(*s); + if (v != *s) { + *s = v; + ret = 1; + } + } + s++; + } + return ret; +} + +/******************************************************************* +wide & sp islower() +determine if a character is lowercase +********************************************************************/ +/* These functions are not used. */ + +int islower_w(ucs2_t c) +{ + return ( c == tolower_w(c)); +} + +int islower_sp(uint32_t c_sp) +{ + return ( c_sp == tolower_sp(c_sp)); +} + +/******************************************************************* +wide & sp isupper() +determine if a character is uppercase +********************************************************************/ +/* These functions are not used. */ + +int isupper_w(ucs2_t c) +{ + return ( c == toupper_w(c)); +} + +int isupper_sp(uint32_t c_sp) +{ + return ( c_sp == toupper_sp(c_sp)); +} + +/******************************************************************* +wide strlen() + Count the number of characters in a UTF-16 string. +********************************************************************/ +/* NOTE: one surrogate pair is two characters. */ + +size_t strlen_w(const ucs2_t *src) +{ + size_t len; + + for(len = 0; *src++; len++) ; + + return len; +} + +/******************************************************************* +wide strnlen() + Count up to max number of characters in a UTF-16 string. +********************************************************************/ +/* NOTE: one surrogate pair is two characters. */ + +size_t strnlen_w(const ucs2_t *src, size_t max) +{ + size_t len; + + for(len = 0; *src++ && (len < max); len++) ; + + return len; +} + +/******************************************************************* +wide strchr() +********************************************************************/ +/* NOTE: hi and lo of surrogate pair are separately processed. */ + +ucs2_t *strchr_w(const ucs2_t *s, ucs2_t c) +{ + while (*s != 0) { + if (c == *s) return (ucs2_t *)s; + s++; + } + if (c == *s) return (ucs2_t *)s; + + return NULL; +} + +/******************************************************************* +wide & sp strcasechr() +********************************************************************/ +/* NOTE: separately process BMP and surrogate pair */ + +ucs2_t *strcasechr_w(const ucs2_t *s, ucs2_t c) +{ + while (*s != 0) { + if (tolower_w(c) == tolower_w(*s)) return (ucs2_t *)s; + s++; + } + if (c == *s) return (ucs2_t *)s; + + return NULL; +} + +ucs2_t *strcasechr_sp(const ucs2_t *s, uint32_t c_sp) +{ + if (*s == 0) return NULL; + while (s[1] != 0) { + if (tolower_sp(c_sp) == tolower_sp((uint32_t)*s << 16 | (uint32_t)s[1])) return (ucs2_t *)s; + s++; + } + + return NULL; +} + +/******************************************************************* +wide strcmp() +********************************************************************/ +/* no problem of surrogate pair */ + +int strcmp_w(const ucs2_t *a, const ucs2_t *b) +{ + while (*b && *a == *b) { a++; b++; } + return (*a - *b); + /* warning: if *a != *b and both are not 0 we retrun a random + greater or lesser than 0 number not realted to which + string is longer */ +} + +/******************************************************************* +wide strncmp() +********************************************************************/ +/* no problem of surrogate pair */ + +int strncmp_w(const ucs2_t *a, const ucs2_t *b, size_t len) +{ + size_t n = 0; + while ((n < len) && *b && *a == *b) { a++; b++; n++;} + return (len - n)?(*a - *b):0; +} + +/******************************************************************* +wide strstr() +********************************************************************/ +/* no problem of surrogate pair */ + +ucs2_t *strstr_w(const ucs2_t *s, const ucs2_t *ins) +{ + ucs2_t *r; + size_t slen, inslen; + + if (!s || !*s || !ins || !*ins) return NULL; + slen = strlen_w(s); + inslen = strlen_w(ins); + r = (ucs2_t *)s; + while ((r = strchr_w(r, *ins))) { + if (strncmp_w(r, ins, inslen) == 0) return r; + r++; + } + return NULL; +} + +/******************************************************************* +wide strcasestr() +********************************************************************/ +/* surrogate pair support */ + +ucs2_t *strcasestr_w(const ucs2_t *s, const ucs2_t *ins) +{ + ucs2_t *r; + size_t slen, inslen; + + if (!s || !*s || !ins || !*ins) return NULL; + slen = strlen_w(s); + inslen = strlen_w(ins); + r = (ucs2_t *)s; + + if ((0xD800 <= *ins) && (*ins < 0xDC00)) { + if ((0xDC00 <= ins[1]) && (ins[1] < 0xE000)) { + uint32_t ins_sp = (uint32_t)*ins << 16 | (uint32_t)ins[1]; + while ((r = strcasechr_sp(r, ins_sp))) { + if (strncasecmp_w(r, ins, inslen) == 0) return r; + r++; + } + } else { + return NULL; /* illegal sequence */ + } + } else { + while ((r = strcasechr_w(r, *ins))) { + if (strncasecmp_w(r, ins, inslen) == 0) return r; + r++; + } + } + return NULL; +} + +/******************************************************************* +wide strcasecmp() +case insensitive string comparison +********************************************************************/ +/* surrogate pair support */ + +int strcasecmp_w(const ucs2_t *a, const ucs2_t *b) +{ + int ret; + + while (*a && *b) { + if ((0xD800 <= *a) && (*a < 0xDC00)) { + if ((ret = tolower_sp((uint32_t)*a << 16 | (uint32_t)a[1]) - tolower_sp((uint32_t)*b << 16 | (uint32_t)b[1]))) return ret; + a++; + b++; + if (!(*a && *b)) return (tolower_w(*a) - tolower_w(*b)); /* avoid buffer over run */ + } else { + if ((ret = tolower_w(*a) - tolower_w(*b))) return ret; + } + a++; + b++; + } + return (tolower_w(*a) - tolower_w(*b)); +} + +/******************************************************************* +wide strncasecmp() +case insensitive string comparison, length limited +********************************************************************/ +/* NOTE: compare up to 'len+1' if 'len' isolate surrogate pair */ + +int strncasecmp_w(const ucs2_t *a, const ucs2_t *b, size_t len) +{ + size_t n = 0; + int ret; + + while ((n < len) && *a && *b) { + if ((0xD800 <= *a) && (*a < 0xDC00)) { + if ((ret = tolower_sp((uint32_t)*a << 16 | (uint32_t)a[1]) - tolower_sp((uint32_t)*b << 16 | (uint32_t)b[1]))) return ret; + a++; + b++; + n++; + if (!((n < len) && *a && *b)) return (tolower_w(*a) - tolower_w(*b)); + } else { + if ((ret = tolower_w(*a) - tolower_w(*b))) return ret; + } + a++; + b++; + n++; + } + return (len - n)?(tolower_w(*a) - tolower_w(*b)):0; +} + +/******************************************************************* +wide strndup() +duplicate string +********************************************************************/ +/* NOTE: not check isolation of surrogate pair */ +/* if len == 0 then duplicate the whole string */ + +ucs2_t *strndup_w(const ucs2_t *src, size_t len) +{ + ucs2_t *dest; + + if (!len) len = strlen_w(src); + dest = (ucs2_t *)malloc((len + 1) * sizeof(ucs2_t)); + if (!dest) { + LOG (log_error, logtype_default, "strdup_w: out of memory!"); + return NULL; + } + + memcpy(dest, src, len * sizeof(ucs2_t)); + dest[len] = 0; + + return dest; +} + +/******************************************************************* +wide strdup() +duplicate string +********************************************************************/ +/* no problem of surrogate pair */ + +ucs2_t *strdup_w(const ucs2_t *src) +{ + return strndup_w(src, 0); +} + +/******************************************************************* +copy a string with max len +********************************************************************/ +/* This function is not used. */ +/* NOTE: not check isolation of surrogate pair */ + +ucs2_t *strncpy_w(ucs2_t *dest, const ucs2_t *src, const size_t max) +{ + size_t len; + + if (!dest || !src) return NULL; + + for (len = 0; (src[len] != 0) && (len < max); len++) + dest[len] = src[len]; + while (len < max) + dest[len++] = 0; + + return dest; +} + + +/******************************************************************* +append a string of len bytes and add a terminator +********************************************************************/ +/* These functions are not used. */ + +/* NOTE: not check isolation of surrogate pair */ +ucs2_t *strncat_w(ucs2_t *dest, const ucs2_t *src, const size_t max) +{ + size_t start; + size_t len; + + if (!dest || !src) return NULL; + + start = strlen_w(dest); + len = strnlen_w(src, max); + + memcpy(&dest[start], src, len*sizeof(ucs2_t)); + dest[start+len] = 0; + + return dest; +} + +/* no problem of surrogate pair */ +ucs2_t *strcat_w(ucs2_t *dest, const ucs2_t *src) +{ + size_t start; + size_t len; + + if (!dest || !src) return NULL; + + start = strlen_w(dest); + len = strlen_w(src); + + memcpy(&dest[start], src, len*sizeof(ucs2_t)); + dest[start+len] = 0; + + return dest; +} + + +/******************************************************************* +binary search for pre|decomposition +********************************************************************/ + +static ucs2_t do_precomposition(unsigned int base, unsigned int comb) +{ + int min = 0; + int max = PRECOMP_COUNT - 1; + int mid; + uint32_t sought = (base << 16) | comb, that; + + /* binary search */ + while (max >= min) { + mid = (min + max) / 2; + that = (precompositions[mid].base << 16) | (precompositions[mid].comb); + if (that < sought) { + min = mid + 1; + } else if (that > sought) { + max = mid - 1; + } else { + return precompositions[mid].replacement; + } + } + /* no match */ + return 0; +} + +/* ------------------------ */ +static uint32_t do_precomposition_sp(unsigned int base_sp, unsigned int comb_sp) +{ + int min = 0; + int max = PRECOMP_SP_COUNT - 1; + int mid; + uint64_t sought_sp = ((uint64_t)base_sp << 32) | (uint64_t)comb_sp, that_sp; + + /* binary search */ + while (max >= min) { + mid = (min + max) / 2; + that_sp = ((uint64_t)precompositions_sp[mid].base_sp << 32) | ((uint64_t)precompositions_sp[mid].comb_sp); + if (that_sp < sought_sp) { + min = mid + 1; + } else if (that_sp > sought_sp) { + max = mid - 1; + } else { + return precompositions_sp[mid].replacement_sp; + } + } + /* no match */ + return 0; +} + +/* -------------------------- */ +static uint32_t do_decomposition(ucs2_t base) +{ + int min = 0; + int max = DECOMP_COUNT - 1; + int mid; + uint32_t sought = base; + uint32_t result, that; + + /* binary search */ + while (max >= min) { + mid = (min + max) / 2; + that = decompositions[mid].replacement; + if (that < sought) { + min = mid + 1; + } else if (that > sought) { + max = mid - 1; + } else { + result = (decompositions[mid].base << 16) | (decompositions[mid].comb); + return result; + } + } + /* no match */ + return 0; +} + +/* -------------------------- */ +static uint64_t do_decomposition_sp(unsigned int base_sp) +{ + int min = 0; + int max = DECOMP_SP_COUNT - 1; + int mid; + uint32_t sought_sp = base_sp; + uint32_t that_sp; + uint64_t result_sp; + + /* binary search */ + while (max >= min) { + mid = (min + max) / 2; + that_sp = decompositions_sp[mid].replacement_sp; + if (that_sp < sought_sp) { + min = mid + 1; + } else if (that_sp > sought_sp) { + max = mid - 1; + } else { + result_sp = ((uint64_t)decompositions_sp[mid].base_sp << 32) | ((uint64_t)decompositions_sp[mid].comb_sp); + return result_sp; + } + } + /* no match */ + return 0; +} + +/******************************************************************* +pre|decomposition + + we can't use static, this stuff needs to be reentrant + static char comp[MAXPATHLEN +1]; + + We don't implement Singleton and Canonical Ordering. + We ignore CompositionExclusions.txt. + because they cause the problem of the roundtrip + such as Dancing Icon. + + exclude U2000-U2FFF, UFE30-UFE4F and U2F800-U2FA1F ranges + in precompose.h from composition according to AFP 3.x spec +********************************************************************/ + +size_t precompose_w (ucs2_t *name, size_t inplen, ucs2_t *comp, size_t *outlen) +{ + size_t i; + ucs2_t base, comb; + uint32_t base_sp, comb_sp; + ucs2_t *in, *out; + ucs2_t lindex, vindex; + ucs2_t result; + uint32_t result_sp; + size_t o_len = *outlen; + + if (!inplen || (inplen & 1) || inplen > o_len) + return (size_t)-1; + + i = 0; + in = name; + out = comp; + + base = *in; + while (*outlen > 2) { + i += 2; + if (i == inplen) { + *out = base; + out++; + *out = 0; + *outlen -= 2; + return o_len - *outlen; + } + in++; + comb = *in; + result = 0; + + /* Non-Combination Character */ + if (comb < 0x300) ; + + /* Unicode Standard Annex #15 A10.3 Hangul Composition */ + /* Step 1 */ + else if ((VBASE <= comb) && (comb <= VBASE + VCOUNT)) { + if ((LBASE <= base) && (base < LBASE + LCOUNT)) { + result = 1; + lindex = base - LBASE; + vindex = comb - VBASE; + base = SBASE + (lindex * VCOUNT + vindex) * TCOUNT; + } + } + + /* Step 2 */ + else if ((TBASE < comb) && (comb < TBASE + TCOUNT)) { + if ((SBASE <= base) && (base < SBASE + SCOUNT) && (((base - SBASE) % TCOUNT) == 0)) { + result = 1; + base += comb - TBASE; + } + } + + /* Binary Search for Surrogate Pair */ + else if ((0xD800 <= base) && (base < 0xDC00)) { + if ((0xDC00 <= comb) && (comb < 0xE000) && (i + 6 <= inplen)) { + base_sp = ((uint32_t)base << 16) | (uint32_t)comb; + do { + comb_sp = ((uint32_t)in[1] << 16) | (uint32_t)in[2]; + if ((result_sp = do_precomposition_sp(base_sp, comb_sp))) { + base_sp = result_sp; + i += 4; + in +=2; + } + } while ((i + 6 <= inplen) && result_sp) ; + + *out = base_sp >> 16; + out++; + *outlen -= 2; + + if (*outlen <= 2) { + errno = E2BIG; + return (size_t)-1; + } + + *out = base_sp & 0xFFFF; + out++; + *outlen -= 2; + + i += 2; + if (i == inplen) { + out++; + *out = 0; + return o_len - *outlen; + } + in++; + base = *in; + + result = 1; + } + } + + /* Binary Search for BMP */ + else if ((result = do_precomposition(base, comb))) { + base = result; + } + + if (!result) { + *out = base; + out++; + *outlen -= 2; + base = comb; + } + } + + errno = E2BIG; + return (size_t)-1; +} + +/* --------------- */ +size_t decompose_w (ucs2_t *name, size_t inplen, ucs2_t *comp, size_t *outlen) +{ + size_t i; + size_t comblen; + ucs2_t base, comb[COMBBUFLEN]; + uint32_t base_sp; + ucs2_t sindex, tjamo; + ucs2_t *in, *out; + unsigned int result; + uint64_t result_sp; + size_t o_len = *outlen; + + if (!inplen || (inplen & 1)) + return (size_t)-1; + i = 0; + in = name; + out = comp; + + while (i < inplen) { + base = *in; + comblen = 0; + + /* check ASCII first. this is frequent. */ + if (base <= 0x007f) ; + + /* Unicode Standard Annex #15 A10.2 Hangul Decomposition */ + else if ((SBASE <= base) && (base < SBASE + SCOUNT)) { + sindex = base - SBASE; + base = LBASE + sindex / NCOUNT; + comb[COMBBUFLEN-2] = VBASE + (sindex % NCOUNT) / TCOUNT; + + /* */ + if ((tjamo = TBASE + sindex % TCOUNT) == TBASE) { + comb[COMBBUFLEN-1] = comb[COMBBUFLEN-2]; + comblen = 1; + } + + /* */ + else { + comb[COMBBUFLEN-1] = tjamo; + comblen = 2; + } + } + + /* Binary Search for Surrogate Pair */ + else if ((0xD800 <= base) && (base < 0xDC00)) { + if (i + 2 < inplen) { + base_sp = ((uint32_t)base << 16) | (uint32_t)in[1]; + do { + if ( !(result_sp = do_decomposition_sp(base_sp))) break; + comblen += 2; + base_sp = result_sp >> 32; + comb[COMBBUFLEN-comblen] = (result_sp >> 16) & 0xFFFF; /* hi */ + comb[COMBBUFLEN-comblen+1] = result_sp & 0xFFFF; /* lo */ + } while (comblen < MAXCOMBSPLEN); + + if (*outlen < (comblen + 1) << 1) { + errno = E2BIG; + return (size_t)-1; + } + + *out = base_sp >> 16; /* hi */ + out++; + *outlen -= 2; + + base = base_sp & 0xFFFF; /* lo */ + + i += 2; + in++; + } + } + + /* Binary Search for BMP */ + else { + do { + if ( !(result = do_decomposition(base))) break; + comblen++; + base = result >> 16; + comb[COMBBUFLEN-comblen] = result & 0xFFFF; + } while ((0x007f < base) && (comblen < MAXCOMBLEN)); + } + + if (*outlen < (comblen + 1) << 1) { + errno = E2BIG; + return (size_t)-1; + } + + *out = base; + out++; + *outlen -= 2; + + while ( comblen > 0 ) { + *out = comb[COMBBUFLEN-comblen]; + out++; + *outlen -= 2; + comblen--; + } + + i += 2; + in++; + } + + *out = 0; + return o_len-*outlen; +} + +/******************************************************************* +length of UTF-8 character and string +********************************************************************/ + +size_t utf8_charlen ( char* utf8 ) +{ + unsigned char *p; + + p = (unsigned char*) utf8; + + if ( *p < 0x80 ) + return (1); + else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0) + return (2); + else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0) + return (3); + else if ( *p > 0xe0 && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0) + return (3); + else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 ) + return (4); + else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 ) + return (4); + else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 ) + return (4); + else + return ((size_t) -1); +} + + +size_t utf8_strlen_validate ( char * utf8 ) +{ + size_t len; + unsigned char *p; + + p = (unsigned char*) utf8; + len = 0; + + /* see http://www.unicode.org/unicode/reports/tr27/ for an explanation */ + + while ( *p != '\0') + { + if ( *p < 0x80 ) + p++; + + else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0) + p += 2; + + else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0) + p += 3; + + else if ( *p > 0xe0 && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0) + p += 3; + + else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 ) + p += 4; + + else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 ) + p += 4; + + else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 ) + p += 4; + + else + return ((size_t) -1); + + len++; + } + + return (len); +} diff --git a/libatalk/util/Makefile.am b/libatalk/util/Makefile.am new file mode 100644 index 0000000..2019516 --- /dev/null +++ b/libatalk/util/Makefile.am @@ -0,0 +1,34 @@ +# Makefile.am for libatalk/util/ + +pkgconfdir = @PKGCONFDIR@ + +noinst_LTLIBRARIES = libutil.la + +libutil_la_SOURCES = \ + bprint.c \ + cnid.c \ + fault.c \ + getiface.c \ + gettok.c \ + locking.c \ + logger.c \ + module.c \ + netatalk_conf.c \ + queue.c \ + server_child.c \ + server_ipc.c \ + server_lock.c \ + socket.c \ + strdicasecmp.c \ + unix.c + +libutil_la_CFLAGS = \ + -D_PATH_CONFDIR='"$(pkgconfdir)/"' \ + -DSERVERTEXT='"$(SERVERTEXT)/"' \ + -D_PATH_AFPDPWFILE='"$(pkgconfdir)/afppasswd"' \ + -D_PATH_AFPDUAMPATH='"$(UAMS_PATH)/"' \ + -D_PATH_STATEDIR='"$(localstatedir)/netatalk/"' + +if HAVE_ATFUNCS +libutil_la_SOURCES += ftw.c +endif diff --git a/libatalk/util/Makefile.in b/libatalk/util/Makefile.in new file mode 100644 index 0000000..8fee29f --- /dev/null +++ b/libatalk/util/Makefile.in @@ -0,0 +1,823 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/util/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_ATFUNCS_TRUE@am__append_1 = ftw.c +subdir = libatalk/util +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libutil_la_LIBADD = +am__libutil_la_SOURCES_DIST = bprint.c cnid.c fault.c getiface.c \ + gettok.c locking.c logger.c module.c netatalk_conf.c queue.c \ + server_child.c server_ipc.c server_lock.c socket.c \ + strdicasecmp.c unix.c ftw.c +@HAVE_ATFUNCS_TRUE@am__objects_1 = libutil_la-ftw.lo +am_libutil_la_OBJECTS = libutil_la-bprint.lo libutil_la-cnid.lo \ + libutil_la-fault.lo libutil_la-getiface.lo \ + libutil_la-gettok.lo libutil_la-locking.lo \ + libutil_la-logger.lo libutil_la-module.lo \ + libutil_la-netatalk_conf.lo libutil_la-queue.lo \ + libutil_la-server_child.lo libutil_la-server_ipc.lo \ + libutil_la-server_lock.lo libutil_la-socket.lo \ + libutil_la-strdicasecmp.lo libutil_la-unix.lo $(am__objects_1) +libutil_la_OBJECTS = $(am_libutil_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libutil_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libutil_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libutil_la_SOURCES) +DIST_SOURCES = $(am__libutil_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkgconfdir = @PKGCONFDIR@ +noinst_LTLIBRARIES = libutil.la +libutil_la_SOURCES = bprint.c cnid.c fault.c getiface.c gettok.c \ + locking.c logger.c module.c netatalk_conf.c queue.c \ + server_child.c server_ipc.c server_lock.c socket.c \ + strdicasecmp.c unix.c $(am__append_1) +libutil_la_CFLAGS = \ + -D_PATH_CONFDIR='"$(pkgconfdir)/"' \ + -DSERVERTEXT='"$(SERVERTEXT)/"' \ + -D_PATH_AFPDPWFILE='"$(pkgconfdir)/afppasswd"' \ + -D_PATH_AFPDUAMPATH='"$(UAMS_PATH)/"' \ + -D_PATH_STATEDIR='"$(localstatedir)/netatalk/"' + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/util/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/util/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libutil.la: $(libutil_la_OBJECTS) $(libutil_la_DEPENDENCIES) $(EXTRA_libutil_la_DEPENDENCIES) + $(AM_V_CCLD)$(libutil_la_LINK) $(libutil_la_OBJECTS) $(libutil_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-bprint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-cnid.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-fault.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-ftw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-getiface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-gettok.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-locking.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-logger.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-module.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-netatalk_conf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-queue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-server_child.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-server_ipc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-server_lock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-socket.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-strdicasecmp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libutil_la-unix.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libutil_la-bprint.lo: bprint.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-bprint.lo -MD -MP -MF $(DEPDIR)/libutil_la-bprint.Tpo -c -o libutil_la-bprint.lo `test -f 'bprint.c' || echo '$(srcdir)/'`bprint.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-bprint.Tpo $(DEPDIR)/libutil_la-bprint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bprint.c' object='libutil_la-bprint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-bprint.lo `test -f 'bprint.c' || echo '$(srcdir)/'`bprint.c + +libutil_la-cnid.lo: cnid.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-cnid.lo -MD -MP -MF $(DEPDIR)/libutil_la-cnid.Tpo -c -o libutil_la-cnid.lo `test -f 'cnid.c' || echo '$(srcdir)/'`cnid.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-cnid.Tpo $(DEPDIR)/libutil_la-cnid.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cnid.c' object='libutil_la-cnid.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-cnid.lo `test -f 'cnid.c' || echo '$(srcdir)/'`cnid.c + +libutil_la-fault.lo: fault.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-fault.lo -MD -MP -MF $(DEPDIR)/libutil_la-fault.Tpo -c -o libutil_la-fault.lo `test -f 'fault.c' || echo '$(srcdir)/'`fault.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-fault.Tpo $(DEPDIR)/libutil_la-fault.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fault.c' object='libutil_la-fault.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-fault.lo `test -f 'fault.c' || echo '$(srcdir)/'`fault.c + +libutil_la-getiface.lo: getiface.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-getiface.lo -MD -MP -MF $(DEPDIR)/libutil_la-getiface.Tpo -c -o libutil_la-getiface.lo `test -f 'getiface.c' || echo '$(srcdir)/'`getiface.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-getiface.Tpo $(DEPDIR)/libutil_la-getiface.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getiface.c' object='libutil_la-getiface.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-getiface.lo `test -f 'getiface.c' || echo '$(srcdir)/'`getiface.c + +libutil_la-gettok.lo: gettok.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-gettok.lo -MD -MP -MF $(DEPDIR)/libutil_la-gettok.Tpo -c -o libutil_la-gettok.lo `test -f 'gettok.c' || echo '$(srcdir)/'`gettok.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-gettok.Tpo $(DEPDIR)/libutil_la-gettok.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gettok.c' object='libutil_la-gettok.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-gettok.lo `test -f 'gettok.c' || echo '$(srcdir)/'`gettok.c + +libutil_la-locking.lo: locking.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-locking.lo -MD -MP -MF $(DEPDIR)/libutil_la-locking.Tpo -c -o libutil_la-locking.lo `test -f 'locking.c' || echo '$(srcdir)/'`locking.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-locking.Tpo $(DEPDIR)/libutil_la-locking.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='locking.c' object='libutil_la-locking.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-locking.lo `test -f 'locking.c' || echo '$(srcdir)/'`locking.c + +libutil_la-logger.lo: logger.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-logger.lo -MD -MP -MF $(DEPDIR)/libutil_la-logger.Tpo -c -o libutil_la-logger.lo `test -f 'logger.c' || echo '$(srcdir)/'`logger.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-logger.Tpo $(DEPDIR)/libutil_la-logger.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logger.c' object='libutil_la-logger.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-logger.lo `test -f 'logger.c' || echo '$(srcdir)/'`logger.c + +libutil_la-module.lo: module.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-module.lo -MD -MP -MF $(DEPDIR)/libutil_la-module.Tpo -c -o libutil_la-module.lo `test -f 'module.c' || echo '$(srcdir)/'`module.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-module.Tpo $(DEPDIR)/libutil_la-module.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='module.c' object='libutil_la-module.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-module.lo `test -f 'module.c' || echo '$(srcdir)/'`module.c + +libutil_la-netatalk_conf.lo: netatalk_conf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-netatalk_conf.lo -MD -MP -MF $(DEPDIR)/libutil_la-netatalk_conf.Tpo -c -o libutil_la-netatalk_conf.lo `test -f 'netatalk_conf.c' || echo '$(srcdir)/'`netatalk_conf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-netatalk_conf.Tpo $(DEPDIR)/libutil_la-netatalk_conf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netatalk_conf.c' object='libutil_la-netatalk_conf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-netatalk_conf.lo `test -f 'netatalk_conf.c' || echo '$(srcdir)/'`netatalk_conf.c + +libutil_la-queue.lo: queue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-queue.lo -MD -MP -MF $(DEPDIR)/libutil_la-queue.Tpo -c -o libutil_la-queue.lo `test -f 'queue.c' || echo '$(srcdir)/'`queue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-queue.Tpo $(DEPDIR)/libutil_la-queue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue.c' object='libutil_la-queue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-queue.lo `test -f 'queue.c' || echo '$(srcdir)/'`queue.c + +libutil_la-server_child.lo: server_child.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-server_child.lo -MD -MP -MF $(DEPDIR)/libutil_la-server_child.Tpo -c -o libutil_la-server_child.lo `test -f 'server_child.c' || echo '$(srcdir)/'`server_child.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-server_child.Tpo $(DEPDIR)/libutil_la-server_child.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server_child.c' object='libutil_la-server_child.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-server_child.lo `test -f 'server_child.c' || echo '$(srcdir)/'`server_child.c + +libutil_la-server_ipc.lo: server_ipc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-server_ipc.lo -MD -MP -MF $(DEPDIR)/libutil_la-server_ipc.Tpo -c -o libutil_la-server_ipc.lo `test -f 'server_ipc.c' || echo '$(srcdir)/'`server_ipc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-server_ipc.Tpo $(DEPDIR)/libutil_la-server_ipc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server_ipc.c' object='libutil_la-server_ipc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-server_ipc.lo `test -f 'server_ipc.c' || echo '$(srcdir)/'`server_ipc.c + +libutil_la-server_lock.lo: server_lock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-server_lock.lo -MD -MP -MF $(DEPDIR)/libutil_la-server_lock.Tpo -c -o libutil_la-server_lock.lo `test -f 'server_lock.c' || echo '$(srcdir)/'`server_lock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-server_lock.Tpo $(DEPDIR)/libutil_la-server_lock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server_lock.c' object='libutil_la-server_lock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-server_lock.lo `test -f 'server_lock.c' || echo '$(srcdir)/'`server_lock.c + +libutil_la-socket.lo: socket.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-socket.lo -MD -MP -MF $(DEPDIR)/libutil_la-socket.Tpo -c -o libutil_la-socket.lo `test -f 'socket.c' || echo '$(srcdir)/'`socket.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-socket.Tpo $(DEPDIR)/libutil_la-socket.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='socket.c' object='libutil_la-socket.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-socket.lo `test -f 'socket.c' || echo '$(srcdir)/'`socket.c + +libutil_la-strdicasecmp.lo: strdicasecmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-strdicasecmp.lo -MD -MP -MF $(DEPDIR)/libutil_la-strdicasecmp.Tpo -c -o libutil_la-strdicasecmp.lo `test -f 'strdicasecmp.c' || echo '$(srcdir)/'`strdicasecmp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-strdicasecmp.Tpo $(DEPDIR)/libutil_la-strdicasecmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strdicasecmp.c' object='libutil_la-strdicasecmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-strdicasecmp.lo `test -f 'strdicasecmp.c' || echo '$(srcdir)/'`strdicasecmp.c + +libutil_la-unix.lo: unix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-unix.lo -MD -MP -MF $(DEPDIR)/libutil_la-unix.Tpo -c -o libutil_la-unix.lo `test -f 'unix.c' || echo '$(srcdir)/'`unix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-unix.Tpo $(DEPDIR)/libutil_la-unix.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='unix.c' object='libutil_la-unix.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-unix.lo `test -f 'unix.c' || echo '$(srcdir)/'`unix.c + +libutil_la-ftw.lo: ftw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -MT libutil_la-ftw.lo -MD -MP -MF $(DEPDIR)/libutil_la-ftw.Tpo -c -o libutil_la-ftw.lo `test -f 'ftw.c' || echo '$(srcdir)/'`ftw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libutil_la-ftw.Tpo $(DEPDIR)/libutil_la-ftw.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftw.c' object='libutil_la-ftw.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libutil_la_CFLAGS) $(CFLAGS) -c -o libutil_la-ftw.lo `test -f 'ftw.c' || echo '$(srcdir)/'`ftw.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/util/bprint.c b/libatalk/util/bprint.c new file mode 100644 index 0000000..87b5746 --- /dev/null +++ b/libatalk/util/bprint.c @@ -0,0 +1,52 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef DEBUG +#include +#include +#include +#include + +#include + +static const char hexdig[] = "0123456789ABCDEF"; + +#define BPXLEN 50 +#define BPALEN 18 + +void bprint( data, len ) + char *data; + int len; +{ + char xout[ BPXLEN ], aout[ BPALEN ]; + int i; + + memset( xout, 0, BPXLEN ); + memset( aout, 0, BPALEN ); + + for ( i = 0; len; len--, data++, i++ ) { + if ( i == 16 ) { + printf( "%-48s\t%-16s\n", xout, aout ); + memset( xout, 0, BPXLEN ); + memset( aout, 0, BPALEN ); + i = 0; + } + + if (isprint( (unsigned char)*data )) { + aout[ i ] = *data; + } else { + aout[ i ] = '.'; + } + + xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; + xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ]; + xout[ (i*3) + 2 ] = ' '; + } + + if ( i ) + printf( "%-48s\t%-16s\n", xout, aout ); + + printf("(end)\n"); +} +#endif diff --git a/libatalk/util/cnid.c b/libatalk/util/cnid.c new file mode 100644 index 0000000..7fb0790 --- /dev/null +++ b/libatalk/util/cnid.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2009 Frank Lahm + * Copyright (c) 1991, 1993, 1994 + * 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. + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/*! + * Build path relativ to volume root + * + * path might be: + * (a) relative: + * "dir/subdir" with cwd: "/afp_volume/topdir" + * (b) absolute: + * "/afp_volume/dir/subdir" + * + * @param path (r) path relative to cwd() or absolute + * @param volpath (r) volume path that path is a subdir of (has been computed in volinfo funcs) + * + * @returns relative path in new bstring, caller must bdestroy it + */ +bstring rel_path_in_vol(const char *path, const char *volpath) +{ + EC_INIT; + int cwd = -1; + bstring fpath = NULL; + char *dname = NULL; + struct stat st; + + if (path == NULL || volpath == NULL) + return NULL; + + EC_NEG1_LOG(cwd = open(".", O_RDONLY)); + EC_ZERO( lstat(path, &st) ); + + if (path[0] == '/') { + EC_NULL(fpath = bfromcstr(path)); + } else { + switch (S_IFMT & st.st_mode) { + case S_IFREG: + case S_IFLNK: + EC_NULL_LOG(dname = strdup(path)); + EC_ZERO_LOGSTR(chdir(dirname(dname)), "chdir(%s): %s", dirname, strerror(errno)); + free(dname); + dname = NULL; + EC_NULL(fpath = bfromcstr(getcwdpath())); + BSTRING_STRIP_SLASH(fpath); + EC_ZERO(bcatcstr(fpath, "/")); + EC_NULL_LOG(dname = strdup(path)); + EC_ZERO(bcatcstr(fpath, basename(dname))); + break; + + case S_IFDIR: + EC_ZERO_LOGSTR(chdir(path), "chdir(%s): %s", path, strerror(errno)); + EC_NULL(fpath = bfromcstr(getcwdpath())); + break; + + default: + EC_FAIL; + } + } + + BSTRING_STRIP_SLASH(fpath); + + /* + * Now we have eg: + * fpath: /Volume/netatalk/dir/bla + * volpath: /Volume/netatalk/ + * we want: "dir/bla" + */ + int len = strlen(volpath); + if (volpath[len-1] != '/') + /* in case volpath has no trailing slash */ + len ++; + EC_ZERO(bdelete(fpath, 0, len)); + +EC_CLEANUP: + if (dname) free(dname); + if (cwd != -1) { + fchdir(cwd); + close(cwd); + } + if (ret != 0) + return NULL; + return fpath; +} + +/*! + * Resolves CNID of a given path + * + * path might be: + * (a) relative: + * "dir/subdir" with cwd: "/afp_volume/topdir" + * (b) absolute: + * "/afp_volume/dir/subdir" + * + * path MUST be pointing inside vol, this is usually the case as vol has been build from + * path using loadvolinfo and friends. + * + * @param cdb (r) CNID db handle + * @param volpath (r) UNIX path of volume + * @param path (r) path, see above + * @param did (w) parent CNID of returned CNID + * + * @returns CNID of path + */ +cnid_t cnid_for_path(struct _cnid_db *cdb, + const char *volpath, + const char *path, + cnid_t *did) +{ + EC_INIT; + + cnid_t cnid; + bstring rpath = NULL; + bstring statpath = NULL; + struct bstrList *l = NULL; + struct stat st; + + cnid = htonl(2); + + EC_NULL(rpath = rel_path_in_vol(path, volpath)); + EC_NULL(statpath = bfromcstr(volpath)); + EC_ZERO(bcatcstr(statpath, "/")); + + l = bsplit(rpath, '/'); + for (int i = 0; i < l->qty ; i++) { + *did = cnid; + + EC_ZERO( bconcat(statpath, l->entry[i]) ); + EC_ZERO( lstat(cfrombstr(statpath), &st) ); + + if ((cnid = cnid_add(cdb, + &st, + *did, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + 0)) == CNID_INVALID) { + EC_FAIL; + } + EC_ZERO(bcatcstr(statpath, "/")); + } + +EC_CLEANUP: + bdestroy(rpath); + bstrListDestroy(l); + bdestroy(statpath); + if (ret != 0) + return CNID_INVALID; + + return cnid; +} diff --git a/libatalk/util/fault.c b/libatalk/util/fault.c new file mode 100644 index 0000000..48c4fe0 --- /dev/null +++ b/libatalk/util/fault.c @@ -0,0 +1,164 @@ +/* + Unix SMB/CIFS implementation. + Critical Fault handling + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#ifdef HAVE_BACKTRACE_SYMBOLS +#include +#endif +#include + +#ifndef SIGNAL_CAST +#define SIGNAL_CAST (void (*)(int)) +#endif +#ifndef SAFE_FREE /* Oh no this is also defined in tdb.h */ +#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) +#endif +#define BACKTRACE_STACK_SIZE 64 + +static void (*cont_fn)(void *); + +/******************************************************************* + Catch a signal. This should implement the following semantics: + + 1) The handler remains installed after being called. + 2) The signal should be blocked during handler execution. +********************************************************************/ + +static void (*CatchSignal(int signum,void (*handler)(int )))(int) +{ +#ifdef HAVE_SIGACTION + struct sigaction act; + struct sigaction oldact; + + ZERO_STRUCT(act); + + act.sa_handler = handler; +#if 0 + /* + * We *want* SIGALRM to interrupt a system call. + */ + if(signum != SIGALRM) + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask,signum); + sigaction(signum,&act,&oldact); + return oldact.sa_handler; +#else /* !HAVE_SIGACTION */ + /* FIXME: need to handle sigvec and systems with broken signal() */ + return signal(signum, handler); +#endif +} + +/******************************************************************* + Something really nasty happened - panic ! +********************************************************************/ + +void netatalk_panic(const char *why) +{ +#ifdef HAVE_BACKTRACE_SYMBOLS + void *backtrace_stack[BACKTRACE_STACK_SIZE]; + size_t backtrace_size; + char **backtrace_strings; + + /* get the backtrace (stack frames) */ + backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE); + backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size); + + LOG(log_severe, logtype_default, "PANIC: %s", why); + LOG(log_severe, logtype_default, "BACKTRACE: %d stack frames:", backtrace_size); + + if (backtrace_strings) { + size_t i; + + for (i = 0; i < backtrace_size; i++) + LOG(log_severe, logtype_default, " #%u %s", i, backtrace_strings[i]); + + SAFE_FREE(backtrace_strings); + } +#endif +} + + +/******************************************************************* +report a fault +********************************************************************/ +static void fault_report(int sig) +{ + static int counter; + + if (counter) + abort(); + + counter++; + + LOG(log_severe, logtype_default, "==============================================================="); + LOG(log_severe, logtype_default, "INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),VERSION); + LOG(log_severe, logtype_default, "==============================================================="); + + netatalk_panic("internal error"); + + if (cont_fn) { + cont_fn(NULL); +#ifdef SIGSEGV + CatchSignal(SIGSEGV,SIGNAL_CAST SIG_DFL); +#endif +#ifdef SIGBUS + CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL); +#endif + return; /* this should cause a core dump */ + } + abort(); +} + +/**************************************************************************** +catch serious errors +****************************************************************************/ +static void sig_fault(int sig) +{ + fault_report(sig); +} + +/******************************************************************* +setup our fault handlers +********************************************************************/ +void fault_setup(void (*fn)(void *)) +{ + cont_fn = fn; + +#ifdef SIGSEGV + CatchSignal(SIGSEGV,SIGNAL_CAST sig_fault); +#endif +#ifdef SIGBUS + CatchSignal(SIGBUS,SIGNAL_CAST sig_fault); +#endif +} + diff --git a/libatalk/util/ftw.c b/libatalk/util/ftw.c new file mode 100644 index 0000000..f0ac17f --- /dev/null +++ b/libatalk/util/ftw.c @@ -0,0 +1,828 @@ +/* File tree walker functions. + Copyright (C) 1996-2004, 2006-2008, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + 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. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if __GNUC__ +# define alloca __builtin_alloca +#else +# include +#endif + +#include +#define NAMLEN(dirent) strlen ((dirent)->d_name) +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_SYS_PARAM_H +# include +#endif + +#include + +#ifndef HAVE_MEMPCPY +#define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +#endif + +#define NDEBUG 1 +#include + +#ifndef _LIBC +# undef __chdir +# define __chdir chdir +# undef __closedir +# define __closedir closedir +# undef __fchdir +# define __fchdir fchdir +# undef __getcwd +# define __getcwd(P, N) xgetcwd () +# undef __mempcpy +# define __mempcpy mempcpy +# undef __opendir +# define __opendir opendir +# undef __readdir64 +# define __readdir64 readdir +# undef __tdestroy +# define __tdestroy tdestroy +# undef __tfind +# define __tfind tfind +# undef __tsearch +# define __tsearch tsearch +# undef internal_function +# define internal_function /* empty */ +# undef dirent64 +# define dirent64 dirent +# undef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +/* Support for the LFS API version. */ +#ifndef FTW_NAME +# define FTW_NAME ftw +# define NFTW_NAME nftw +# define NFTW_OLD_NAME __old_nftw +# define NFTW_NEW_NAME __new_nftw +# define INO_T ino_t +# define STAT stat +# define LXSTAT(V,f,sb) lstat (f,sb) +# define XSTAT(V,f,sb) stat (f,sb) +# define FXSTATAT(V,d,f,sb,m) fstatat (d, f, sb, m) + +#endif + +/* We define PATH_MAX if the system does not provide a definition. + This does not artificially limit any operation. PATH_MAX is simply + used as a guesstimate for the expected maximal path length. + Buffers will be enlarged if necessary. */ +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +struct dir_data +{ + DIR *stream; + int streamfd; + char *content; +}; + +struct known_object +{ + dev_t dev; + INO_T ino; +}; + +struct ftw_data +{ + /* Array with pointers to open directory streams. */ + struct dir_data **dirstreams; + size_t actdir; + size_t maxdir; + + /* Buffer containing name of currently processed object. */ + char *dirbuf; + size_t dirbufsize; + + /* Passed as fourth argument to `nftw' callback. The `base' member + tracks the content of the `dirbuf'. */ + struct FTW ftw; + + /* Flags passed to `nftw' function. 0 for `ftw'. */ + int flags; + + /* Conversion array for flag values. It is the identity mapping for + `nftw' calls, otherwise it maps the values to those known by + `ftw'. */ + const int *cvt_arr; + + /* Callback function. We always use the `nftw' form. */ + NFTW_FUNC_T func; + + /* Device of starting point. Needed for FTW_MOUNT. */ + dev_t dev; + + /* Data structure for keeping fingerprints of already processed + object. This is needed when not using FTW_PHYS. */ + void *known_objects; +}; + + +/* Internally we use the FTW_* constants used for `nftw'. When invoked + as `ftw', map each flag to the subset of values used by `ftw'. */ +static const int nftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN +}; + +static const int ftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS +}; + + +static dir_notification_func_t upfunc; + +/* Forward declarations of local functions. */ +static int ftw_dir (struct ftw_data *data, struct STAT *st, + struct dir_data *old_dir) internal_function; + +typedef void (*__free_fn_t) (void *__nodep); +typedef struct node_t { + const void *key; + struct node_t *left; + struct node_t *right; + unsigned int red:1; +} *node; + +static void tdestroy_recurse (node root, __free_fn_t freefct) +{ + if (root->left != NULL) + tdestroy_recurse (root->left, freefct); + if (root->right != NULL) + tdestroy_recurse (root->right, freefct); + (*freefct) ((void *) root->key); + /* Free the node itself. */ + free (root); +} + +static void mytdestroy (void *vroot, __free_fn_t freefct) +{ + node root = (node) vroot; + + if (root != NULL) + tdestroy_recurse (root, freefct); +} + +static char *mystpcpy(char *a, const char *b) +{ + strcpy(a, b); + return (a + strlen(a)); +} + +static char *xgetcwd(void) +{ + char *cwd; + char *ret; + unsigned path_max; + + errno = 0; + path_max = (unsigned) PATH_MAX; + path_max += 2; /* The getcwd docs say to do this. */ + + cwd = malloc (path_max); + errno = 0; + while ((ret = getcwd (cwd, path_max)) == NULL && errno == ERANGE) { + path_max += 512; + cwd = realloc (cwd, path_max); + errno = 0; + } + + if (ret == NULL) { + int save_errno = errno; + free (cwd); + errno = save_errno; + return NULL; + } + return cwd; +} + +static int +object_compare (const void *p1, const void *p2) +{ + /* We don't need a sophisticated and useful comparison. We are only + interested in equality. However, we must be careful not to + accidentally compare `holes' in the structure. */ + const struct known_object *kp1 = p1, *kp2 = p2; + int cmp1; + cmp1 = (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino); + if (cmp1 != 0) + return cmp1; + return (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev); +} + + +static int +add_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object *newp = malloc (sizeof (struct known_object)); + if (newp == NULL) + return -1; + newp->dev = st->st_dev; + newp->ino = st->st_ino; + return __tsearch (newp, &data->known_objects, object_compare) ? 0 : -1; +} + + +static inline int +find_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object obj; + obj.dev = st->st_dev; + obj.ino = st->st_ino; + return __tfind (&obj, &data->known_objects, object_compare) != NULL; +} + + +static inline int +open_dir_stream (int *dfdp, struct ftw_data *data, struct dir_data *dirp) +{ + int result = 0; + + if (data->dirstreams[data->actdir] != NULL) + { + /* Oh, oh. We must close this stream. Get all remaining + entries and store them as a list in the `content' member of + the `struct dir_data' variable. */ + size_t bufsize = 1024; + char *buf = malloc (bufsize); + + if (buf == NULL) + result = -1; + else + { + DIR *st = data->dirstreams[data->actdir]->stream; + struct dirent64 *d; + size_t actsize = 0; + + while ((d = __readdir64 (st)) != NULL) + { + size_t this_len = NAMLEN (d); + if (actsize + this_len + 2 >= bufsize) + { + char *newp; + bufsize += MAX (1024, 2 * this_len); + newp = (char *) realloc (buf, bufsize); + if (newp == NULL) + { + /* No more memory. */ + int save_err = errno; + free (buf); + __set_errno (save_err); + return -1; + } + buf = newp; + } + + *((char *) __mempcpy (buf + actsize, d->d_name, this_len)) + = '\0'; + actsize += this_len + 1; + } + + /* Terminate the list with an additional NUL byte. */ + buf[actsize++] = '\0'; + + /* Shrink the buffer to what we actually need. */ + data->dirstreams[data->actdir]->content = realloc (buf, actsize); + if (data->dirstreams[data->actdir]->content == NULL) + { + int save_err = errno; + free (buf); + __set_errno (save_err); + result = -1; + } + else + { + __closedir (st); + data->dirstreams[data->actdir]->stream = NULL; + data->dirstreams[data->actdir]->streamfd = -1; + data->dirstreams[data->actdir] = NULL; + } + } + } + + /* Open the new stream. */ + if (result == 0) + { + assert (data->dirstreams[data->actdir] == NULL); + + if (dfdp != NULL && *dfdp != -1) + { + int fd = openat(*dfdp, data->dirbuf + data->ftw.base, O_RDONLY); + dirp->stream = NULL; + if (fd != -1 && (dirp->stream = fdopendir (fd)) == NULL) + close(fd); + } + else + { + const char *name; + + if (data->flags & FTW_CHDIR) + { + name = data->dirbuf + data->ftw.base; + if (name[0] == '\0') + name = "."; + } + else + name = data->dirbuf; + + dirp->stream = __opendir (name); + } + + if (dirp->stream == NULL) + result = -1; + else + { + dirp->streamfd = dirfd (dirp->stream); + dirp->content = NULL; + data->dirstreams[data->actdir] = dirp; + + if (++data->actdir == data->maxdir) + data->actdir = 0; + } + } + + return result; +} + + +static int +process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, size_t namlen) +{ + struct STAT st; + int result = 0; + int flag = 0; + size_t new_buflen; + + if (name[0] == '.' && (name[1] == '\0' + || (name[1] == '.' && name[2] == '\0'))) + /* Don't process the "." and ".." entries. */ + return 0; + + new_buflen = data->ftw.base + namlen + 2; + if (data->dirbufsize < new_buflen) + { + /* Enlarge the buffer. */ + char *newp; + + data->dirbufsize = 2 * new_buflen; + newp = (char *) realloc (data->dirbuf, data->dirbufsize); + if (newp == NULL) + return -1; + data->dirbuf = newp; + } + + *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; + + int statres; + if (dir->streamfd != -1) + statres = FXSTATAT (_STAT_VER, dir->streamfd, name, &st, + (data->flags & FTW_PHYS) ? AT_SYMLINK_NOFOLLOW : 0); + else + { + if ((data->flags & FTW_CHDIR) == 0) + name = data->dirbuf; + + statres = ((data->flags & FTW_PHYS) + ? LXSTAT (_STAT_VER, name, &st) + : XSTAT (_STAT_VER, name, &st)); + } + + if (statres < 0) + { + if (errno != EACCES && errno != ENOENT) + result = -1; + else if (data->flags & FTW_PHYS) + flag = FTW_NS; + else + { + if (dir->streamfd != -1) + statres = FXSTATAT (_STAT_VER, dir->streamfd, name, &st, + AT_SYMLINK_NOFOLLOW); + else + statres = LXSTAT (_STAT_VER, name, &st); + if (statres == 0 && S_ISLNK (st.st_mode)) + flag = FTW_SLN; + else + flag = FTW_NS; + } + } + else + { + if (S_ISDIR (st.st_mode)) + flag = FTW_D; + else if (S_ISLNK (st.st_mode)) + flag = FTW_SL; + else + flag = FTW_F; + } + + if (result == 0 + && (flag == FTW_NS + || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev)) + { + if (flag == FTW_D) + { + if ((data->flags & FTW_PHYS) + || (!find_object (data, &st) + /* Remember the object. */ + && (result = add_object (data, &st)) == 0)) + result = ftw_dir (data, &st, dir); + } + else + result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], + &data->ftw); + } + + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SUBTREE) + result = 0; + + return result; +} + + +static int +ftw_dir (struct ftw_data *data, struct STAT *st, struct dir_data *old_dir) +{ + struct dir_data dir; + struct dirent64 *d; + int previous_base = data->ftw.base; + int result; + char *startp; + + /* Open the stream for this directory. This might require that + another stream has to be closed. */ + result = open_dir_stream (old_dir == NULL ? NULL : &old_dir->streamfd, + data, &dir); + if (result != 0) + { + if (errno == EACCES) + /* We cannot read the directory. Signal this with a special flag. */ + result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw); + + return result; + } + + /* First, report the directory (if not depth-first). */ + if (!(data->flags & FTW_DEPTH)) + { + result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw); + if (result != 0) + { + int save_err; + fail: + save_err = errno; + __closedir (dir.stream); + dir.streamfd = -1; + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + return result; + } + } + + /* If necessary, change to this directory. */ + if (data->flags & FTW_CHDIR) + { + if (__fchdir (dirfd (dir.stream)) < 0) + { + result = -1; + goto fail; + } + } + + /* Next, update the `struct FTW' information. */ + ++data->ftw.level; + startp = data->dirbuf + strlen(data->dirbuf); + /* There always must be a directory name. */ + assert (startp != data->dirbuf); + if (startp[-1] != '/') + *startp++ = '/'; + data->ftw.base = startp - data->dirbuf; + + while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL) + { + result = process_entry (data, &dir, d->d_name, NAMLEN (d)); + if (result != 0) + break; + } + + if (dir.stream != NULL) + { + /* The stream is still open. I.e., we did not need more + descriptors. Simply close the stream now. */ + int save_err = errno; + + assert (dir.content == NULL); + + __closedir (dir.stream); + dir.streamfd = -1; + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + } + else + { + int save_err; + char *runp = dir.content; + + while (result == 0 && *runp != '\0') + { + char *endp = strchr (runp, '\0'); + + // XXX Should store the d_type values as well?! + result = process_entry (data, &dir, runp, endp - runp); + + runp = endp + 1; + } + + save_err = errno; + free (dir.content); + __set_errno (save_err); + } + + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS) + result = 0; + + /* Prepare the return, revert the `struct FTW' information. */ + data->dirbuf[data->ftw.base - 1] = '\0'; + --data->ftw.level; + if (upfunc) + (*upfunc)(); + data->ftw.base = previous_base; + + /* Finally, if we process depth-first report the directory. */ + if (result == 0 && (data->flags & FTW_DEPTH)) + result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw); + + if (old_dir + && (data->flags & FTW_CHDIR) + && (result == 0 + || ((data->flags & FTW_ACTIONRETVAL) + && (result != -1 && result != FTW_STOP)))) + { + /* Change back to the parent directory. */ + int done = 0; + if (old_dir->stream != NULL) + if (__fchdir (dirfd (old_dir->stream)) == 0) + done = 1; + + if (!done) + { + if (data->ftw.base == 1) + { + if (__chdir ("/") < 0) + result = -1; + } + else + if (__chdir ("..") < 0) + result = -1; + } + } + + return result; +} + + +static int ftw_startup (const char *dir, + int is_nftw, + void *func, + dir_notification_func_t up, + int descriptors, + int flags) +{ + struct ftw_data data; + struct STAT st; + int result = 0; + int save_err; + int cwdfd = -1; + char *cwd = NULL; + char *cp; + + upfunc = up; + + /* First make sure the parameters are reasonable. */ + if (dir[0] == '\0') + { + __set_errno (ENOENT); + return -1; + } + + data.maxdir = descriptors < 1 ? 1 : descriptors; + data.actdir = 0; + data.dirstreams = (struct dir_data **) alloca (data.maxdir + * sizeof (struct dir_data *)); + memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); + + /* PATH_MAX is always defined when we get here. */ + data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX); + data.dirbuf = (char *) malloc (data.dirbufsize); + if (data.dirbuf == NULL) + return -1; + cp = mystpcpy (data.dirbuf, dir); + /* Strip trailing slashes. */ + while (cp > data.dirbuf + 1 && cp[-1] == '/') + --cp; + *cp = '\0'; + + data.ftw.level = 0; + + /* Find basename. */ + while (cp > data.dirbuf && cp[-1] != '/') + --cp; + data.ftw.base = cp - data.dirbuf; + + data.flags = flags; + + /* This assignment might seem to be strange but it is what we want. + The trick is that the first three arguments to the `ftw' and + `nftw' callback functions are equal. Therefore we can call in + every case the callback using the format of the `nftw' version + and get the correct result since the stack layout for a function + call in C allows this. */ + data.func = (NFTW_FUNC_T) func; + + /* Since we internally use the complete set of FTW_* values we need + to reduce the value range before calling a `ftw' callback. */ + data.cvt_arr = is_nftw ? nftw_arr : ftw_arr; + + /* No object known so far. */ + data.known_objects = NULL; + + /* Now go to the directory containing the initial file/directory. */ + if (flags & FTW_CHDIR) + { + /* We have to be able to go back to the current working + directory. The best way to do this is to use a file + descriptor. */ + cwdfd = open (".", O_RDONLY); + if (cwdfd == -1) + { + /* Try getting the directory name. This can be needed if + the current directory is executable but not readable. */ + if (errno == EACCES) + /* GNU extension ahead. */ + cwd = __getcwd(NULL, 0); + + if (cwd == NULL) + goto out_fail; + } + else if (data.maxdir > 1) + /* Account for the file descriptor we use here. */ + --data.maxdir; + + if (data.ftw.base > 0) + { + /* Change to the directory the file is in. In data.dirbuf + we have a writable copy of the file name. Just NUL + terminate it for now and change the directory. */ + if (data.ftw.base == 1) + /* I.e., the file is in the root directory. */ + result = __chdir ("/"); + else + { + char ch = data.dirbuf[data.ftw.base - 1]; + data.dirbuf[data.ftw.base - 1] = '\0'; + result = __chdir (data.dirbuf); + data.dirbuf[data.ftw.base - 1] = ch; + } + } + } + + /* Get stat info for start directory. */ + if (result == 0) + { + const char *name; + + if (data.flags & FTW_CHDIR) + { + name = data.dirbuf + data.ftw.base; + if (name[0] == '\0') + name = "."; + } + else + name = data.dirbuf; + + if (((flags & FTW_PHYS) + ? LXSTAT (_STAT_VER, name, &st) + : XSTAT (_STAT_VER, name, &st)) < 0) + { + if (!(flags & FTW_PHYS) + && errno == ENOENT + && LXSTAT (_STAT_VER, name, &st) == 0 + && S_ISLNK (st.st_mode)) + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN], + &data.ftw); + else + /* No need to call the callback since we cannot say anything + about the object. */ + result = -1; + } + else + { + if (S_ISDIR (st.st_mode)) + { + /* Remember the device of the initial directory in case + FTW_MOUNT is given. */ + data.dev = st.st_dev; + + /* We know this directory now. */ + if (!(flags & FTW_PHYS)) + result = add_object (&data, &st); + + if (result == 0) + result = ftw_dir (&data, &st, NULL); + } + else + { + int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F; + + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag], + &data.ftw); + } + } + + if ((flags & FTW_ACTIONRETVAL) + && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS)) + result = 0; + } + + /* Return to the start directory (if necessary). */ + if (cwdfd != -1) + { + int save_err = errno; + __fchdir (cwdfd); + close(cwdfd); + __set_errno (save_err); + } + else if (cwd != NULL) + { + int save_err = errno; + __chdir (cwd); + free (cwd); + __set_errno (save_err); + } + + /* Free all memory. */ +out_fail: + save_err = errno; + mytdestroy (data.known_objects, free); + free (data.dirbuf); + __set_errno (save_err); + + return result; +} + + + +/* Entry points. */ +int NFTW_NAME(const char *path, + NFTW_FUNC_T func, + dir_notification_func_t up, + int descriptors, + int flags) +{ + return ftw_startup (path, 1, func, up, descriptors, flags); +} + diff --git a/libatalk/util/getiface.c b/libatalk/util/getiface.c new file mode 100644 index 0000000..bf79fff --- /dev/null +++ b/libatalk/util/getiface.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * Copyright (c) 1999-2000 Adrian Sun. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef TRU64 +#include +#include +#endif /* TRU64 */ +#include +#include + +#ifdef __svr4__ +#include +#endif + +#include + +/* allocation size for interface list. */ +#define IFACE_NUM 5 + +/* we leave all of the ioctl's to the application */ +static int addname(char **list, int *i, const char *name) + +{ + /* if we've run out of room, allocate some more. just return + * the present list if we can't. */ + + if ((list[*i] = strdup(name)) == NULL) + return -1; + + (*i)++; + list[*i] = NULL; /* zero out the next entry */ + return 0; +} + + +static int getifaces(const int sockfd, char ***list) +{ +#ifdef HAVE_IFNAMEINDEX + struct if_nameindex *ifstart, *ifs; + int i = 0; + char **new; + + ifs = ifstart = if_nameindex(); + + new = (char **) malloc((sizeof(ifs)/sizeof(struct if_nameindex) + 1) * sizeof(char *)); + while (ifs && ifs->if_name) { + /* just bail if there's a problem */ + if (addname(new, &i, ifs->if_name) < 0) + break; + ifs++; + } + + if_freenameindex(ifstart); + *list = new; + return i; + +#else + struct ifconf ifc; + struct ifreq ifrs[ 64 ], *ifr, *nextifr; + int ifrsize, i = 0; + char **new; + + if (!list) + return 0; + + memset( &ifc, 0, sizeof( struct ifconf )); + ifc.ifc_len = sizeof( ifrs ); + memset( ifrs, 0, sizeof( ifrs )); + ifc.ifc_buf = (caddr_t)ifrs; + if ( ioctl( sockfd, SIOCGIFCONF, &ifc ) < 0 ) { + return 0; + } + + new = (char **) malloc((ifc.ifc_len/sizeof(struct ifreq) + 1) * sizeof(char *)); + for ( ifr = ifc.ifc_req; ifc.ifc_len >= (int) sizeof( struct ifreq ); + ifc.ifc_len -= ifrsize, ifr = nextifr ) { +#ifdef BSD4_4 + ifrsize = sizeof(ifr->ifr_name) + + (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) + ? ifr->ifr_addr.sa_len : sizeof(struct sockaddr)); +#else /* !BSD4_4 */ + ifrsize = sizeof( struct ifreq ); +#endif /* BSD4_4 */ + nextifr = (struct ifreq *)((caddr_t)ifr + ifrsize ); + + /* just bail if there's a problem */ + if (addname(new, &i, ifr->ifr_name) < 0) + break; + } + *list = new; + return i; +#endif +} + + +/* + * Get interfaces from the kernel. we keep an extra null entry to signify + * the end of the interface list. + */ +char **getifacelist(void) +{ + char **list = NULL; /* FIXME */ + int i, fd; + + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) + return NULL; + + if ((i = getifaces(fd, &list)) == 0) { + free(list); + close(fd); + return NULL; + } + close(fd); + + return list; +} + + +/* go through and free the interface list */ +void freeifacelist(char **ifacelist) +{ + char *value, **list = ifacelist; + + if (!ifacelist) + return; + + while ((value = *list++)) { + free(value); + } + + free(ifacelist); +} diff --git a/libatalk/util/gettok.c b/libatalk/util/gettok.c new file mode 100644 index 0000000..4859fec --- /dev/null +++ b/libatalk/util/gettok.c @@ -0,0 +1,162 @@ +/* + * + * Copyright (c) 1990,1994 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include + +#include + +static char *l_curr; +static char *l_end; + +void initline( int len, char *line) +{ + l_curr = line; + l_end = line + len; +} + +#define ST_QUOTE 0 +#define ST_WORD 1 +#define ST_BEGIN 2 + +int +parseline(int len, char *token) +{ + char *p, *e; + int state; + + state = ST_BEGIN; + p = token; + e = token + len; + + for (;;) { + if ( l_curr > l_end ) { /* end of line */ + *token = '\0'; + return( -1 ); + } + + switch ( *l_curr ) { + case '"' : + if ( state == ST_QUOTE ) { + state = ST_WORD; + } else { + state = ST_QUOTE; + } + break; + + case '\0' : + case '\t' : + case '\n' : + case ' ' : + if ( state == ST_WORD ) { + *p = '\0'; + return( p - token ); + } + if ( state != ST_QUOTE ) { + break; + } + /* FALL THROUGH */ + + default : + if ( state == ST_BEGIN ) { + state = ST_WORD; + } + if ( p > e ) { /* end of token */ + *token = '\0'; + return( -1 ); + } + *p++ = *l_curr; + break; + } + + l_curr++; + } +} + +#ifdef notdef +void parseline(char *token, char *user) +{ + char *p = pos, *t = token, *u, *q, buf[ MAXPATHLEN ]; + struct passwd *pwent; + int quoted = 0; + + while ( isspace( *p )) { + p++; + } + + /* + * If we've reached the end of the line, or a comment, + * don't return any more tokens. + */ + if ( *p == '\0' || *p == '#' ) { + *token = '\0'; + return; + } + + if ( *p == '"' ) { + p++; + quoted = 1; + } + while ( *p != '\0' && ( quoted || !isspace( *p ))) { + if ( *p == '"' ) { + if ( quoted ) { + *t = '\0'; + break; + } + quoted = 1; + p++; + } else { + *t++ = *p++; + } + } + pos = p; + *t = '\0'; + + /* + * We got to the end of the line without closing an open quote + */ + if ( *p == '\0' && quoted ) { + *token = '\0'; + return; + } + + t = token; + if ( *t == '~' ) { + t++; + if ( *t == '\0' || *t == '/' ) { + u = user; + if ( *t == '/' ) { + t++; + } + } else { + u = t; + if (( q = strchr( t, '/' )) == NULL ) { + t = ""; + } else { + *q = '\0'; + t = q + 1; + } + } + if ( u == NULL || ( pwent = getpwnam( u )) == NULL ) { + *token = '\0'; + return; + } + strcpy( buf, pwent->pw_dir ); + if ( *t != '\0' ) { + strcat( buf, "/" ); + strcat( buf, t ); + } + strcpy( token, buf ); + } + return; +} +#endif /* notdef */ diff --git a/libatalk/util/locking.c b/libatalk/util/locking.c new file mode 100644 index 0000000..0b473b6 --- /dev/null +++ b/libatalk/util/locking.c @@ -0,0 +1,95 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +/*! + * @file + * Netatalk utility functions + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +/*! + * @def read_lock(fd, offset, whence, len) + * @brief place read lock on file + * + * @param fd (r) File descriptor + * @param offset (r) byte offset relative to l_whence + * @param whence (r) SEEK_SET, SEEK_CUR, SEEK_END + * @param len (r) no. of bytes (0 means to EOF) + * + * @returns 0 on success, -1 on failure with + * fcntl return value and errno + */ + +/*! + * @def write_lock(fd, offset, whence, len) + * @brief place write lock on file + * + * @param fd (r) File descriptor + * @param offset (r) byte offset relative to l_whence + * @param whence (r) SEEK_SET, SEEK_CUR, SEEK_END + * @param len (r) no. of bytes (0 means to EOF) + * + * @returns 0 on success, -1 on failure with + * fcntl return value and errno + */ + +/*! + * @def unlock(fd, offset, whence, len) + * @brief unlock a file + * + * @param fd (r) File descriptor + * @param offset (r) byte offset relative to l_whence + * @param whence (r) SEEK_SET, SEEK_CUR, SEEK_END + * @param len (r) no. of bytes (0 means to EOF) + * + * @returns 0 on success, -1 on failure with + * fcntl return value and errno + */ + +/*! + * @brief lock a file with fctnl + * + * This function is called via the macros: + * read_lock, write_lock, un_lock + * + * @param fd (r) File descriptor + * @param cmd (r) cmd to fcntl, only F_SETLK is usable here + * @param type (r) F_RDLCK, F_WRLCK, F_UNLCK + * @param offset (r) byte offset relative to l_whence + * @param whence (r) SEEK_SET, SEEK_CUR, SEEK_END + * @param len (r) no. of bytes (0 means to EOF) + * + * @returns 0 on success, -1 on failure with + * fcntl return value and errno + * + * @sa read_lock, write_lock, unlock + */ +int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) +{ + struct flock lock; + + lock.l_type = type; + lock.l_start = offset; + lock.l_whence = whence; + lock.l_len = len; + + return (fcntl(fd, cmd, &lock)); +} diff --git a/libatalk/util/logger.c b/libatalk/util/logger.c new file mode 100644 index 0000000..203abbd --- /dev/null +++ b/libatalk/util/logger.c @@ -0,0 +1,518 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* ========================================================================= + +logger.c was written by Simon Bazley (sibaz@sibaz.com) + +I believe libatalk is released under the L/GPL licence. +Just incase, it is, thats the licence I'm applying to this file. +Netatalk 2001 (c) + +========================================================================= */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define COUNT_ARRAY(array) (sizeof((array))/sizeof((array)[0])) + +#define MAXLOGSIZE 512 + +#define LOGLEVEL_STRING_IDENTIFIERS { \ + "-", \ + "severe", \ + "error", \ + "warn", \ + "note", \ + "info", \ + "debug", \ + "debug6", \ + "debug7", \ + "debug8", \ + "debug9", \ + "maxdebug"} + +/* these are the string identifiers corresponding to each logtype */ +#define LOGTYPE_STRING_IDENTIFIERS { \ + "Default", \ + "Logger", \ + "CNID", \ + "AFPDaemon", \ + "DSI", \ + "UAMS", \ + "FCE", \ + "ad", \ + "Spotlight", \ + "end_of_list_marker"} + +/* ========================================================================= + Config + ========================================================================= */ + +/* Main log config container */ +log_config_t log_config = { 0 }; + +/* Default log config: log nothing to files. + 0: set ? + 0: syslog ? + -1: logfiles fd + log_none: no logging by default + 0: Display options */ +#define DEFAULT_LOG_CONFIG {0, 0, -1, log_none, 0} + +UAM_MODULE_EXPORT logtype_conf_t type_configs[logtype_end_of_list_marker] = { + DEFAULT_LOG_CONFIG, /* logtype_default */ + DEFAULT_LOG_CONFIG, /* logtype_logger */ + DEFAULT_LOG_CONFIG, /* logtype_cnid */ + DEFAULT_LOG_CONFIG, /* logtype_afpd */ + DEFAULT_LOG_CONFIG, /* logtype_dsi */ + DEFAULT_LOG_CONFIG, /* logtype_uams */ + DEFAULT_LOG_CONFIG, /* logtype_fce */ + DEFAULT_LOG_CONFIG, /* logtype_ad */ + DEFAULT_LOG_CONFIG /* logtype_sl */ +}; + +static void syslog_setup(int loglevel, enum logtypes logtype, int display_options, int facility); + +/* These are used by the LOG macro to store __FILE__ and __LINE__ */ +static const char *log_src_filename; +static int log_src_linenumber; + +/* Array to store text to list given a log type */ +static const char *arr_logtype_strings[] = LOGTYPE_STRING_IDENTIFIERS; +static const unsigned int num_logtype_strings = COUNT_ARRAY(arr_logtype_strings); + +/* Array for charachters representing log severity in the log file */ +static const char arr_loglevel_chars[] = {'-','S', 'E', 'W', 'N', 'I', 'D'}; +static const unsigned int num_loglevel_chars = COUNT_ARRAY(arr_loglevel_chars); + +static const char *arr_loglevel_strings[] = LOGLEVEL_STRING_IDENTIFIERS; +static const unsigned int num_loglevel_strings = COUNT_ARRAY(arr_loglevel_strings); + +/* ========================================================================= + Internal function definitions + ========================================================================= */ + +static int generate_message(char **message_details_buffer, + char *user_message, + int display_options, + enum loglevels loglevel, + enum logtypes logtype) +{ + char *details; + int len; + struct timeval tv; + pid_t pid; + char buf[256]; + + gettimeofday(&tv, NULL); + strftime(buf, sizeof(buf), "%b %d %H:%M:%S.", localtime(&tv.tv_sec)); + pid = getpid(); + const char *basename = strrchr(log_src_filename, '/'); + if (basename) { + basename++; + } else { + basename = log_src_filename; + } + + + len = asprintf(&details, + "%s%06u %s[%d] {%s:%d} (%s:%s): %s\n", + buf, + (int)tv.tv_usec, + log_config.processname, + pid, + basename, + log_src_linenumber, + arr_loglevel_strings[loglevel], + arr_logtype_strings[logtype], + user_message); + if (len == -1) { + *message_details_buffer = ""; + return -1; + } + *message_details_buffer = details; + return len; +} + +static int get_syslog_equivalent(enum loglevels loglevel) +{ + switch (loglevel) + { + /* The question is we know how bad it is for us, + but how should that translate in the syslogs? */ + case 1: /* severe */ + return LOG_ERR; + case 2: /* error */ + return LOG_ERR; + case 3: /* warning */ + return LOG_WARNING; + case 4: /* note */ + return LOG_NOTICE; + case 5: /* information */ + return LOG_INFO; + default: /* debug */ + return LOG_DEBUG; + } +} + +/* Called by the LOG macro for syslog messages */ +static void make_syslog_entry(enum loglevels loglevel, enum logtypes logtype _U_, char *message) +{ + if ( !log_config.syslog_opened ) { + openlog(log_config.processname, + log_config.syslog_display_options, + log_config.syslog_facility); + log_config.syslog_opened = true; + } + + syslog(get_syslog_equivalent(loglevel), "%s", message); +} + +static void log_init(void) +{ + syslog_setup(log_info, + logtype_default, + logoption_ndelay | logoption_pid, + logfacility_daemon); +} + +static void log_setup(const char *filename, enum loglevels loglevel, enum logtypes logtype) +{ + if (loglevel == 0) { + /* Disable */ + if (type_configs[logtype].set) { + if (type_configs[logtype].fd != -1) + close(type_configs[logtype].fd); + type_configs[logtype].fd = -1; + type_configs[logtype].level = -1; + type_configs[logtype].set = false; + + /* if disabling default also set all "default using" levels to 0 */ + if (logtype == logtype_default) { + while (logtype != logtype_end_of_list_marker) { + if ( ! (type_configs[logtype].set)) + type_configs[logtype].level = -1; + logtype++; + } + } + } + return; + } + + /* Safety check */ + if (NULL == filename) + return; + + /* Resetting existing config ? */ + if (type_configs[logtype].set) { + if (type_configs[logtype].fd != -1) + close(type_configs[logtype].fd); + type_configs[logtype].fd = -1; + type_configs[logtype].level = -1; + type_configs[logtype].set = false; + type_configs[logtype].syslog = false; + + /* Reset configs using default */ + if (logtype == logtype_default) { + int typeiter = 0; + while (typeiter != logtype_end_of_list_marker) { + if (type_configs[typeiter].set == false) { + type_configs[typeiter].level = -1; + type_configs[typeiter].syslog = false; + } + typeiter++; + } + } + } + + /* Set new values */ + type_configs[logtype].level = loglevel; + + /* Open log file as OPEN_LOGS_AS_UID*/ + + /* Is it /dev/tty ? */ + if (strcmp(filename, "/dev/tty") == 0) { + type_configs[logtype].fd = 1; /* stdout */ + + /* Does it end in "XXXXXX" ? debug reguest via SIGINT */ + } else if (strcmp(filename + strlen(filename) - 6, "XXXXXX") == 0) { + char *tmp = strdup(filename); + type_configs[logtype].fd = mkstemp(tmp); + free(tmp); + + } else { + become_root(); + type_configs[logtype].fd = open(filename, + O_CREAT | O_WRONLY | O_APPEND, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + unbecome_root(); + } + + /* Check for error opening/creating logfile */ + if (type_configs[logtype].fd == -1) { + type_configs[logtype].level = -1; + type_configs[logtype].set = false; + return; + } + + fcntl(type_configs[logtype].fd, F_SETFD, FD_CLOEXEC); + type_configs[logtype].set = true; + log_config.inited = true; + + /* Here's how we make it possible to LOG to a logtype like "logtype_afpd" */ + /* which then uses the default logtype setup if it isn't setup itself: */ + /* we just copy the loglevel from default to all logtypes that are not setup. */ + /* In "make_log_entry" we then check for the logtypes if they arent setup */ + /* and use default then. We must provide accessible values for all logtypes */ + /* in order to make it easy and fast to check the loglevels in the LOG macro! */ + + if (logtype == logtype_default) { + int typeiter = 0; + while (typeiter != logtype_end_of_list_marker) { + if ( ! (type_configs[typeiter].set)) + type_configs[typeiter].level = loglevel; + typeiter++; + } + } + + LOG(log_debug, logtype_logger, "Setup file logging: type: %s, level: %s, file: %s", + arr_logtype_strings[logtype], arr_loglevel_strings[loglevel], filename); +} + +/* Setup syslog logging */ +static void syslog_setup(int loglevel, enum logtypes logtype, int display_options, int facility) +{ + /* + * FIXME: + * this currently doesn't care if logtype is already logging to a file. + * Fortunately currently there's no way a user could trigger this as afpd.conf + * is not re-read on SIGHUP. + */ + + type_configs[logtype].level = loglevel; + type_configs[logtype].set = true; + type_configs[logtype].syslog = true; + log_config.syslog_display_options = display_options; + log_config.syslog_facility = facility; + + /* Setting default logging? Then set all logtype not set individually */ + if (logtype == logtype_default) { + int typeiter = 0; + while (typeiter != logtype_end_of_list_marker) { + if ( ! (type_configs[typeiter].set)) { + type_configs[typeiter].level = loglevel; + type_configs[typeiter].syslog = true; + } + typeiter++; + } + } + + log_config.inited = 1; + + LOG(log_info, logtype_logger, "Set syslog logging to level: %s", + arr_loglevel_strings[loglevel]); +} + +/* + * If filename == NULL its for syslog logging, otherwise its for file-logging. + * "unsetuplog" calls with loglevel == NULL. + * loglevel == NULL means: + * if logtype == default + * disable logging + * else + * set to default logging + */ +static void setuplog_internal(const char *loglevel, const char *logtype, const char *filename) +{ + unsigned int typenum, levelnum; + + /* Parse logtype */ + for( typenum=0; typenum < num_logtype_strings; typenum++) { + if (strcasecmp(logtype, arr_logtype_strings[typenum]) == 0) + break; + } + if (typenum >= num_logtype_strings) { + return; + } + + /* Parse loglevel */ + if (loglevel == NULL) { + levelnum = 0; + } else { + for(levelnum=1; levelnum < num_loglevel_strings; levelnum++) { + if (strcasecmp(loglevel, arr_loglevel_strings[levelnum]) == 0) + break; + } + if (levelnum >= num_loglevel_strings) { + return; + } + } + + /* is this a syslog setup or a filelog setup ? */ + if (filename == NULL) { + /* must be syslog */ + syslog_setup(levelnum, + typenum, + logoption_ndelay | logoption_pid, + logfacility_daemon); + } else { + /* this must be a filelog */ + log_setup(filename, levelnum, typenum); + } + + return; +} + +/* ========================================================================= + Global function definitions + ========================================================================= */ + +/* This function sets up the processname */ +void set_processname(const char *processname) +{ + strncpy(log_config.processname, processname, 15); + log_config.processname[15] = 0; +} + +/* ------------------------------------------------------------------------- + make_log_entry has 1 main flaws: + The message in its entirity, must fit into the tempbuffer. + So it must be shorter than MAXLOGSIZE + ------------------------------------------------------------------------- */ +void make_log_entry(enum loglevels loglevel, enum logtypes logtype, + const char *file, int line, char *message, ...) +{ + /* fn is not reentrant but is used in signal handler + * with LOGGER it's a little late source name and line number + * are already changed. */ + static int inlog = 0; + int fd, len; + char *user_message, *log_message; + va_list args; + + if (inlog) + return; + + inlog = 1; + + if (!log_config.inited) { + log_init(); + } + + if (type_configs[logtype].syslog) { + if (type_configs[logtype].level >= loglevel) { + /* Initialise the Messages and send it to syslog */ + va_start(args, message); + len = vasprintf(&user_message, message, args); + va_end(args); + if (len == -1) { + return; + } + make_syslog_entry(loglevel, logtype, user_message); + free(user_message); + } + inlog = 0; + return; + } + + /* logging to a file */ + + log_src_filename = file; + log_src_linenumber = line; + + /* Check if requested logtype is setup */ + if (type_configs[logtype].set) { + /* Yes */ + fd = type_configs[logtype].fd; + } else { + /* No: use default */ + fd = type_configs[logtype_default].fd; + } + + if (fd < 0) { + /* no where to send the output, give up */ + goto exit; + } + + /* Initialise the Messages */ + va_start(args, message); + len = vasprintf(&user_message, message, args); + if (len == -1) { + goto exit; + } + va_end(args); + + len = generate_message(&log_message, + user_message, + type_configs[logtype].set ? + type_configs[logtype].display_options : + type_configs[logtype_default].display_options, + loglevel, logtype); + if (len == -1) { + goto exit; + } + write(fd, log_message, len); + free(log_message); + free(user_message); + +exit: + inlog = 0; +} + +void setuplog(const char *logstr, const char *logfile) +{ + char *ptr, *save; + char *logtype, *loglevel; + char c; + + save = ptr = strdup(logstr); + + ptr = strtok(ptr, ", "); + + while (ptr) { + while (*ptr) { + while (*ptr && isspace(*ptr)) + ptr++; + + logtype = ptr; + ptr = strpbrk(ptr, ":"); + if (!ptr) + break; + *ptr = 0; + + ptr++; + loglevel = ptr; + while (*ptr && !isspace(*ptr)) + ptr++; + c = *ptr; + *ptr = 0; + setuplog_internal(loglevel, logtype, logfile); + *ptr = c; + } + ptr = strtok(NULL, ", "); + } + + free(save); +} + diff --git a/libatalk/util/module.c b/libatalk/util/module.c new file mode 100644 index 0000000..b651476 --- /dev/null +++ b/libatalk/util/module.c @@ -0,0 +1,71 @@ +/* + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include + +#ifndef HAVE_DLFCN_H +#ifdef MACOSX_SERVER +#include + +void *mod_open(const char *path) +{ + NSObjectFileImage file; + + if (NSCreateObjectFileImageFromFile(path, &file) != + NSObjectFileImageSuccess) + return NULL; + return NSLinkModule(file, path, TRUE); +} + +void *mod_symbol(void *module, const char *name) +{ + NSSymbol symbol; + char *underscore; + + if ((underscore = (char *) malloc(strlen(name) + 2)) == NULL) + return NULL; + strcpy(underscore, "_"); + strcat(underscore, name); + symbol = NSLookupAndBindSymbol(underscore); + free(underscore); + + return NSAddressOfSymbol(symbol); +} + +void mod_close(void *module) +{ + NSUnLinkModule(module, FALSE); +} +#endif /* MACOSX_SERVER */ + +#else /* HAVE_DLFCN_H */ + +#include + +#ifdef DLSYM_PREPEND_UNDERSCORE +void *mod_symbol(void *module, const char *name) +{ + void *symbol; + char *underscore; + + if (!module) + return NULL; + + if ((underscore = (char *) malloc(strlen(name) + 2)) == NULL) + return NULL; + + strcpy(underscore, "_"); + strcat(underscore, name); + symbol = dlsym(module, underscore); + free(underscore); + + return symbol; +} +#endif /* DLSYM_PREPEND_UNDERSCORE */ +#endif /* HAVE_DLFCN_H */ diff --git a/libatalk/util/netatalk_conf.c b/libatalk/util/netatalk_conf.c new file mode 100644 index 0000000..3953d28 --- /dev/null +++ b/libatalk/util/netatalk_conf.c @@ -0,0 +1,2170 @@ +/* + Copyright (c) 2012 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_LOCALE_H +#include +#endif +#if HAVE_LANGINFO_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VOLPASSLEN 8 +#ifndef UUID_PRINTABLE_STRING_LENGTH +#define UUID_PRINTABLE_STRING_LENGTH 37 +#endif + +#define IS_VAR(a, b) (strncmp((a), (b), 2) == 0) + +/************************************************************** + * Locals + **************************************************************/ + +static int have_uservol = 0; /* whether there's generic user home share in config ("~" or "~/path", but not "~user") */ +static struct vol *Volumes = NULL; +static uint16_t lastvid = 0; + +/* + * Get a volumes UUID from the config file. + * If there is none, it is generated and stored there. + * + * Returns pointer to allocated storage on success, NULL on error. + */ +static char *get_vol_uuid(const AFPObj *obj, const char *volname) +{ + char *volname_conf; + char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p; + FILE *fp; + struct stat tmpstat; + int fd; + + if ((fp = fopen(obj->options.uuidconf, "r")) != NULL) { /* read open? */ + /* scan in the conf file */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + p = buf; + while (p && isblank(*p)) + p++; + if (!p || (*p == '#') || (*p == '\n')) + continue; /* invalid line */ + if (*p == '"') { + p++; + if ((volname_conf = strtok( p, "\"" )) == NULL) + continue; /* syntax error */ + } else { + if ((volname_conf = strtok( p, " \t" )) == NULL) + continue; /* syntax error: invalid name */ + } + p = strchr(p, '\0'); + p++; + if (*p == '\0') + continue; /* syntax error */ + + if (strcmp(volname, volname_conf) != 0) + continue; /* another volume name */ + + while (p && isblank(*p)) + p++; + + if (sscanf(p, "%36s", uuid) == 1 ) { + for (int i=0; uuid[i]; i++) + uuid[i] = toupper(uuid[i]); + LOG(log_debug, logtype_afpd, "get_uuid('%s'): UUID: '%s'", volname, uuid); + fclose(fp); + return strdup(uuid); + } + } + } + + if (fp) + fclose(fp); + + /* not found or no file, reopen in append mode */ + + if (stat(obj->options.uuidconf, &tmpstat)) { /* no file */ + if (( fd = creat(obj->options.uuidconf, 0644 )) < 0 ) { + LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s).", + obj->options.uuidconf, strerror(errno)); + return NULL; + } + if (( fp = fdopen( fd, "w" )) == NULL ) { + LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s).", + obj->options.uuidconf, strerror(errno)); + close(fd); + return NULL; + } + } else if ((fp = fopen(obj->options.uuidconf, "a+")) == NULL) { /* not found */ + LOG(log_error, logtype_afpd, "Cannot create or append to %s (%s).", + obj->options.uuidconf, strerror(errno)); + return NULL; + } + fseek(fp, 0L, SEEK_END); + if(ftell(fp) == 0) { /* size = 0 */ + fprintf(fp, "# DON'T TOUCH NOR COPY THOUGHTLESSLY!\n"); + fprintf(fp, "# This file is auto-generated by afpd\n"); + fprintf(fp, "# and stores UUIDs for Time Machine volumes.\n\n"); + } else { + fseek(fp, -1L, SEEK_END); + if(fgetc(fp) != '\n') fputc('\n', fp); /* last char is \n? */ + } + + /* generate uuid and write to file */ + atalk_uuid_t id; + const char *cp; + randombytes((void *)id, 16); + cp = uuid_bin2string(id); + + LOG(log_debug, logtype_afpd, "get_uuid('%s'): generated UUID '%s'", volname, cp); + + fprintf(fp, "\"%s\"\t%36s\n", volname, cp); + fclose(fp); + + return strdup(cp); +} + +/* + Check if the underlying filesystem supports EAs. + If not, switch to ea:ad. + As we can't check (requires write access) on ro-volumes, we switch ea:auto + volumes that are options:ro to ea:none. +*/ +#define EABUFSZ 4 +static int do_check_ea_support(const struct vol *vol) +{ + int haseas; + const char *eaname = "org.netatalk.has-Extended-Attributes"; + const char *eacontent = "yes"; + char buf[EABUFSZ]; + + if (sys_lgetxattr(vol->v_path, eaname, buf, EABUFSZ) != -1) + return 1; + + if (vol->v_flags & AFPVOL_RO) { + LOG(log_debug, logtype_afpd, "read-only volume '%s', can't test for EA support, assuming yes", vol->v_localname); + return 1; + } + + become_root(); + + if ((sys_setxattr(vol->v_path, eaname, eacontent, strlen(eacontent) + 1, 0)) == 0) { + haseas = 1; + } else { + LOG(log_warning, logtype_afpd, "volume \"%s\" does not support Extended Attributes or read-only volume", + vol->v_localname); + haseas = 0; + } + + unbecome_root(); + + return haseas; +} + +static void check_ea_support(struct vol *vol) +{ + int haseas; + + haseas = do_check_ea_support(vol); + + if (vol->v_vfs_ea == AFPVOL_EA_AUTO) { + if (haseas) + vol->v_vfs_ea = AFPVOL_EA_SYS; + else + vol->v_vfs_ea = AFPVOL_EA_NONE; + } + + if (vol->v_adouble == AD_VERSION_EA) { + if (!haseas) + vol->v_adouble = AD_VERSION2; + } +} + +/*! + * Check whether a volume supports ACLs + * + * @param vol (r) volume + * + * @returns 0 if not, 1 if yes + */ +static int check_vol_acl_support(const struct vol *vol) +{ + int ret = 0; + +#ifdef HAVE_NFSV4_ACLS + ace_t *aces = NULL; + ret = 1; + if (get_nfsv4_acl(vol->v_path, &aces) == -1) + ret = 0; +#endif +#ifdef HAVE_POSIX_ACLS + acl_t acl = NULL; + ret = 1; + if ((acl = acl_get_file(vol->v_path, ACL_TYPE_ACCESS)) == NULL) + ret = 0; +#endif + +#ifdef HAVE_NFSV4_ACLS + if (aces) free(aces); +#endif +#ifdef HAVE_POSIX_ACLS + if (acl) acl_free(acl); +#endif /* HAVE_POSIX_ACLS */ + + LOG(log_debug, logtype_afpd, "Volume \"%s\" ACL support: %s", + vol->v_path, ret ? "yes" : "no"); + return ret; +} + +/* + * Handle variable substitutions. here's what we understand: + * $b -> basename of path + * $c -> client ip/appletalk address + * $d -> volume pathname on server + * $f -> full name (whatever's in the gecos field) + * $g -> group + * $h -> hostname + * $i -> client ip/appletalk address without port + * $s -> server name (hostname if it doesn't exist) + * $u -> username (guest is usually nobody) + * $v -> volume name or basename if null + * $$ -> $ + * + * This get's called from readvolfile with + * path = NULL, volname = NULL for xlating the volumes path + * path = path, volname = NULL for xlating the volumes name + * ... and from volumes options parsing code when xlating eg dbpath with + * path = path, volname = volname + * + * Using this information we can reject xlation of any variable depeninding on a login + * context which is not given in the afp master, where we must evaluate this whole stuff + * too for the Zeroconf announcements. + */ +static char *volxlate(const AFPObj *obj, + char *dest, + size_t destlen, + const char *src, + const struct passwd *pwd, + const char *path, + const char *volname) +{ + char *p, *r; + const char *q; + int len; + char *ret; + int xlatevolname = 0; + + if (path && !volname) + /* cf above */ + xlatevolname = 1; + + if (!src) { + return NULL; + } + if (!dest) { + dest = calloc(destlen +1, 1); + } + ret = dest; + if (!ret) { + return NULL; + } + strlcpy(dest, src, destlen +1); + if ((p = strchr(src, '$')) == NULL) /* nothing to do */ + return ret; + + /* first part of the path. just forward to the next variable. */ + len = MIN((size_t)(p - src), destlen); + if (len > 0) { + destlen -= len; + dest += len; + } + + while (p && destlen > 0) { + /* now figure out what the variable is */ + q = NULL; + if (IS_VAR(p, "$b")) { + if (path) { + if ((q = strrchr(path, '/')) == NULL) + q = path; + else if (*(q + 1) != '\0') + q++; + } + } else if (IS_VAR(p, "$c")) { + if (IS_AFP_SESSION(obj)) { + DSI *dsi = obj->dsi; + len = sprintf(dest, "%s:%u", + getip_string((struct sockaddr *)&dsi->client), + getip_port((struct sockaddr *)&dsi->client)); + dest += len; + destlen -= len; + } + } else if (IS_VAR(p, "$d")) { + q = path; + } else if (pwd && IS_VAR(p, "$f")) { + if ((r = strchr(pwd->pw_gecos, ','))) + *r = '\0'; + q = pwd->pw_gecos; + } else if (pwd && IS_VAR(p, "$g")) { + struct group *grp = getgrgid(pwd->pw_gid); + if (grp) + q = grp->gr_name; + } else if (IS_VAR(p, "$h")) { + q = obj->options.hostname; + } else if (IS_VAR(p, "$i")) { + DSI *dsi = obj->dsi; + q = getip_string((struct sockaddr *)&dsi->client); + } else if (IS_VAR(p, "$s")) { + q = obj->options.hostname; + } else if (obj->username[0] && IS_VAR(p, "$u")) { + char* sep = NULL; + if ( obj->options.ntseparator && (sep = strchr(obj->username, obj->options.ntseparator[0])) != NULL) + q = sep+1; + else + q = obj->username; + } else if (IS_VAR(p, "$v")) { + if (volname) { + q = volname; + } + else if (path) { + if ((q = strrchr(path, '/')) == NULL) + q = path; + else if (*(q + 1) != '\0') + q++; + } + } else if (IS_VAR(p, "$$")) { + q = "$"; + } else + q = p; + + /* copy the stuff over. if we don't understand something that we + * should, just skip it over. */ + if (q) { + len = MIN(p == q ? 2 : strlen(q), destlen); + strncpy(dest, q, len); + dest += len; + destlen -= len; + } + + /* stuff up to next $ */ + src = p + 2; + p = strchr(src, '$'); + len = p ? MIN((size_t)(p - src), destlen) : destlen; + if (len > 0) { + strncpy(dest, src, len); + dest += len; + destlen -= len; + } + } + return ret; +} + +/*! + * check access list + * + * this function wants a string consisting of names seperated by comma + * or space. Names may be quoted within a pair of quotes. Groups are + * denoted by a leading @ symbol. + * Example: + * user1 user2, user3, @group1 @group2, @group3 "user name1", "@group name1" + * A NULL argument allows everybody to have access. + * We return three things: + * -1: no list + * 0: list exists, but name isn't in it + * 1: in list + */ +static int accessvol(const AFPObj *obj, const char *args, const char *name) +{ + EC_INIT; + char *names = NULL, *p; + struct group *gr; + + if (!args) + EC_EXIT_STATUS(-1); + + EC_NULL_LOG( names = strdup(args) ); + + if ((p = strtok_quote(names, ", ")) == NULL) /* nothing, return okay */ + EC_EXIT_STATUS(-1); + + while (p) { + if (*p == '@') { /* it's a group */ + if ((gr = getgrnam(p + 1)) && gmem(gr->gr_gid, obj->ngroups, obj->groups)) + EC_EXIT_STATUS(1); + } else if (strcasecmp(p, name) == 0) /* it's a user name */ + EC_EXIT_STATUS(1); + p = strtok_quote(NULL, ", "); + } + +EC_CLEANUP: + if (names) + free(names); + EC_EXIT; +} + +static int hostaccessvol(const AFPObj *obj, const char *volname, const char *args) +{ + int mask_int; + char buf[MAXPATHLEN + 1], *p, *b; + struct sockaddr_storage client; + const DSI *dsi = obj->dsi; + + if (!args || !dsi) + return -1; + + strlcpy(buf, args, sizeof(buf)); + if ((p = strtok_r(buf, ", ", &b)) == NULL) /* nothing, return okay */ + return -1; + + while (p) { + int ret; + char *ipaddr, *mask_char; + struct addrinfo hints, *ai; + + ipaddr = strtok(p, "/"); + mask_char = strtok(NULL,"/"); + + /* Get address from string with getaddrinfo */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if ((ret = getaddrinfo(ipaddr, NULL, &hints, &ai)) != 0) { + LOG(log_error, logtype_afpd, "hostaccessvol: getaddrinfo: %s\n", gai_strerror(ret)); + continue; + } + + /* netmask */ + if (mask_char != NULL) + mask_int = atoi(mask_char); /* apply_ip_mask does range checking on it */ + else { + if (ai->ai_family == AF_INET) /* IPv4 */ + mask_int = 32; + else /* IPv6 */ + mask_int = 128; + } + + /* Apply mask to addresses */ + client = dsi->client; + apply_ip_mask((struct sockaddr *)&client, mask_int); + apply_ip_mask(ai->ai_addr, mask_int); + + if (compare_ip((struct sockaddr *)&client, ai->ai_addr) == 0) { + freeaddrinfo(ai); + return 1; + } + + /* next address */ + freeaddrinfo(ai); + p = strtok_r(NULL, ", ", &b); + } + + return 0; +} + +/*! + * Get option string from config, use default value if not set + * + * @param conf (r) config handle + * @param vol (r) volume name (must be section name ie wo vars expanded) + * @param opt (r) option + * @param defsec (r) if "option" is not found in "vol", try to find it in section "defsec" + * @param defval (r) if neither "vol" nor "defsec" contain "opt" return "defval" + * + * @returns const option string from "vol" or "defsec", or "defval" if not found + */ +static const char *getoption(const dictionary *conf, const char *vol, const char *opt, const char *defsec, const char *defval) +{ + const char *result; + + if ((!(result = atalk_iniparser_getstring(conf, vol, opt, NULL))) && (defsec != NULL)) + result = atalk_iniparser_getstring(conf, defsec, opt, NULL); + + if (result == NULL) + result = defval; + return result; +} + +/*! + * Get boolean option from config, use default value if not set + * + * @param conf (r) config handle + * @param vol (r) volume name (must be section name ie wo vars expanded) + * @param opt (r) option + * @param defsec (r) if "option" is not found in "vol", try to find it in section "defsec" + * @param defval (r) if neither "vol" nor "defsec" contain "opt" return "defval" + * + * @returns const option string from "vol" or "defsec", or "defval" if not found + */ +static int getoption_bool(const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval) +{ + int result; + + if (((result = atalk_iniparser_getboolean(conf, vol, opt, -1)) == -1) && (defsec != NULL)) + result = atalk_iniparser_getboolean(conf, defsec, opt, -1); + + if (result == -1) + result = defval; + return result; +} + +/*! + * Get boolean option from volume, default section or global - use default value if not set + * + * Order of precedence: volume -> default section -> global -> default value + * + * "vdg" means volume, default section or global + * + * @param conf (r) config handle + * @param vol (r) volume name (must be section name ie wo vars expanded) + * @param opt (r) option + * @param defsec (r) if "option" is not found in "vol", try to find it in section "defsec" + * @param defval (r) if neither "vol" nor "defsec" contain "opt" return "defval" + * + * @returns const option string from "vol" or "defsec", or "defval" if not found + */ +static int vdgoption_bool(const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval) +{ + int result; + + result = atalk_iniparser_getboolean(conf, vol, opt, -1); + + if ((result == -1) && (defsec != NULL)) + result = atalk_iniparser_getboolean(conf, defsec, opt, -1); + + if (result == -1) + result = atalk_iniparser_getboolean(conf, INISEC_GLOBAL, opt, defval); + + return result; +} + +/*! + * Create volume struct + * + * @param obj (r) handle + * @param pwd (r) struct passwd of logged in user, may be NULL in master afpd + * @param section (r) volume name wo variables expanded (exactly as in iniconfig) + * @param name (r) volume name + * @param path_in (r) volume path + * @param preset (r) default preset, may be NULL + * @returns vol on success, NULL on error + */ +static struct vol *creatvol(AFPObj *obj, + const struct passwd *pwd, + const char *section, + const char *name, + const char *path_in, + const char *preset) +{ + EC_INIT; + struct vol *volume = NULL; + int i, suffixlen, vlen, tmpvlen, u8mvlen, macvlen; + char tmpname[AFPVOL_U8MNAMELEN+1]; + char path[MAXPATHLEN + 1]; + ucs2_t u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2]; + char suffix[6]; /* max is #FFFF */ + uint16_t flags; + const char *val; + char *p, *q; + bstring dbpath = NULL; + bstring global_path_tmp = NULL; + + strlcpy(path, path_in, MAXPATHLEN); + + LOG(log_debug, logtype_afpd, "creatvol(volume: '%s', path: \"%s\", preset: '%s'): BEGIN", + name, path, preset ? preset : "-"); + + if ( name == NULL || *name == '\0' ) { + if ((name = strrchr( path, '/' )) == NULL) + EC_FAIL; + /* if you wish to share /, you need to specify a name. */ + if (*++name == '\0') + EC_FAIL; + } + + /* Once volumes are loaded, we never change options again, we just delete em when they're removed from afp.conf */ + + for (struct vol *vol = Volumes; vol; vol = vol->v_next) { + if (STRCMP(name, ==, vol->v_localname) && vol->v_deleted) { + /* + * reloading config, volume still present, nothing else to do, + * we don't change options for volumes once they're loaded + */ + vol->v_deleted = 0; + volume = vol; + EC_EXIT_STATUS(0); + } + if (STRCMP(path, ==, vol->v_path)) { + LOG(log_note, logtype_afpd, "volume \"%s\" path \"%s\" is the same as volumes \"%s\" path", + name, path, vol->v_configname); + EC_EXIT_STATUS(0); + } + /* + * We could check for nested volume paths here, but + * nobody was able to come up with an implementation yet, + * that is simple, fast and correct. + */ + } + + /* + * Check allow/deny lists: + * allow -> either no list (-1), or in list (1) + * deny -> either no list (-1), or not in list (0) + */ + if (pwd) { + if (accessvol(obj, getoption(obj->iniconfig, section, "invalid users", preset, NULL), pwd->pw_name) == 1) + goto EC_CLEANUP; + if (accessvol(obj, getoption(obj->iniconfig, section, "valid users", preset, NULL), pwd->pw_name) == 0) + goto EC_CLEANUP; + if (hostaccessvol(obj, section, getoption(obj->iniconfig, section, "hosts deny", preset, NULL)) == 1) + goto EC_CLEANUP; + if (hostaccessvol(obj, section, getoption(obj->iniconfig, section, "hosts allow", preset, NULL)) == 0) + goto EC_CLEANUP; + } + + EC_NULL( volume = calloc(1, sizeof(struct vol)) ); + + EC_NULL( volume->v_configname = strdup(section)); + + volume->v_vfs_ea = AFPVOL_EA_AUTO; + volume->v_umask = obj->options.umask; + + if ((val = getoption(obj->iniconfig, section, "password", preset, NULL))) + EC_NULL( volume->v_password = strdup(val) ); + + if ((val = getoption(obj->iniconfig, section, "veto files", preset, NULL))) + EC_NULL( volume->v_veto = strdup(val) ); + + /* vol charset is in [G] and [V] */ + if ((val = getoption(obj->iniconfig, section, "vol charset", preset, NULL))) { + if (strcasecmp(val, "UTF-8") == 0) { + val = strdup("UTF8"); + } + EC_NULL( volume->v_volcodepage = strdup(val) ); + } + else + EC_NULL( volume->v_volcodepage = strdup(obj->options.volcodepage) ); + + /* mac charset is in [G] and [V] */ + if ((val = getoption(obj->iniconfig, section, "mac charset", preset, NULL))) { + if (strncasecmp(val, "MAC", 3) != 0) { + LOG(log_warning, logtype_afpd, "Is '%s' really mac charset? ", val); + } + EC_NULL( volume->v_maccodepage = strdup(val) ); + } + else + EC_NULL( volume->v_maccodepage = strdup(obj->options.maccodepage) ); + + vlen = strlen(name); + strlcpy(tmpname, name, sizeof(tmpname)); + for(i = 0; i < vlen; i++) + if(tmpname[i] == '/') tmpname[i] = ':'; + + + if (atalk_iniparser_getboolean(obj->iniconfig, INISEC_GLOBAL, "vol dbnest", 0)) { + EC_NULL( volume->v_dbpath = strdup(path) ); + } else { + char *global_path; + val = getoption(obj->iniconfig, section, "vol dbpath", preset, NULL); + if (val == NULL) { + /* check global option */ + global_path = atalk_iniparser_getstring(obj->iniconfig, + INISEC_GLOBAL, + "vol dbpath", + NULL); + if (global_path) { + /* check for pre 3.1.1 behaviour without variable */ + if (strchr(global_path, '$') == NULL) { + global_path_tmp = bformat("%s/%s/", global_path, tmpname); + val = cfrombstr(global_path_tmp); + } else { + val = global_path; + } + } + } + + if (val == NULL) { + EC_NULL( dbpath = bformat("%s/%s/", _PATH_STATEDIR "CNID/", tmpname) ); + } else { + EC_NULL( dbpath = bfromcstr(val)); + } + EC_NULL( volume->v_dbpath = volxlate(obj, NULL, MAXPATHLEN + 1, + cfrombstr(dbpath), pwd, NULL, tmpname) ); + } + + if ((val = getoption(obj->iniconfig, section, "cnid scheme", preset, NULL))) + EC_NULL( volume->v_cnidscheme = strdup(val) ); + else + volume->v_cnidscheme = strdup(DEFAULT_CNID_SCHEME); + + if ((val = getoption(obj->iniconfig, section, "umask", preset, NULL))) + volume->v_umask = (int)strtol(val, NULL, 8); + + if ((val = getoption(obj->iniconfig, section, "directory perm", preset, NULL))) + volume->v_dperm = (int)strtol(val, NULL, 8); + + if ((val = getoption(obj->iniconfig, section, "file perm", preset, NULL))) + volume->v_fperm = (int)strtol(val, NULL, 8); + + if ((val = getoption(obj->iniconfig, section, "vol size limit", preset, NULL))) + volume->v_limitsize = (uint32_t)strtoul(val, NULL, 10); + + if ((val = getoption(obj->iniconfig, section, "preexec", preset, NULL))) + EC_NULL( volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) ); + + if ((val = getoption(obj->iniconfig, section, "postexec", preset, NULL))) + EC_NULL( volume->v_postexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) ); + + if ((val = getoption(obj->iniconfig, section, "root preexec", preset, NULL))) + EC_NULL( volume->v_root_preexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) ); + + if ((val = getoption(obj->iniconfig, section, "root postexec", preset, NULL))) + EC_NULL( volume->v_root_postexec = volxlate(obj, NULL, MAXPATHLEN, val, pwd, path, name) ); + + if ((val = getoption(obj->iniconfig, section, "appledouble", preset, NULL))) { + if (strcmp(val, "v2") == 0) + volume->v_adouble = AD_VERSION2; + else if (strcmp(val, "ea") == 0) + volume->v_adouble = AD_VERSION_EA; + } else { + volume->v_adouble = AD_VERSION; + } + + if ((val = getoption(obj->iniconfig, section, "cnid server", preset, NULL))) { + EC_NULL( p = strdup(val) ); + volume->v_cnidserver = p; + if ((q = strrchr(val, ':'))) { + *q++ = 0; + volume->v_cnidport = strdup(q); + } else { + volume->v_cnidport = strdup("4700"); + } + + } else { + volume->v_cnidserver = strdup(obj->options.Cnid_srv); + volume->v_cnidport = strdup(obj->options.Cnid_port); + } + + if ((val = getoption(obj->iniconfig, section, "ea", preset, NULL))) { + if (strcasecmp(val, "ad") == 0) + volume->v_vfs_ea = AFPVOL_EA_AD; + else if (strcasecmp(val, "sys") == 0) + volume->v_vfs_ea = AFPVOL_EA_SYS; + else if (strcasecmp(val, "none") == 0) + volume->v_vfs_ea = AFPVOL_EA_NONE; + } + + if ((val = getoption(obj->iniconfig, section, "casefold", preset, NULL))) { + if (strcasecmp(val, "tolower") == 0) + volume->v_casefold = AFPVOL_UMLOWER; + else if (strcasecmp(val, "toupper") == 0) + volume->v_casefold = AFPVOL_UMUPPER; + else if (strcasecmp(val, "xlatelower") == 0) + volume->v_casefold = AFPVOL_UUPPERMLOWER; + else if (strcasecmp(val, "xlateupper") == 0) + volume->v_casefold = AFPVOL_ULOWERMUPPER; + } + if (getoption_bool(obj->iniconfig, section, "case sensitive", preset, 1)) + volume->v_casefold |= AFPVOL_CASESENS; + + if (getoption_bool(obj->iniconfig, section, "read only", preset, 0)) + volume->v_flags |= AFPVOL_RO; + if (getoption_bool(obj->iniconfig, section, "invisible dots", preset, 0)) + volume->v_flags |= AFPVOL_INV_DOTS; + if (!getoption_bool(obj->iniconfig, section, "stat vol", preset, 1)) + volume->v_flags |= AFPVOL_NOSTAT; + if (getoption_bool(obj->iniconfig, section, "unix priv", preset, 1)) + volume->v_flags |= AFPVOL_UNIX_PRIV; + if (!getoption_bool(obj->iniconfig, section, "cnid dev", preset, 1)) + volume->v_flags |= AFPVOL_NODEV; + if (getoption_bool(obj->iniconfig, section, "illegal seq", preset, 0)) + volume->v_flags |= AFPVOL_EILSEQ; + if (getoption_bool(obj->iniconfig, section, "time machine", preset, 0)) + volume->v_flags |= AFPVOL_TM; + if (getoption_bool(obj->iniconfig, section, "search db", preset, 0)) + volume->v_flags |= AFPVOL_SEARCHDB; + if (!getoption_bool(obj->iniconfig, section, "network ids", preset, 1)) + volume->v_flags |= AFPVOL_NONETIDS; +#ifdef HAVE_ACLS + if (getoption_bool(obj->iniconfig, section, "acls", preset, 1)) + volume->v_flags |= AFPVOL_ACLS; +#endif + if (!getoption_bool(obj->iniconfig, section, "convert appledouble", preset, 1)) + volume->v_flags |= AFPVOL_NOV2TOEACONV; + if (getoption_bool(obj->iniconfig, section, "follow symlinks", preset, 0)) + volume->v_flags |= AFPVOL_FOLLOWSYM; + if (getoption_bool(obj->iniconfig, section, "spotlight", preset, obj->options.flags & OPTION_SPOTLIGHT_VOL)) { + volume->v_flags |= AFPVOL_SPOTLIGHT; + obj->options.flags |= OPTION_SPOTLIGHT; + } + if (getoption_bool(obj->iniconfig, section, "delete veto files", preset, 0)) + volume->v_flags |= AFPVOL_DELVETO; + + if (getoption_bool(obj->iniconfig, section, "preexec close", preset, 0)) + volume->v_preexec_close = 1; + if (getoption_bool(obj->iniconfig, section, "root preexec close", preset, 0)) + volume->v_root_preexec_close = 1; + if (vdgoption_bool(obj->iniconfig, section, "force xattr with sticky bit", preset, 0)) + volume->v_flags |= AFPVOL_FORCE_STICKY_XATTR; + + if ((val = getoption(obj->iniconfig, section, "ignored attributes", preset, obj->options.ignored_attr))) { + if (strstr(val, "all")) { + volume->v_ignattr |= ATTRBIT_NOWRITE | ATTRBIT_NORENAME | ATTRBIT_NODELETE; + } + if (strstr(val, "nowrite")) { + volume->v_ignattr |= ATTRBIT_NOWRITE; + } + if (strstr(val, "norename")) { + volume->v_ignattr |= ATTRBIT_NORENAME; + } + if (strstr(val, "nodelete")) { + volume->v_ignattr |= ATTRBIT_NODELETE; + } + } + + val = getoption(obj->iniconfig, section, "chmod request", preset, NULL); + if (val == NULL) { + val = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "chmod request", "preserve"); + } + if (strcasecmp(val, "ignore") == 0) { + volume->v_flags |= AFPVOL_CHMOD_IGNORE; + } else if (strcasecmp(val, "preserve") == 0) { + volume->v_flags |= AFPVOL_CHMOD_PRESERVE_ACL; + } else if (strcasecmp(val, "simple") != 0) { + LOG(log_warning, logtype_afpd, "unknown 'chmod request' setting: '%s', using default", val); + volume->v_flags |= AFPVOL_CHMOD_PRESERVE_ACL; + } + + /* + * Handle read-only behaviour. semantics: + * 1) neither the rolist nor the rwlist exist -> rw + * 2) rolist exists -> ro if user is in it. + * 3) rwlist exists -> ro unless user is in it. + * 4) cnid scheme = last -> ro forcibly. + */ + if (pwd) { + if (accessvol(obj, getoption(obj->iniconfig, section, "rolist", preset, NULL), pwd->pw_name) == 1 + || accessvol(obj, getoption(obj->iniconfig, section, "rwlist", preset, NULL), pwd->pw_name) == 0) + volume->v_flags |= AFPVOL_RO; + } + if (0 == strcmp(volume->v_cnidscheme, "last")) + volume->v_flags |= AFPVOL_RO; + + if ((volume->v_flags & AFPVOL_NODEV)) + volume->v_ad_options |= ADVOL_NODEV; + if ((volume->v_flags & AFPVOL_UNIX_PRIV)) + volume->v_ad_options |= ADVOL_UNIXPRIV; + if ((volume->v_flags & AFPVOL_INV_DOTS)) + volume->v_ad_options |= ADVOL_INVDOTS; + if ((volume->v_flags & AFPVOL_FOLLOWSYM)) + volume->v_ad_options |= ADVOL_FOLLO_SYML; + if ((volume->v_flags & AFPVOL_RO)) + volume->v_ad_options |= ADVOL_RO; + if ((volume->v_flags & AFPVOL_FORCE_STICKY_XATTR)) + volume->v_ad_options |= ADVOL_FORCE_STICKY_XATTR; + + /* Mac to Unix conversion flags*/ + if ((volume->v_flags & AFPVOL_EILSEQ)) + volume->v_mtou_flags |= CONV__EILSEQ; + + if ((volume->v_casefold & AFPVOL_MTOUUPPER)) + volume->v_mtou_flags |= CONV_TOUPPER; + else if ((volume->v_casefold & AFPVOL_MTOULOWER)) + volume->v_mtou_flags |= CONV_TOLOWER; + + /* Unix to Mac conversion flags*/ + volume->v_utom_flags = CONV_IGNORE; + if ((volume->v_casefold & AFPVOL_UTOMUPPER)) + volume->v_utom_flags |= CONV_TOUPPER; + else if ((volume->v_casefold & AFPVOL_UTOMLOWER)) + volume->v_utom_flags |= CONV_TOLOWER; + if ((volume->v_flags & AFPVOL_EILSEQ)) + volume->v_utom_flags |= CONV__EILSEQ; + + /* suffix for mangling use (lastvid + 1) */ + /* because v_vid has not been decided yet. */ + suffixlen = sprintf(suffix, "#%X", lastvid + 1 ); + + /* Unicode Volume Name */ + /* Firstly convert name from unixcharset to UTF8-MAC */ + flags = CONV_IGNORE; + tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags); + if (tmpvlen <= 0) { + strcpy(tmpname, "???"); + tmpvlen = 3; + } + + /* Do we have to mangle ? */ + if ( (flags & CONV_REQMANGLE) || (tmpvlen > obj->options.volnamelen)) { + if (tmpvlen + suffixlen > obj->options.volnamelen) { + flags = CONV_FORCE; + tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, obj->options.volnamelen - suffixlen, &flags); + tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0; + } + strcat(tmpname, suffix); + tmpvlen = strlen(tmpname); + } + + /* Secondly convert name from UTF8-MAC to UCS2 */ + if ( 0 >= ( u8mvlen = convert_string(CH_UTF8_MAC, CH_UCS2, tmpname, tmpvlen, u8mtmpname, AFPVOL_U8MNAMELEN*2)) ) + EC_FAIL; + + LOG(log_maxdebug, logtype_afpd, "creatvol: Volume '%s' -> UTF8-MAC Name: '%s'", name, tmpname); + + /* Maccharset Volume Name */ + /* Firsty convert name from unixcharset to maccharset */ + flags = CONV_IGNORE; + tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags); + if (tmpvlen <= 0) { + strcpy(tmpname, "???"); + tmpvlen = 3; + } + + /* Do we have to mangle ? */ + if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) { + if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) { + flags = CONV_FORCE; + tmpvlen = convert_charset(obj->options.unixcharset, + obj->options.maccharset, + 0, + name, + vlen, + tmpname, + AFPVOL_MACNAMELEN - suffixlen, + &flags); + tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0; + } + strcat(tmpname, suffix); + tmpvlen = strlen(tmpname); + } + + /* Secondly convert name from maccharset to UCS2 */ + if ( 0 >= ( macvlen = convert_string(obj->options.maccharset, + CH_UCS2, + tmpname, + tmpvlen, + mactmpname, + AFPVOL_U8MNAMELEN*2)) ) + EC_FAIL; + + LOG(log_maxdebug, logtype_afpd, "creatvol: Volume '%s' -> Longname: '%s'", name, tmpname); + + EC_NULL( volume->v_localname = strdup(name) ); + EC_NULL( volume->v_u8mname = strdup_w(u8mtmpname) ); + EC_NULL( volume->v_macname = strdup_w(mactmpname) ); + EC_NULL( volume->v_path = strdup(path) ); + + volume->v_name = utf8_encoding(obj) ? volume->v_u8mname : volume->v_macname; + +#ifdef __svr4__ + volume->v_qfd = -1; +#endif /* __svr4__ */ + + /* os X start at 1 and use network order ie. 1 2 3 */ + volume->v_vid = ++lastvid; + volume->v_vid = htons(volume->v_vid); + +#ifdef HAVE_ACLS + if (!check_vol_acl_support(volume)) { + LOG(log_debug, logtype_afpd, "creatvol(\"%s\"): disabling ACL support", volume->v_path); + volume->v_flags &= ~AFPVOL_ACLS; + } +#endif + + /* Check EA support on volume */ + if (volume->v_vfs_ea == AFPVOL_EA_AUTO || volume->v_adouble == AD_VERSION_EA) + check_ea_support(volume); + initvol_vfs(volume); + + /* get/store uuid from file in afpd master*/ + become_root(); + char *uuid = get_vol_uuid(obj, volume->v_localname); + unbecome_root(); + if (!uuid) { + LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID", + volume->v_localname); + } else { + volume->v_uuid = uuid; + LOG(log_debug, logtype_afpd, "Volume '%s': UUID '%s'", + volume->v_localname, volume->v_uuid); + } + + /* no errors shall happen beyond this point because the cleanup would mess the volume chain up */ + volume->v_next = Volumes; + Volumes = volume; + volume->v_obj = obj; + +EC_CLEANUP: + LOG(log_debug, logtype_afpd, "creatvol: END: %d", ret); + if (dbpath) + bdestroy(dbpath); + if (global_path_tmp) + bdestroy(global_path_tmp); + if (ret != 0) { + if (volume) + volume_free(volume); + return NULL; + } + return volume; +} + +/* ---------------------- + */ +static int volfile_changed(AFPObj *obj) +{ + struct stat st; + struct afp_options *p = &obj->options; + int result; + const char *includefile; + + result = stat(p->configfile, &st); + if (result != 0) { + LOG(log_debug, logtype_afpd, "where is the config file %s ?", + p->configfile); + /* + * We return 1 which means "config file changed". The caller + * will re-read config and fail too which is what we want. + */ + return 1; + } + + if (st.st_mtime > p->volfile.mtime) { + p->volfile.mtime = st.st_mtime; + return 1; + } + + includefile = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, + "include", NULL); + if (includefile) { + result = stat(includefile, &st); + if (result != 0) { + LOG(log_debug, logtype_afpd, "where is the include file %s ?", + includefile); + return 1; + } + + if (st.st_mtime > p->includefile.mtime) { + p->includefile.mtime = st.st_mtime; + return 1; + } + } + + return 0; +} + +static int vol_section(const char *sec) +{ + if (STRCMP(sec, ==, INISEC_GLOBAL)) + return 0; + return 1; +} + +#define MAXPRESETLEN 100 +/*! + * Read volumes from iniconfig and add the volumes contained within to + * the global volume list. This gets called from the forked afpd childs. + * The master now reads this too for Zeroconf announcements. + */ +static int readvolfile(AFPObj *obj, const struct passwd *pwent) +{ + EC_INIT; + static int regexerr = -1; + static regex_t reg; + char *realvolpath; + char volname[AFPVOL_U8MNAMELEN + 1]; + char path[MAXPATHLEN + 1], tmp[MAXPATHLEN + 1]; + const char *preset, *default_preset, *p, *basedir; + int i; + regmatch_t match[1]; + + LOG(log_debug, logtype_afpd, "readvolfile: BEGIN"); + + int secnum = atalk_iniparser_getnsec(obj->iniconfig); + LOG(log_debug, logtype_afpd, "readvolfile: sections: %d", secnum); + const char *secname; + + if ((default_preset = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol preset", NULL))) { + LOG(log_debug, logtype_afpd, "readvolfile: default_preset: %s", default_preset); + } + + for (i = 0; i < secnum; i++) { + secname = atalk_iniparser_getsecname(obj->iniconfig, i); + + if (!vol_section(secname)) + continue; + if (STRCMP(secname, ==, INISEC_HOMES)) { + have_uservol = 1; + if (!IS_AFP_SESSION(obj) + || strcmp(obj->username, obj->options.guest) == 0) + /* not an AFP session, but cnid daemon, dbd or ad util, or guest login */ + continue; + if (pwent->pw_dir == NULL || STRCMP("", ==, pwent->pw_dir)) { + LOG(log_debug, logtype_afpd, "readvolfile: pwent->pw_dir: NULL or \"\" - no user home"); + continue; + } + LOG(log_debug, logtype_afpd, "readvolfile: pwent->pw_dir: '%s'", pwent->pw_dir); + + if ((realpath(pwent->pw_dir, tmp)) == NULL) { + LOG(log_debug, logtype_afpd, "readvolfile: Cannot get realpath '%s' (%s).", pwent->pw_dir, strerror(errno)); + continue; + } + LOG(log_debug, logtype_afpd, "readvolfile: realpath pwent->pw_dir: '%s'", tmp); + + /* check if user home matches our "basedir regex" */ + if ((basedir = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL) { + LOG(log_error, logtype_afpd, "\"basedir regex =\" must be defined in [Homes] section"); + continue; + } + LOG(log_debug, logtype_afpd, "readvolfile: basedir regex: '%s'", basedir); + + if (regexerr != 0 && (regexerr = regcomp(®, basedir, REG_EXTENDED)) != 0) { + char errbuf[1024]; + regerror(regexerr, ®, errbuf, sizeof(errbuf)); + LOG(log_debug, logtype_default, "readvolfile: bad basedir regex: %s", errbuf); + continue; + } + + if (regexec(®, tmp, 1, match, 0) == REG_NOMATCH) { + LOG(log_error, logtype_default, "readvolfile: user home \"%s\" doesn't match basedir regex \"%s\"", + tmp, basedir); + continue; + } + + if ((p = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) { + strlcat(tmp, "/", MAXPATHLEN); + strlcat(tmp, p, MAXPATHLEN); + } + } else { + /* Get path */ + if ((p = atalk_iniparser_getstring(obj->iniconfig, secname, "path", NULL)) == NULL) + continue; + strlcpy(tmp, p, MAXPATHLEN); + } + + if (volxlate(obj, path, sizeof(path) - 1, tmp, pwent, NULL, NULL) == NULL) + continue; + + /* do variable substitution for volume name */ + if (STRCMP(secname, ==, INISEC_HOMES)) { + p = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home"); + if (strstr(p, "$u") == NULL) { + LOG(log_warning, logtype_afpd, "home name must contain $u."); + p = "$u's home"; + } + if (strchr(p, ':') != NULL) { + LOG(log_warning, logtype_afpd, "home name must not contain \":\"."); + p = "$u's home"; + } + strlcpy(tmp, p, MAXPATHLEN); + } else { + strlcpy(tmp, secname, AFPVOL_U8MNAMELEN); + } + if (volxlate(obj, volname, sizeof(volname) - 1, tmp, pwent, path, NULL) == NULL) + continue; + + preset = atalk_iniparser_getstring(obj->iniconfig, secname, "vol preset", NULL); + + if ((realvolpath = realpath_safe(path)) == NULL) + continue; + + creatvol(obj, pwent, secname, volname, realvolpath, preset ? preset : default_preset ? default_preset : NULL); + free(realvolpath); + } + +// EC_CLEANUP: + EC_EXIT; +} + +static struct extmap *Extmap = NULL, *Defextmap = NULL; +static int Extmap_cnt; + +static int setextmap(char *ext, char *type, char *creator) +{ + EC_INIT; + struct extmap *em; + int cnt; + + if (Extmap == NULL) { + EC_NULL_LOG( Extmap = calloc(1, sizeof( struct extmap )) ); + } + + ext++; + + for (em = Extmap, cnt = 0; em->em_ext; em++, cnt++) + if ((strdiacasecmp(em->em_ext, ext)) == 0) + goto EC_CLEANUP; + + EC_NULL_LOG( Extmap = realloc(Extmap, sizeof(struct extmap) * (cnt + 2)) ); + (Extmap + cnt + 1)->em_ext = NULL; + em = Extmap + cnt; + + EC_NULL( em->em_ext = strdup(ext) ); + + if ( *type == '\0' ) { + memcpy(em->em_type, "\0\0\0\0", sizeof( em->em_type )); + } else { + memcpy(em->em_type, type, sizeof( em->em_type )); + } + if ( *creator == '\0' ) { + memcpy(em->em_creator, "\0\0\0\0", sizeof( em->em_creator )); + } else { + memcpy(em->em_creator, creator, sizeof( em->em_creator )); + } + +EC_CLEANUP: + EC_EXIT; +} + +/* -------------------------- */ +static int extmap_cmp(const void *map1, const void *map2) +{ + const struct extmap *em1 = map1; + const struct extmap *em2 = map2; + return strdiacasecmp(em1->em_ext, em2->em_ext); +} + +static void sortextmap( void) +{ + struct extmap *em; + + Extmap_cnt = 0; + if ((em = Extmap) == NULL) { + return; + } + while (em->em_ext) { + em++; + Extmap_cnt++; + } + if (Extmap_cnt) { + qsort(Extmap, Extmap_cnt, sizeof(struct extmap), extmap_cmp); + if (*Extmap->em_ext == 0) { + /* the first line is really "." the default entry, + * we remove the leading '.' in setextmap + */ + Defextmap = Extmap; + } + } +} + +static void free_extmap( void) +{ + struct extmap *em; + + if (Extmap) { + for ( em = Extmap; em->em_ext; em++) { + free (em->em_ext); + } + free(Extmap); + Extmap = NULL; + Defextmap = Extmap; + Extmap_cnt = 0; + } +} + +static int ext_cmp_key(const void *key, const void *obj) +{ + const char *p = key; + const struct extmap *em = obj; + return strdiacasecmp(p, em->em_ext); +} + +struct extmap *getextmap(const char *path) +{ + char *p; + struct extmap *em; + + if (!Extmap_cnt || NULL == ( p = strrchr( path, '.' )) ) { + return( Defextmap ); + } + p++; + if (!*p) { + return( Defextmap ); + } + em = bsearch(p, Extmap, Extmap_cnt, sizeof(struct extmap), ext_cmp_key); + if (em) { + return( em ); + } else { + return( Defextmap ); + } +} + +struct extmap *getdefextmap(void) +{ + return( Defextmap ); +} + +static int readextmap(const char *file) +{ + EC_INIT; + FILE *fp; + char ext[256]; + char buf[256]; + char type[5], creator[5]; + + LOG(log_debug, logtype_afpd, "readextmap: loading \"%s\"", file); + + EC_NULL_LOGSTR( fp = fopen(file, "r"), "Couldn't open extension maping file %s", file); + + while (fgets(buf, sizeof(buf), fp) != NULL) { + initline(strlen(buf), buf); + parseline(sizeof(ext) - 1, ext); + + switch (ext[0]) { + case '.' : + parseline(sizeof(type) - 1, type); + parseline(sizeof(creator) - 1, creator); + setextmap(ext, type, creator); + LOG(log_debug, logtype_afpd, "readextmap: mapping: '%s' -> %s/%s", ext, type, creator); + break; + } + } + + sortextmap(); + EC_ZERO( fclose(fp) ); + + LOG(log_debug, logtype_afpd, "readextmap: done", file); + +EC_CLEANUP: + EC_EXIT; +} + +/************************************************************** + * API functions + **************************************************************/ + +/*! + * Remove a volume from the linked list of volumes + */ +void volume_unlink(struct vol *volume) +{ + struct vol *vol, *ovol, *nvol; + + if (volume == Volumes) { + Volumes = NULL; + return; + } + for ( vol = Volumes->v_next, ovol = Volumes; vol; vol = nvol) { + nvol = vol->v_next; + + if (vol == volume) { + ovol->v_next = nvol; + break; + } + else { + ovol = vol; + } + } +} + +/*! + * Free all resources allocated in a struct vol in load_volumes() + * + * Actually opening a volume (afp_openvol()) will allocate additional + * ressources which are freed in closevol() + */ +void volume_free(struct vol *vol) +{ + free(vol->v_configname); + free(vol->v_localname); + free(vol->v_u8mname); + free(vol->v_macname); + free(vol->v_path); + free(vol->v_password); + free(vol->v_veto); + free(vol->v_volcodepage); + free(vol->v_maccodepage); + free(vol->v_cnidscheme); + free(vol->v_dbpath); + free(vol->v_gvs); + free(vol->v_uuid); + free(vol->v_cnidserver); + free(vol->v_cnidport); + free(vol->v_preexec); + free(vol->v_root_preexec); + free(vol->v_postexec); + free(vol->v_root_postexec); + + free(vol); +} + +/*! + * Load charsets for a volume + */ +int load_charset(struct vol *vol) +{ + if ((vol->v_maccharset = add_charset(vol->v_maccodepage)) == (charset_t)-1) { + LOG(log_error, logtype_default, "Setting mac charset '%s' failed", vol->v_maccodepage); + return -1; + } + + if ((vol->v_volcharset = add_charset(vol->v_volcodepage)) == (charset_t)-1) { + LOG(log_error, logtype_default, "Setting vol charset '%s' failed", vol->v_volcodepage); + return -1; + } + + return 0; +} + +/*! + * Initialize volumes and load ini configfile + * + * @param obj (r) handle + * @param flags (r) flags controlling volume load behaviour + */ +int load_volumes(AFPObj *obj, lv_flags_t flags) +{ + EC_INIT; + + static long bufsize; + static char *pwbuf = NULL; + + int fd = -1; + struct passwd pwent; + struct passwd *pwresult = NULL; + struct stat st; + int retries = 0; + struct vol *vol; + char *includefile; + + LOG(log_debug, logtype_afpd, "load_volumes: BEGIN"); + + if (pwbuf == NULL) { + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) /* Value was indeterminate */ + bufsize = 16384; /* Should be more than enough */ + EC_NULL( pwbuf = malloc(bufsize) ); + } + + if (!(flags & lv_all) && obj->uid) { + ret = getpwuid_r(obj->uid, &pwent, pwbuf, bufsize, &pwresult); + if (pwresult == NULL) { + LOG(log_error, logtype_afpd, "load_volumes: getpwuid_r: %s", strerror(errno)); + EC_FAIL; + } + pwresult = &pwent; + } + + if (Volumes) { + if (!(flags & lv_force) && !volfile_changed(obj)) + goto EC_CLEANUP; + have_uservol = 0; + for (vol = Volumes; vol; vol = vol->v_next) { + vol->v_deleted = 1; + } + if (obj->uid && pwresult) { + become_root(); + ret = set_groups(obj, pwresult); + unbecome_root(); + if (ret != 0) { + LOG(log_error, logtype_afpd, "load_volumes: set_groups: %s", strerror(errno)); + EC_FAIL; + } + } + } else { + LOG(log_debug, logtype_afpd, "load_volumes: no volumes yet"); + EC_ZERO_LOG( lstat(obj->options.configfile, &st) ); + obj->options.volfile.mtime = st.st_mtime; + + includefile = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, + "include", NULL); + if (includefile) { + EC_ZERO_LOG( stat(includefile, &st) ); + obj->options.includefile.mtime = st.st_mtime; + } + } + + /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */ + + fd = open(obj->options.configfile, O_RDONLY); + + while (retries < 2) { + if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) { + retries++; + if (!retries) { + LOG(log_error, logtype_afpd, "readvolfile: can't lock configfile \"%s\"", + obj->options.configfile); + EC_FAIL; + } + sleep(1); + continue; + } + break; + } + + if (obj->iniconfig) + atalk_iniparser_freedict(obj->iniconfig); + LOG(log_debug, logtype_afpd, "load_volumes: loading: %s", obj->options.configfile); + obj->iniconfig = atalk_iniparser_load(obj->options.configfile); + + EC_ZERO_LOG( readvolfile(obj, pwresult) ); + + struct vol *nextvol, *prevvol; + + vol = Volumes; + prevvol = NULL; + + while (vol) { + if (vol->v_deleted && !(vol->v_flags & AFPVOL_OPEN)) { + LOG(log_debug, logtype_afpd, "load_volumes: deleted: %s", vol->v_localname); + nextvol = vol->v_next; + if (prevvol) { + prevvol->v_next = vol->v_next; + } else { + Volumes = nextvol; + } + volume_free(vol); + vol = nextvol; + continue; + } + prevvol = vol; + vol = vol->v_next; + } + +EC_CLEANUP: + if (fd != -1) + (void)close(fd); + + LOG(log_debug, logtype_afpd, "load_volumes: END"); + EC_EXIT; +} + +void unload_volumes(AFPObj *obj) +{ + struct vol *vol, *p; + + LOG(log_debug, logtype_afpd, "unload_volumes: BEGIN"); + + p = Volumes; + while (p) { + vol = p; + p = vol->v_next; + volume_free(vol); + } + Volumes = NULL; + obj->options.volfile.mtime = 0; + + LOG(log_debug, logtype_afpd, "unload_volumes: END"); +} + +struct vol *getvolumes(void) +{ + return Volumes; +} + +struct vol *getvolbyvid(const uint16_t vid ) +{ + struct vol *vol; + + for ( vol = Volumes; vol; vol = vol->v_next ) { + if ( vid == vol->v_vid ) { + break; + } + } + if ( vol == NULL || ( vol->v_flags & AFPVOL_OPEN ) == 0 ) { + return( NULL ); + } + + return( vol ); +} + +/* + * get username by path + * + * getvolbypath() assumes that the user home directory has the same name as the username. + * If that is not true, getuserbypath() is called and tries to retrieve the username + * from the directory owner, checking its validity. + * + * @param path (r) absolute volume path + * @returns NULL if no match is found, pointer to username if successfull + * + */ +static char *getuserbypath(const char *path) +{ + EC_INIT; + struct stat sbuf; + struct passwd *pwd; + char *hdir = NULL; + + LOG(log_debug, logtype_afpd, "getuserbypath(\"%s\")", path); + + /* does folder exists? */ + if (stat(path, &sbuf) != 0) + EC_FAIL; + + /* get uid of dir owner */ + if ((pwd = getpwuid(sbuf.st_uid)) == NULL) + EC_FAIL; + + /* does user home directory exists? */ + if (stat(pwd->pw_dir, &sbuf) != 0) + EC_FAIL; + + /* resolve and remove symlinks */ + if ((hdir = realpath_safe(pwd->pw_dir)) == NULL) + EC_FAIL; + + /* handle subdirectories, path = */ + if (strncmp(path, hdir, strlen(hdir)) != 0) + EC_FAIL; + + LOG(log_debug, logtype_afpd, "getuserbypath: match user: %s, home: %s, realhome: %s", + pwd->pw_name, pwd->pw_dir, hdir); + +EC_CLEANUP: + if (hdir) + free(hdir); + if (ret != 0) + return NULL; + return pwd->pw_name; +} +/*! + * Search volume by path, creating user home vols as necessary + * + * Path may be absolute or relative. Ordinary volume structs are created when + * the ini config is initially parsed (load_volumes()), but user volumes are + * as load_volumes() only can create the user volume of the logged in user + * in an AFP session in afpd, but not when called from eg cnid_metad or dbd. + * Both cnid_metad and dbd thus need a way to lookup and create struct vols + * for user home by path. This is what this func does as well. + * + * (1) Search "normal" volume list + * (2) Check if theres a [Homes] section, load_volumes() remembers this for us + * (3) If there is, match "path" with "basedir regex" to get the user home parent dir + * (4) Built user home path by appending the basedir matched in (3) and appending the username + * (5) The next path element then is the username + * (5b) getvolbypath() assumes that the user home directory has the same name as the username. + * If that is not true, getuserbypath() is called and tries to retrieve the username + * from the directory owner, checking its validity + * (6) Append [Homes]->path subdirectory if defined + * (7) Create volume + * + * @param obj (rw) handle + * @param path (r) path, may be relative or absolute + */ +struct vol *getvolbypath(AFPObj *obj, const char *path) +{ + EC_INIT; + static int regexerr = -1; + static regex_t reg; + struct vol *vol; + struct vol *tmp; + const struct passwd *pw; + char volname[AFPVOL_U8MNAMELEN + 1]; + char *realabspath = NULL; + char volpath[MAXPATHLEN + 1], *realvolpath = NULL; + char tmpbuf[MAXPATHLEN + 1]; + const char *secname, *basedir, *p = NULL, *subpath = NULL, *subpathconfig; + char *user = NULL, *prw; + regmatch_t match[1]; + + LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\")", path); + + /* build absolute path */ + EC_NULL( realabspath = realpath_safe(path) ); + path = realabspath; + + for (tmp = Volumes; tmp; tmp = tmp->v_next) { /* (1) */ + size_t v_path_len = strlen(tmp->v_path); + if (strncmp(path, tmp->v_path, v_path_len) == 0) { + if (v_path_len < strlen(path) && path[v_path_len] != '/') { + LOG(log_debug, logtype_afpd, "getvolbypath: path(\"%s\") != volume(\"%s\")", path, tmp->v_path); + } else { + LOG(log_debug, logtype_afpd, "getvolbypath: path(\"%s\") == volume(\"%s\")", path, tmp->v_path); + vol = tmp; + goto EC_CLEANUP; + } + } else { + LOG(log_debug, logtype_afpd, "getvolbypath: path(\"%s\") != volume(\"%s\")", path, tmp->v_path); + } + } + + if (!have_uservol) /* (2) */ + EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path); + + int secnum = atalk_iniparser_getnsec(obj->iniconfig); + + for (int i = 0; i < secnum; i++) { + secname = atalk_iniparser_getsecname(obj->iniconfig, i); + if (STRCMP(secname, ==, INISEC_HOMES)) + break; + } + + if (STRCMP(secname, !=, INISEC_HOMES)) + EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path); + + /* (3) */ + EC_NULL_LOG( basedir = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL) ); + LOG(log_debug, logtype_afpd, "getvolbypath: user home section: '%s', basedir: '%s'", secname, basedir); + + if (regexerr != 0 && (regexerr = regcomp(®, basedir, REG_EXTENDED)) != 0) { + char errbuf[1024]; + regerror(regexerr, ®, errbuf, sizeof(errbuf)); + printf("error: %s\n", errbuf); + EC_FAIL_LOG("getvolbypath(\"%s\"): bad basedir regex: %s", errbuf); + } + + if (regexec(®, path, 1, match, 0) == REG_NOMATCH) + EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path); + + if (match[0].rm_eo - match[0].rm_so > MAXPATHLEN) + EC_FAIL_LOG("getvolbypath(\"%s\"): path too long", path); + + /* (4) */ + strncpy(tmpbuf, path + match[0].rm_so, match[0].rm_eo - match[0].rm_so); + tmpbuf[match[0].rm_eo - match[0].rm_so] = 0; + + LOG(log_debug, logtype_afpd, "getvolbypath: basedir regex: '%s', basedir match: \"%s\"", + basedir, tmpbuf); + + strlcat(tmpbuf, "/", MAXPATHLEN); + + /* (5) */ + p = path + match[0].rm_eo - match[0].rm_so; + while (*p == '/') + p++; + EC_NULL_LOG( user = strdup(p) ); + + if ((prw = strchr(user, '/'))) + *prw++ = 0; + if (prw != 0) + subpath = prw; + + strlcat(tmpbuf, user, MAXPATHLEN); + if ((pw = getpwnam(user)) == NULL) { + /* (5b) */ + char *tuser; + if ((tuser = getuserbypath(tmpbuf)) != NULL) { + free(user); + user = strdup(tuser); + } + if ((pw = getpwnam(user)) == NULL) + EC_FAIL_LOG("unknown user: %s", user); + } + strlcpy(obj->username, user, MAXUSERLEN); + strlcat(tmpbuf, "/", MAXPATHLEN); + + /* (6) */ + if ((subpathconfig = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) { + /* + if (!subpath || strncmp(subpathconfig, subpath, strlen(subpathconfig)) != 0) { + EC_FAIL; + } + */ + strlcat(tmpbuf, subpathconfig, MAXPATHLEN); + strlcat(tmpbuf, "/", MAXPATHLEN); + } + + + /* (7) */ + if (volxlate(obj, volpath, sizeof(volpath) - 1, tmpbuf, pw, NULL, NULL) == NULL) + EC_FAIL; + + EC_NULL( realvolpath = realpath_safe(volpath) ); + EC_NULL( pw = getpwnam(user) ); + + LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\"): user: %s, homedir: %s => realvolpath: \"%s\"", + path, user, pw->pw_dir, realvolpath); + + /* do variable substitution for volume name */ + p = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home"); + if (strstr(p, "$u") == NULL) + p = "$u's home"; + strlcpy(tmpbuf, p, AFPVOL_U8MNAMELEN); + EC_NULL_LOG( volxlate(obj, volname, sizeof(volname) - 1, tmpbuf, pw, realvolpath, NULL) ); + + const char *preset, *default_preset; + default_preset = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol preset", NULL); + preset = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "vol preset", NULL); + + vol = creatvol(obj, pw, INISEC_HOMES, volname, realvolpath, preset ? preset : default_preset ? default_preset : NULL); + +EC_CLEANUP: + if (user) + free(user); + if (realvolpath) + free(realvolpath); + if (realabspath) + free(realabspath); + if (ret != 0) + vol = NULL; + return vol; +} + +struct vol *getvolbyname(const char *name) +{ + struct vol *vol = NULL; + struct vol *tmp; + + for (tmp = Volumes; tmp; tmp = tmp->v_next) { + if (strncmp(name, tmp->v_configname, strlen(tmp->v_configname)) == 0) { + vol = tmp; + break; + } + } + return vol; +} + +#define MAXVAL 1024 +/*! + * Initialize an AFPObj and options from ini config file + */ +int afp_config_parse(AFPObj *AFPObj, char *processname) +{ + EC_INIT; + dictionary *config; + struct afp_options *options = &AFPObj->options; + int c; + const char *p; + char *q, *r; + char val[MAXVAL]; + + if (processname != NULL) + set_processname(processname); + + AFPObj->afp_version = 11; + options->configfile = AFPObj->cmdlineconfigfile ? strdup(AFPObj->cmdlineconfigfile) : strdup(_PATH_CONFDIR "afp.conf"); + options->sigconffile = strdup(_PATH_STATEDIR "afp_signature.conf"); + options->uuidconf = strdup(_PATH_STATEDIR "afp_voluuid.conf"); + options->flags = OPTION_UUID | AFPObj->cmdlineflags; + + if ((config = atalk_iniparser_load(AFPObj->options.configfile)) == NULL) + return -1; + AFPObj->iniconfig = config; + + /* [Global] */ + options->logconfig = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "log level", "default:note"); + options->logfile = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "log file", NULL); + + setuplog(options->logconfig, options->logfile); + + /* "server options" boolean options */ + if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "zeroconf", 1)) + options->flags |= OPTION_NOZEROCONF; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "advertise ssh", 0)) + options->flags |= OPTION_ANNOUNCESSH; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0)) + options->flags |= OPTION_CLOSEVOL; + if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0)) + options->flags |= OPTION_SERVERNOTIF; + if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "use sendfile", 1)) + options->flags |= OPTION_NOSENDFILE; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "recvfile", 0)) + options->flags |= OPTION_RECVFILE; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "solaris share reservations", 1)) + options->flags |= OPTION_SHARE_RESERV; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "afpstats", 0)) + options->flags |= OPTION_DBUS_AFPSTATS; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "afp read locks", 0)) + options->flags |= OPTION_AFP_READ_LOCK; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "spotlight", 0)) + options->flags |= OPTION_SPOTLIGHT_VOL; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "veto message", 0)) + options->flags |= OPTION_VETOMSG; + if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1)) + options->passwdbits |= PASSWD_NOSAVE; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0)) + options->passwdbits |= PASSWD_SET; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "spotlight expr", 1)) + options->flags |= OPTION_SPOTLIGHT_EXPR; + + /* figure out options w values */ + options->loginmesg = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "login message", NULL); + options->guest = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "guest account", "nobody"); + options->extmapfile = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "extmap file", _PATH_CONFDIR "extmap.conf"); + options->passwdfile = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "passwd file", _PATH_AFPDPWFILE); + options->uampath = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "uam path", _PATH_AFPDUAMPATH); + options->uamlist = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "uam list", "uams_dhx.so uams_dhx2.so"); + options->port = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "afp port", "548"); + options->signatureopt = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "signature", ""); + options->k5service = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "k5 service", NULL); + options->k5realm = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "k5 realm", NULL); + options->listen = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "afp listen", NULL); + options->interfaces = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "afp interfaces", NULL); + options->ntdomain = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "nt domain", NULL); + options->addomain = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "ad domain", NULL); + options->ntseparator = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "nt separator", NULL); + options->mimicmodel = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "mimic model", NULL); + options->adminauthuser = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "admin auth user",NULL); + options->ignored_attr = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "ignored attributes", NULL); + options->cnid_mysql_host = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "cnid mysql host", NULL); + options->cnid_mysql_user = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "cnid mysql user", NULL); + options->cnid_mysql_pw = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "cnid mysql pw", NULL); + options->cnid_mysql_db = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "cnid mysql db", NULL); + options->connections = atalk_iniparser_getint (config, INISEC_GLOBAL, "max connections",200); + options->passwdminlen = atalk_iniparser_getint (config, INISEC_GLOBAL, "passwd minlen", 0); + options->tickleval = atalk_iniparser_getint (config, INISEC_GLOBAL, "tickleval", 30); + options->timeout = atalk_iniparser_getint (config, INISEC_GLOBAL, "timeout", 4); + options->dsireadbuf = atalk_iniparser_getint (config, INISEC_GLOBAL, "dsireadbuf", 12); + options->server_quantum = atalk_iniparser_getint (config, INISEC_GLOBAL, "server quantum", DSI_SERVQUANT_DEF); + options->volnamelen = atalk_iniparser_getint (config, INISEC_GLOBAL, "volnamelen", 80); + options->dircachesize = atalk_iniparser_getint (config, INISEC_GLOBAL, "dircachesize", DEFAULT_MAX_DIRCACHE_SIZE); + options->tcp_sndbuf = atalk_iniparser_getint (config, INISEC_GLOBAL, "tcpsndbuf", 0); + options->tcp_rcvbuf = atalk_iniparser_getint (config, INISEC_GLOBAL, "tcprcvbuf", 0); + options->fce_fmodwait = atalk_iniparser_getint (config, INISEC_GLOBAL, "fce holdfmod", 60); + options->sleep = atalk_iniparser_getint (config, INISEC_GLOBAL, "sleep time", 10); + options->disconnected = atalk_iniparser_getint (config, INISEC_GLOBAL, "disconnect time",24); + options->splice_size = atalk_iniparser_getint (config, INISEC_GLOBAL, "splice size", 64*1024); + options->sparql_limit = atalk_iniparser_getint (config, INISEC_GLOBAL, "sparql results limit", 0); + + p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "map acls", "rights"); + if (STRCMP(p, ==, "rights")) + options->flags |= OPTION_ACL2MACCESS; + else if (STRCMP(p, ==, "mode")) + options->flags |= OPTION_ACL2MODE | OPTION_ACL2MACCESS; + else { + if (STRCMP(p, !=, "none")) { + LOG(log_error, logtype_afpd, "bad ACL mapping option: %s, defaulting to 'rights'", p); + options->flags |= OPTION_ACL2MACCESS; + } + } + + if ((p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "hostname", NULL))) { + EC_NULL_LOG( options->hostname = strdup(p) ); + } else { + if (gethostname(val, sizeof(val)) < 0 ) { + perror( "gethostname" ); + EC_FAIL; + } + if ((q = strchr(val, '.'))) + *q = '\0'; + options->hostname = strdup(val); + } + + if ((p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "k5 keytab", NULL))) { + EC_NULL_LOG( options->k5keytab = malloc(strlen(p) + 14) ); + snprintf(options->k5keytab, strlen(p) + 14, "KRB5_KTNAME=%s", p); + putenv(options->k5keytab); + } + +#ifdef ADMIN_GRP + if ((p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "admin group", NULL))) { + struct group *gr = getgrnam(p); + if (gr != NULL) + options->admingid = gr->gr_gid; + } +#endif /* ADMIN_GRP */ + + q = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "cnid server", "localhost:4700"); + r = strrchr(q, ':'); + if (r) + *r = 0; + options->Cnid_srv = strdup(q); + if (r) + options->Cnid_port = strdup(r + 1); + else + options->Cnid_port = strdup("4700"); + LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", options->Cnid_srv, options->Cnid_port); + if (q) + free(q); + + if ((q = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "fqdn", NULL))) { + /* do a little checking for the domain name. */ + r = strchr(q, ':'); + if (r) + *r = '\0'; + if (gethostbyname(q)) { + if (r) + *r = ':'; + EC_NULL_LOG( options->fqdn = strdup(q) ); + } else { + LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", q); + } + free(q); + } + + /* Charset Options */ + + /* unix charset is in [G] only */ + if (!(p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "unix charset", NULL))) { + options->unixcodepage = strdup("UTF8"); + set_charset_name(CH_UNIX, "UTF8"); + } else { + if (strcasecmp(p, "LOCALE") == 0) { +#if defined(CODESET) + setlocale(LC_ALL, ""); + p = nl_langinfo(CODESET); + LOG(log_debug, logtype_afpd, "Locale charset is '%s'", p); +#else /* system doesn't have LOCALE support */ + LOG(log_warning, logtype_afpd, "system doesn't have LOCALE support"); + p = "UTF8"; +#endif + } + if (strcasecmp(p, "UTF-8") == 0) { + p = "UTF8"; + } + options->unixcodepage = strdup(p); + set_charset_name(CH_UNIX, p); + } + options->unixcharset = CH_UNIX; + LOG(log_debug, logtype_afpd, "Global unix charset is %s", options->unixcodepage); + + /* vol charset is in [G] and [V] */ + if (!(p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "vol charset", NULL))) { + options->volcodepage = strdup(options->unixcodepage); + } else { + if (strcasecmp(p, "UTF-8") == 0) { + p = "UTF8"; + } + options->volcodepage = strdup(p); + } + LOG(log_debug, logtype_afpd, "Global vol charset is %s", options->volcodepage); + + /* mac charset is in [G] and [V] */ + if (!(p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "mac charset", NULL))) { + options->maccodepage = strdup("MAC_ROMAN"); + set_charset_name(CH_MAC, "MAC_ROMAN"); + } else { + if (strncasecmp(p, "MAC", 3) != 0) { + LOG(log_warning, logtype_afpd, "Is '%s' really mac charset? ", p); + } + options->maccodepage = strdup(p); + set_charset_name(CH_MAC, p); + } + options->maccharset = CH_MAC; + LOG(log_debug, logtype_afpd, "Global mac charset is %s", options->maccodepage); + + if (readextmap(options->extmapfile) != 0) { + LOG(log_error, logtype_afpd, "Couldn't load extension -> type/creator mappings file \"%s\"", + options->extmapfile); + } + + /* Check for sane values */ + if (options->tickleval <= 0) + options->tickleval = 30; + options->disconnected *= 3600 / options->tickleval; + options->sleep *= 3600 / options->tickleval; + if (options->timeout <= 0) + options->timeout = 4; + if (options->sleep <= 4) + options->disconnected = options->sleep = 4; + if (options->dsireadbuf < 6) + options->dsireadbuf = 6; + if (options->volnamelen < 8) + options->volnamelen = 8; /* max mangled volname "???#FFFF" */ + if (options->volnamelen > 255) + options->volnamelen = 255; /* AFP3 spec */ + +EC_CLEANUP: + EC_EXIT; +} + +#define CONFIG_ARG_FREE(a) do { \ + free(a); \ + a = NULL; \ + } while (0); + +/* get rid of any allocated afp_option buffers. */ +void afp_config_free(AFPObj *obj) +{ + if (obj->options.configfile) + CONFIG_ARG_FREE(obj->options.configfile); + if (obj->options.sigconffile) + CONFIG_ARG_FREE(obj->options.sigconffile); + if (obj->options.uuidconf) + CONFIG_ARG_FREE(obj->options.uuidconf); + if (obj->options.logconfig) + CONFIG_ARG_FREE(obj->options.logconfig); + if (obj->options.logfile) + CONFIG_ARG_FREE(obj->options.logfile); + if (obj->options.loginmesg) + CONFIG_ARG_FREE(obj->options.loginmesg); + if (obj->options.guest) + CONFIG_ARG_FREE(obj->options.guest); + if (obj->options.extmapfile) + CONFIG_ARG_FREE(obj->options.extmapfile); + if (obj->options.passwdfile) + CONFIG_ARG_FREE(obj->options.passwdfile); + if (obj->options.uampath) + CONFIG_ARG_FREE(obj->options.uampath); + if (obj->options.uamlist) + CONFIG_ARG_FREE(obj->options.uamlist); + if (obj->options.port) + CONFIG_ARG_FREE(obj->options.port); + if (obj->options.signatureopt) + CONFIG_ARG_FREE(obj->options.signatureopt); + if (obj->options.k5service) + CONFIG_ARG_FREE(obj->options.k5service); + if (obj->options.k5realm) + CONFIG_ARG_FREE(obj->options.k5realm); + if (obj->options.k5principal) + CONFIG_ARG_FREE(obj->options.k5principal); + if (obj->options.listen) + CONFIG_ARG_FREE(obj->options.listen); + if (obj->options.interfaces) + CONFIG_ARG_FREE(obj->options.interfaces); + if (obj->options.ntdomain) + CONFIG_ARG_FREE(obj->options.ntdomain); + if (obj->options.addomain) + CONFIG_ARG_FREE(obj->options.addomain); + if (obj->options.ntseparator) + CONFIG_ARG_FREE(obj->options.ntseparator); + if (obj->options.mimicmodel) + CONFIG_ARG_FREE(obj->options.mimicmodel); + if (obj->options.adminauthuser) + CONFIG_ARG_FREE(obj->options.adminauthuser); + if (obj->options.hostname) + CONFIG_ARG_FREE(obj->options.hostname); + if (obj->options.k5keytab) + CONFIG_ARG_FREE(obj->options.k5keytab); + if (obj->options.Cnid_srv) + CONFIG_ARG_FREE(obj->options.Cnid_srv); + if (obj->options.Cnid_port) + CONFIG_ARG_FREE(obj->options.Cnid_port); + if (obj->options.fqdn) + CONFIG_ARG_FREE(obj->options.fqdn); + if (obj->options.ignored_attr) + CONFIG_ARG_FREE(obj->options.ignored_attr); + if (obj->options.unixcodepage) + CONFIG_ARG_FREE(obj->options.unixcodepage); + if (obj->options.maccodepage) + CONFIG_ARG_FREE(obj->options.maccodepage); + if (obj->options.volcodepage) + CONFIG_ARG_FREE(obj->options.volcodepage); + + obj->options.flags = 0; + obj->options.passwdbits = 0; + + /* Free everything called from afp_config_parse() */ + free_extmap(); + atalk_iniparser_freedict(obj->iniconfig); + free_charset_names(); +} diff --git a/libatalk/util/queue.c b/libatalk/util/queue.c new file mode 100644 index 0000000..114e640 --- /dev/null +++ b/libatalk/util/queue.c @@ -0,0 +1,116 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. +*/ + +/*! + * @file + * Netatalk utility functions: queue + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include + +static qnode_t *alloc_init_node(void *data) +{ + qnode_t *node; + if ((node = malloc(sizeof(qnode_t))) == NULL) + return NULL; + node->data = data; + + return node; +} + +/******************************************************************************** + * Interface + *******************************************************************************/ + +q_t *queue_init(void) +{ + q_t *queue; + + if ((queue = alloc_init_node(NULL)) == NULL) + return NULL; + + queue->prev = queue->next = queue; + return queue; +} + +/* Insert at tail */ +qnode_t *enqueue(q_t *q, void *data) +{ + qnode_t *node; + + if ((node = alloc_init_node(data)) == NULL) + return NULL; + + /* insert at tail */ + node->next = q; + node->prev = q->prev; + q->prev->next = node; + q->prev = node; + + return node; +} + +/* Insert at head */ +qnode_t *prequeue(q_t *q, void *data) +{ + qnode_t *node; + + if ((node = alloc_init_node(data)) == NULL) + return NULL; + + /* insert at head */ + q->next->prev = node; + node->next = q->next; + node->prev = q; + q->next = node; + + return node; +} + +/* Take from head */ +void *dequeue(q_t *q) +{ + qnode_t *node; + void *data; + + if (q == NULL || q->next == q) + return NULL; + + /* take first node from head */ + node = q->next; + data = node->data; + q->next = node->next; + node->next->prev = node->prev; + free(node); + + return data; +} + +void queue_destroy(q_t *q, void (*callback)(void *)) +{ + void *p; + + while ((p = dequeue(q)) != NULL) + callback(p); + + free(q); + q = NULL; +} + diff --git a/libatalk/util/server_child.c b/libatalk/util/server_child.c new file mode 100644 index 0000000..da78c6a --- /dev/null +++ b/libatalk/util/server_child.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * Copyright (c) 2013 Frank Lahm +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif /* ! WEXITSTATUS */ +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif /* ! WIFEXITED */ +#ifndef WIFSTOPPED +#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status)) +#endif +#ifndef WTERMSIG +#define WTERMSIG(status) ((status) & 0x7f) +#endif + +/* hash/child functions: hash OR's pid */ +#define HASH(i) ((((i) >> 8) ^ (i)) & (CHILD_HASHSIZE - 1)) + +static inline void hash_child(afp_child_t **htable, afp_child_t *child) +{ + afp_child_t **table; + + table = &htable[HASH(child->afpch_pid)]; + if ((child->afpch_next = *table) != NULL) + (*table)->afpch_prevp = &child->afpch_next; + *table = child; + child->afpch_prevp = table; +} + +static inline void unhash_child(afp_child_t *child) +{ + if (child->afpch_prevp) { + if (child->afpch_next) + child->afpch_next->afpch_prevp = child->afpch_prevp; + *(child->afpch_prevp) = child->afpch_next; + } +} + +afp_child_t *server_child_resolve(server_child_t *childs, id_t pid) +{ + afp_child_t *child; + + for (child = childs->servch_table[HASH(pid)]; child; child = child->afpch_next) { + if (child->afpch_pid == pid) + break; + } + + return child; +} + +/* initialize server_child structure */ +server_child_t *server_child_alloc(int connections) +{ + server_child_t *children; + + if (!(children = (server_child_t *)calloc(1, sizeof(server_child_t)))) + return NULL; + + children->servch_nsessions = connections; + pthread_mutex_init(&children->servch_lock, NULL); + return children; +} + +/*! + * add a child + * @return pointer to struct server_child_data on success, NULL on error + */ +afp_child_t *server_child_add(server_child_t *children, pid_t pid, int ipc_fd) +{ + afp_child_t *child = NULL; + + pthread_mutex_lock(&children->servch_lock); + + /* it's possible that the child could have already died before the + * pthread_sigmask. we need to check for this. */ + if (kill(pid, 0) < 0) { + LOG(log_error, logtype_default, "server_child_add: no such process pid [%d]", pid); + goto exit; + } + + /* if we already have an entry. just return. */ + if ((child = server_child_resolve(children, pid))) + goto exit; + + if ((child = calloc(1, sizeof(afp_child_t))) == NULL) + goto exit; + + child->afpch_pid = pid; + child->afpch_ipc_fd = ipc_fd; + child->afpch_logintime = time(NULL); + + hash_child(children->servch_table, child); + children->servch_count++; + +exit: + pthread_mutex_unlock(&children->servch_lock); + return child; +} + +/* remove a child and free it */ +int server_child_remove(server_child_t *children, pid_t pid) +{ + int fd; + afp_child_t *child; + + if (!(child = server_child_resolve(children, pid))) + return -1; + + pthread_mutex_lock(&children->servch_lock); + + unhash_child(child); + if (child->afpch_clientid) { + free(child->afpch_clientid); + child->afpch_clientid = NULL; + } + + /* In main:child_handler() we need the fd in order to remove it from the pollfd set */ + fd = child->afpch_ipc_fd; + if (fd != -1) + close(fd); + + free(child); + children->servch_count--; + + pthread_mutex_unlock(&children->servch_lock); + + return fd; +} + +/* free everything: by using a hash table, this increases the cost of + * this part over a linked list by the size of the hash table */ +void server_child_free(server_child_t *children) +{ + afp_child_t *child, *tmp; + int j; + + for (j = 0; j < CHILD_HASHSIZE; j++) { + child = children->servch_table[j]; /* start at the beginning */ + while (child) { + tmp = child->afpch_next; + close(child->afpch_ipc_fd); + if (child->afpch_clientid) + free(child->afpch_clientid); + if (child->afpch_volumes) + free(child->afpch_volumes); + free(child); + child = tmp; + } + } + + free(children); +} + +/* send signal to all child processes */ +void server_child_kill(server_child_t *children, int sig) +{ + afp_child_t *child, *tmp; + int i; + + for (i = 0; i < CHILD_HASHSIZE; i++) { + child = children->servch_table[i]; + while (child) { + tmp = child->afpch_next; + kill(child->afpch_pid, sig); + child = tmp; + } + } +} + +/* send kill to a child processes */ +static int kill_child(afp_child_t *child) +{ + if (!child->afpch_killed) { + kill(child->afpch_pid, SIGTERM); + /* we don't wait because there's no guarantee that we can really kill it */ + child->afpch_killed = 1; + return 1; + } else { + LOG(log_info, logtype_default, "Unresponsive child[%d], sending SIGKILL", child->afpch_pid); + kill(child->afpch_pid, SIGKILL); + } + return 1; +} + +/*! + * Try to find an old session and pass socket + * @returns -1 on error, 0 if no matching session was found, 1 if session was found and socket passed + */ +int server_child_transfer_session(server_child_t *children, + pid_t pid, + uid_t uid, + int afp_socket, + uint16_t DSI_requestID) +{ + EC_INIT; + afp_child_t *child; + + if ((child = server_child_resolve(children, pid)) == NULL) { + LOG(log_note, logtype_default, "Reconnect: no child[%u]", pid); + if (kill(pid, 0) == 0) { + LOG(log_note, logtype_default, "Reconnect: terminating old session[%u]", pid); + kill(pid, SIGTERM); + sleep(2); + if (kill(pid, 0) == 0) { + LOG(log_error, logtype_default, "Reconnect: killing old session[%u]", pid); + kill(pid, SIGKILL); + sleep(2); + } + } + return 0; + } + + if (!child->afpch_valid) { + /* hmm, client 'guess' the pid, rogue? */ + LOG(log_error, logtype_default, "Reconnect: invalidated child[%u]", pid); + return 0; + } else if (child->afpch_uid != uid) { + LOG(log_error, logtype_default, "Reconnect: child[%u] not the same user", pid); + return 0; + } + + LOG(log_note, logtype_default, "Reconnect: transfering session to child[%u]", pid); + + if (writet(child->afpch_ipc_fd, &DSI_requestID, 2, 0, 2) != 2) { + LOG(log_error, logtype_default, "Reconnect: error sending DSI id to child[%u]", pid); + EC_STATUS(-1); + goto EC_CLEANUP; + } + EC_ZERO_LOG(send_fd(child->afpch_ipc_fd, afp_socket)); + EC_ZERO_LOG(kill(pid, SIGURG)); + + EC_STATUS(1); + +EC_CLEANUP: + EC_EXIT; +} + + +/* see if there is a process for the same mac */ +/* if the times don't match mac has been rebooted */ +void server_child_kill_one_by_id(server_child_t *children, pid_t pid, + uid_t uid, uint32_t idlen, char *id, uint32_t boottime) +{ + afp_child_t *child, *tmp; + int i; + + pthread_mutex_lock(&children->servch_lock); + + for (i = 0; i < CHILD_HASHSIZE; i++) { + child = children->servch_table[i]; + while (child) { + tmp = child->afpch_next; + if (child->afpch_pid != pid) { + if (child->afpch_idlen == idlen && memcmp(child->afpch_clientid, id, idlen) == 0) { + if ( child->afpch_boottime != boottime ) { + /* Client rebooted */ + if (uid == child->afpch_uid) { + kill_child(child); + LOG(log_warning, logtype_default, + "Terminated disconnected child[%u], client rebooted.", + child->afpch_pid); + } else { + LOG(log_warning, logtype_default, + "Session with different pid[%u]", child->afpch_pid); + } + } else { + /* One client with multiple sessions */ + LOG(log_debug, logtype_default, + "Found another session[%u] for client[%u]", child->afpch_pid, pid); + } + } + } else { + /* update childs own slot */ + child->afpch_boottime = boottime; + if (child->afpch_clientid) + free(child->afpch_clientid); + LOG(log_debug, logtype_default, "Setting client ID for %u", child->afpch_pid); + child->afpch_uid = uid; + child->afpch_valid = 1; + child->afpch_idlen = idlen; + child->afpch_clientid = id; + } + child = tmp; + } + } + + pthread_mutex_unlock(&children->servch_lock); +} + +/* --------------------------- + * reset children signals + */ +void server_reset_signal(void) +{ + struct sigaction sv; + sigset_t sigs; + const struct itimerval none = {{0, 0}, {0, 0}}; + + setitimer(ITIMER_REAL, &none, NULL); + memset(&sv, 0, sizeof(sv)); + sv.sa_handler = SIG_DFL; + sigemptyset( &sv.sa_mask ); + + sigaction(SIGALRM, &sv, NULL ); + sigaction(SIGHUP, &sv, NULL ); + sigaction(SIGTERM, &sv, NULL ); + sigaction(SIGUSR1, &sv, NULL ); + sigaction(SIGCHLD, &sv, NULL ); + + sigemptyset(&sigs); + sigaddset(&sigs, SIGALRM); + sigaddset(&sigs, SIGHUP); + sigaddset(&sigs, SIGUSR1); + sigaddset(&sigs, SIGCHLD); + pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); + +} diff --git a/libatalk/util/server_ipc.c b/libatalk/util/server_ipc.c new file mode 100644 index 0000000..e49d165 --- /dev/null +++ b/libatalk/util/server_ipc.c @@ -0,0 +1,311 @@ +/* + * All rights reserved. See COPYRIGHT. + * + * IPC over socketpair between parent and children. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPC_HEADERLEN 14 +#define IPC_MAXMSGSIZE 90 + +typedef struct ipc_header { + uint16_t command; + pid_t child_pid; + uid_t uid; + uint32_t len; + char *msg; + int afp_socket; + uint16_t DSI_requestID; +} ipc_header_t; + +static char *ipc_cmd_str[] = { "IPC_DISCOLDSESSION", + "IPC_GETSESSION", + "IPC_STATE", + "IPC_VOLUMES"}; + +/* + * Pass afp_socket to old disconnected session if one has a matching token (token = pid) + * @returns -1 on error, 0 if no matching session was found, 1 if session was found and socket passed + */ +static int ipc_kill_token(struct ipc_header *ipc, server_child_t *children) +{ + pid_t pid; + + if (ipc->len != sizeof(pid_t)) { + return -1; + } + /* assume signals SA_RESTART set */ + memcpy (&pid, ipc->msg, sizeof(pid_t)); + + return server_child_transfer_session(children, + pid, + ipc->uid, + ipc->afp_socket, + ipc->DSI_requestID); +} + +/* ----------------- */ +static int ipc_get_session(struct ipc_header *ipc, server_child_t *children) +{ + uint32_t boottime; + uint32_t idlen; + char *clientid, *p; + + + if (ipc->len < (sizeof(idlen) + sizeof(boottime)) ) + return -1; + + p = ipc->msg; + memcpy (&idlen, p, sizeof(idlen)); + idlen = ntohl (idlen); + p += sizeof(idlen); + + memcpy (&boottime, p, sizeof(boottime)); + p += sizeof(boottime); + + if (ipc->len < idlen + sizeof(idlen) + sizeof(boottime)) + return -1; + + if (NULL == (clientid = (char*) malloc(idlen)) ) + return -1; + memcpy (clientid, p, idlen); + + LOG(log_debug, logtype_afpd, "ipc_get_session(pid: %u, uid: %u, time: 0x%08x)", + ipc->child_pid, ipc->uid, boottime); + + server_child_kill_one_by_id(children, + ipc->child_pid, + ipc->uid, + idlen, + clientid, + boottime); + + return 0; +} + +static int ipc_set_state(struct ipc_header *ipc, server_child_t *children) +{ + EC_INIT; + afp_child_t *child; + + pthread_mutex_lock(&children->servch_lock); + + if ((child = server_child_resolve(children, ipc->child_pid)) == NULL) + EC_FAIL; + + memcpy(&child->afpch_state, ipc->msg, sizeof(uint16_t)); + +EC_CLEANUP: + pthread_mutex_unlock(&children->servch_lock); + EC_EXIT; +} + +static int ipc_set_volumes(struct ipc_header *ipc, server_child_t *children) +{ + EC_INIT; + afp_child_t *child; + + pthread_mutex_lock(&children->servch_lock); + + if ((child = server_child_resolve(children, ipc->child_pid)) == NULL) + EC_FAIL; + + if (child->afpch_volumes) { + free(child->afpch_volumes); + child->afpch_volumes = NULL; + } + if (ipc->len) + child->afpch_volumes = strdup(ipc->msg); + +EC_CLEANUP: + pthread_mutex_unlock(&children->servch_lock); + EC_EXIT; +} + +/*********************************************************************************** + * Public functions + ***********************************************************************************/ + +/* ----------------- + * Ipc format + * command + * pid + * uid + * + */ + +/*! + * Read a IPC message from a child + * + * This is using an fd with non-blocking IO, so EAGAIN is not an error + * + * @args children (rw) pointer to our structure with all childs + * @args fd (r) IPC socket with child + * + * @returns -1 on error, 0 on success + */ +int ipc_server_read(server_child_t *children, int fd) +{ + int ret; + struct ipc_header ipc; + char buf[IPC_MAXMSGSIZE], *p; + + if ((ret = read(fd, buf, IPC_HEADERLEN)) != IPC_HEADERLEN) { + if (ret != 0) { + if (errno == EAGAIN) + return 0; + LOG(log_error, logtype_afpd, "Reading IPC header failed (%i of %u bytes read): %s", + ret, IPC_HEADERLEN, strerror(errno)); + } + return -1; + } + + p = buf; + + memcpy(&ipc.command, p, sizeof(ipc.command)); + p += sizeof(ipc.command); + + memcpy(&ipc.child_pid, p, sizeof(ipc.child_pid)); + p += sizeof(ipc.child_pid); + + memcpy(&ipc.uid, p, sizeof(ipc.uid)); + p += sizeof(ipc.uid); + + memcpy(&ipc.len, p, sizeof(ipc.len)); + + /* This should never happen */ + if (ipc.len > (IPC_MAXMSGSIZE - IPC_HEADERLEN)) { + LOG (log_info, logtype_afpd, "IPC message exceeds allowed size (%u)", ipc.len); + return -1; + } + + memset (buf, 0, IPC_MAXMSGSIZE); + if ( ipc.len != 0) { + if ((ret = read(fd, buf, ipc.len)) != (int) ipc.len) { + LOG(log_info, logtype_afpd, "Reading IPC message failed (%u of %u bytes read): %s", + ret, ipc.len, strerror(errno)); + return -1; + } + } + ipc.msg = buf; + + LOG(log_debug, logtype_afpd, "ipc_server_read(%s): pid: %u", + ipc_cmd_str[ipc.command], ipc.child_pid); + + switch (ipc.command) { + + case IPC_DISCOLDSESSION: + if (readt(fd, &ipc.DSI_requestID, 2, 0, 2) != 2) { + LOG (log_error, logtype_afpd, "ipc_read(%s:child[%u]): couldnt read DSI id: %s", + ipc_cmd_str[ipc.command], ipc.child_pid, strerror(errno)); + return -1; + } + if ((ipc.afp_socket = recv_fd(fd, 1)) == -1) { + LOG (log_error, logtype_afpd, "ipc_read(%s:child[%u]): recv_fd: %s", + ipc_cmd_str[ipc.command], ipc.child_pid, strerror(errno)); + return -1; + } + if (ipc_kill_token(&ipc, children) == 1) { + /* Transfered session (ie afp_socket) to old disconnected child, now kill the new one */ + LOG(log_note, logtype_afpd, "Reconnect: killing new session child[%u] after transfer", + ipc.child_pid); + kill(ipc.child_pid, SIGTERM); + } + close(ipc.afp_socket); + break; + + case IPC_GETSESSION: + if (ipc_get_session(&ipc, children) != 0) + return -1; + break; + + case IPC_STATE: + if (ipc_set_state(&ipc, children) != 0) + return -1; + break; + + case IPC_VOLUMES: + if (ipc_set_volumes(&ipc, children) != 0) + return -1; + break; + + default: + LOG (log_info, logtype_afpd, "ipc_read: unknown command: %d", ipc.command); + return -1; + } + + return 0; +} + +/* ----------------- */ +int ipc_child_write(int fd, uint16_t command, int len, void *msg) +{ + char block[IPC_MAXMSGSIZE], *p; + pid_t pid; + uid_t uid; + ssize_t ret; + + p = block; + + memset ( p, 0 , IPC_MAXMSGSIZE); + if (len + IPC_HEADERLEN > IPC_MAXMSGSIZE) + return -1; + + memcpy(p, &command, sizeof(command)); + p += sizeof(command); + + pid = getpid(); + memcpy(p, &pid, sizeof(pid_t)); + p += sizeof(pid_t); + + /* FIXME + * using uid is wrong. It will not disconnect if the new connection + * is with a different user. + * But we really don't want a remote kill command. + */ + uid = geteuid(); + memcpy(p, &uid, sizeof(uid_t)); + p += sizeof(uid_t); + + memcpy(p, &len, 4); + p += 4; + + memcpy(p, msg, len); + + LOG(log_debug, logtype_afpd, "ipc_child_write(%s)", ipc_cmd_str[command]); + + if ((ret = writet(fd, block, len+IPC_HEADERLEN, 0, 1)) != len + IPC_HEADERLEN) { + return -1; + } + + return 0; +} + +int ipc_child_state(AFPObj *obj, uint16_t state) +{ + return ipc_child_write(obj->ipc_fd, IPC_STATE, sizeof(uint16_t), &state); +} diff --git a/libatalk/util/server_lock.c b/libatalk/util/server_lock.c new file mode 100644 index 0000000..6ae817e --- /dev/null +++ b/libatalk/util/server_lock.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu) + * All rights reserved. See COPYRIGHT. + * + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +static struct itimerval itimer; + +/* this creates an open lock file which hangs around until the program + * dies. it returns the pid. due to problems w/ solaris, this has + * been changed to do the kill() thing. */ +pid_t server_lock(char *program, char *pidfile, int debug) +{ + char buf[10]; + FILE *pf; + pid_t pid; + int mask; + + if ( !debug ) { + mask = umask(022); + /* check for pid. this can get fooled by stale pid's. */ + if ((pf = fopen(pidfile, "r"))) { + if (fgets(buf, sizeof(buf), pf) && !kill(pid = atol(buf), 0)) { + fprintf( stderr, "%s is already running (pid = %d), or the lock file is stale.\n", + program, pid); + fclose(pf); + return -1; + } + fclose(pf); + } + + if ((pf = fopen(pidfile, "w")) == NULL) { + fprintf(stderr, "%s: can't open lock file, \"%s\"\n", program, + pidfile); + return -1; + } + umask(mask); + + /* + * Disassociate from controlling tty. + */ + + int i; + + getitimer(ITIMER_PROF, &itimer); + switch (pid = fork()) { + case 0 : + setitimer(ITIMER_PROF, &itimer, NULL); + fclose(stdin); + fclose(stdout); + fclose(stderr); + i = open( "/dev/null", O_RDWR ); + i = open( "/dev/null", O_RDWR ); + i = open( "/dev/null", O_RDWR ); + +#ifdef TIOCNOTTY + if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) { + (void)ioctl( i, TIOCNOTTY, 0 ); + setpgid( 0, getpid()); + (void) close(i); + } +#else + setpgid( 0, getpid()); +#endif + break; + case -1 : /* error */ + perror( "fork" ); + default : /* server */ + fclose(pf); + return pid; + } + + fprintf(pf, "%d\n", getpid()); + fclose(pf); + } + + return 0; +} + +/*! + * Check lockfile + */ +int check_lockfile(const char *program, const char *pidfile) +{ + char buf[10]; + FILE *pf; + pid_t pid; + + /* check for pid. this can get fooled by stale pid's. */ + if ((pf = fopen(pidfile, "r"))) { + if (fgets(buf, sizeof(buf), pf) && !kill(pid = atol(buf), 0)) { + fprintf(stderr, "%s is already running (pid = %d), or the lock file is stale.\n", + program, pid); + fclose(pf); + return -1; + } + fclose(pf); + } + return 0; +} + +/*! + * Check and create lockfile + */ +int create_lockfile(const char *program, const char *pidfile) +{ + FILE *pf; + int mask; + + if (check_lockfile(program, pidfile) != 0) + return -1; + + /* Write PID to pidfile */ + mask = umask(022); + if ((pf = fopen(pidfile, "w")) == NULL) { + fprintf(stderr, "%s: can't open lock file, \"%s\"\n", program, + pidfile); + return -1; + } + umask(mask); + fprintf(pf, "%d\n", getpid()); + fclose(pf); + + return 0; +} diff --git a/libatalk/util/socket.c b/libatalk/util/socket.c new file mode 100644 index 0000000..60768a6 --- /dev/null +++ b/libatalk/util/socket.c @@ -0,0 +1,737 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +/*! + * @file + * Netatalk utility functions + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static char ipv4mapprefix[] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff}; + +/*! + * @brief set or unset non-blocking IO on a fd + * + * @param fd (r) File descriptor + * @param cmd (r) 0: disable non-blocking IO, ie block\n + * <>0: enable non-blocking IO + * + * @returns 0 on success, -1 on failure + */ +int setnonblock(int fd, int cmd) +{ + int ofdflags; + int fdflags; + + if ((fdflags = ofdflags = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + + if (cmd) + fdflags |= O_NONBLOCK; + else + fdflags &= ~O_NONBLOCK; + + if (fdflags != ofdflags) + if (fcntl(fd, F_SETFL, fdflags) == -1) + return -1; + + return 0; +} + +/*! + * non-blocking drop-in replacement for read with timeout using select + * + * @param socket (r) socket, if in blocking mode, pass "setnonblocking" arg as 1 + * @param data (rw) buffer for the read data + * @param lenght (r) how many bytes to read + * @param setnonblocking (r) when non-zero this func will enable and disable non blocking + * io mode for the socket + * @param timeout (r) number of seconds to try reading, 0 means no timeout + * + * @returns number of bytes actually read or -1 on timeout or error + */ +ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, int timeout) +{ + size_t stored = 0; + ssize_t len = 0; + struct timeval now, end, tv; + fd_set rfds; + int ret; + + FD_ZERO(&rfds); + + if (setnonblocking) { + if (setnonblock(socket, 1) != 0) + return -1; + } + + /* Calculate end time */ + if (timeout) { + (void)gettimeofday(&now, NULL); + end = now; + end.tv_sec += timeout; + } + + while (stored < length) { + len = recv(socket, (char *) data + stored, length - stored, 0); + if (len == -1) { + switch (errno) { + case EINTR: + continue; + case EAGAIN: + FD_SET(socket, &rfds); + if (timeout) { + tv.tv_usec = 0; + tv.tv_sec = timeout; + } + + while ((ret = select(socket + 1, &rfds, NULL, NULL, timeout ? &tv : NULL)) < 1) { + switch (ret) { + case 0: + LOG(log_debug, logtype_dsi, "select timeout %d s", timeout); + errno = EAGAIN; + goto exit; + + default: /* -1 */ + switch (errno) { + case EINTR: + if (timeout) { + (void)gettimeofday(&now, NULL); + if (now.tv_sec > end.tv_sec + || + (now.tv_sec == end.tv_sec && now.tv_usec >= end.tv_usec)) { + LOG(log_debug, logtype_afpd, "select timeout %d s", timeout); + goto exit; + } + if (now.tv_usec > end.tv_usec) { + tv.tv_usec = 1000000 + end.tv_usec - now.tv_usec; + tv.tv_sec = end.tv_sec - now.tv_sec - 1; + } else { + tv.tv_usec = end.tv_usec - now.tv_usec; + tv.tv_sec = end.tv_sec - now.tv_sec; + } + } + FD_SET(socket, &rfds); + continue; + case EBADF: + /* possibly entered disconnected state, don't spam log here */ + LOG(log_debug, logtype_afpd, "select: %s", strerror(errno)); + stored = -1; + goto exit; + default: + LOG(log_error, logtype_afpd, "select: %s", strerror(errno)); + stored = -1; + goto exit; + } + } + } /* while (select) */ + continue; + } /* switch (errno) */ + LOG(log_error, logtype_afpd, "read: %s", strerror(errno)); + stored = -1; + goto exit; + } /* (len == -1) */ + else if (len > 0) + stored += len; + else + break; + } /* while (stored < length) */ + +exit: + if (setnonblocking) { + if (setnonblock(socket, 0) != 0) + return -1; + } + + if (len == -1 && stored == 0) + /* last read or select got an error and we haven't got yet anything => return -1*/ + return -1; + return stored; +} + +/*! + * non-blocking drop-in replacement for read with timeout using select + * + * @param socket (r) socket, if in blocking mode, pass "setnonblocking" arg as 1 + * @param data (rw) buffer for the read data + * @param lenght (r) how many bytes to read + * @param setnonblocking (r) when non-zero this func will enable and disable non blocking + * io mode for the socket + * @param timeout (r) number of seconds to try reading + * + * @returns number of bytes actually read or -1 on fatal error + */ +ssize_t writet(int socket, void *data, const size_t length, int setnonblocking, int timeout) +{ + size_t stored = 0; + ssize_t len = 0; + struct timeval now, end, tv; + fd_set rfds; + int ret; + + if (setnonblocking) { + if (setnonblock(socket, 1) != 0) + return -1; + } + + /* Calculate end time */ + (void)gettimeofday(&now, NULL); + end = now; + end.tv_sec += timeout; + + while (stored < length) { + len = write(socket, (char *) data + stored, length - stored); + if (len == -1) { + switch (errno) { + case EINTR: + continue; + case EAGAIN: + FD_ZERO(&rfds); + FD_SET(socket, &rfds); + tv.tv_usec = 0; + tv.tv_sec = timeout; + + while ((ret = select(socket + 1, &rfds, NULL, NULL, &tv)) < 1) { + switch (ret) { + case 0: + LOG(log_warning, logtype_afpd, "select timeout %d s", timeout); + goto exit; + + default: /* -1 */ + if (errno == EINTR) { + (void)gettimeofday(&now, NULL); + if (now.tv_sec >= end.tv_sec && now.tv_usec >= end.tv_usec) { + LOG(log_warning, logtype_afpd, "select timeout %d s", timeout); + goto exit; + } + if (now.tv_usec > end.tv_usec) { + tv.tv_usec = 1000000 + end.tv_usec - now.tv_usec; + tv.tv_sec = end.tv_sec - now.tv_sec - 1; + } else { + tv.tv_usec = end.tv_usec - now.tv_usec; + tv.tv_sec = end.tv_sec - now.tv_sec; + } + FD_ZERO(&rfds); + FD_SET(socket, &rfds); + continue; + } + LOG(log_error, logtype_afpd, "select: %s", strerror(errno)); + stored = -1; + goto exit; + } + } /* while (select) */ + continue; + } /* switch (errno) */ + LOG(log_error, logtype_afpd, "read: %s", strerror(errno)); + stored = -1; + goto exit; + } /* (len == -1) */ + else if (len > 0) + stored += len; + else + break; + } /* while (stored < length) */ + +exit: + if (setnonblocking) { + if (setnonblock(socket, 0) != 0) + return -1; + } + + if (len == -1 && stored == 0) + /* last read or select got an error and we haven't got yet anything => return -1*/ + return -1; + return stored; +} + +/*! + * @brief convert an IPv4 or IPv6 address to a static string using inet_ntop + * + * IPv6 mapped IPv4 addresses are returned as IPv4 addreses eg + * ::ffff:10.0.0.0 is returned as "10.0.0.0". + * + * @param sa (r) pointer to an struct sockaddr + * + * @returns pointer to a static string cotaining the converted address as string.\n + * On error pointers to "0.0.0.0" or "::0" are returned. + */ +const char *getip_string(const struct sockaddr *sa) +{ + static char ip4[INET_ADDRSTRLEN]; + static char ip6[INET6_ADDRSTRLEN]; + + switch (sa->sa_family) { + + case AF_INET: { + const struct sockaddr_in *sai4 = (const struct sockaddr_in *)sa; + if ((inet_ntop(AF_INET, &(sai4->sin_addr), ip4, INET_ADDRSTRLEN)) == NULL) + return "0.0.0.0"; + return ip4; + } + case AF_INET6: { + const struct sockaddr_in6 *sai6 = (const struct sockaddr_in6 *)sa; + if ((inet_ntop(AF_INET6, &(sai6->sin6_addr), ip6, INET6_ADDRSTRLEN)) == NULL) + return "::0"; + + /* Deal with IPv6 mapped IPv4 addresses*/ + if ((memcmp(sai6->sin6_addr.s6_addr, ipv4mapprefix, sizeof(ipv4mapprefix))) == 0) + return (strrchr(ip6, ':') + 1); + return ip6; + } + default: + return "getip_string ERROR"; + } + + /* We never get here */ +} + +/*! + * @brief return port number from struct sockaddr + * + * @param sa (r) pointer to an struct sockaddr + * + * @returns port as unsigned int + */ +unsigned int getip_port(const struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { /* IPv4 */ + const struct sockaddr_in *sai4 = (const struct sockaddr_in *)sa; + return ntohs(sai4->sin_port); + } else { /* IPv6 */ + const struct sockaddr_in6 *sai6 = (const struct sockaddr_in6 *)sa; + return ntohs(sai6->sin6_port); + } + + /* We never get here */ +} + +/*! + * @brief apply netmask to IP (v4 or v6) + * + * Modifies IP address in sa->sin[6]_addr-s[6]_addr. The caller is responsible + * for passing a value for mask that is sensible to the passed address, + * eg 0 <= mask <= 32 for IPv4 or 0<= mask <= 128 for IPv6. mask > 32 for + * IPv4 is treated as mask = 32, mask > 128 is set to 128 for IPv6. + * + * @param ai (rw) pointer to an struct sockaddr + * @parma mask (r) number of maskbits + */ +void apply_ip_mask(struct sockaddr *sa, int mask) +{ + + switch (sa->sa_family) { + case AF_INET: { + if (mask >= 32) + return; + + struct sockaddr_in *si = (struct sockaddr_in *)sa; + uint32_t nmask = mask ? ~((1 << (32 - mask)) - 1) : 0; + si->sin_addr.s_addr &= htonl(nmask); + break; + } + case AF_INET6: { + if (mask >= 128) + return; + + int i, maskbytes, maskbits; + struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)sa; + + /* Deal with IPv6 mapped IPv4 addresses*/ + if ((memcmp(si6->sin6_addr.s6_addr, ipv4mapprefix, sizeof(ipv4mapprefix))) == 0) { + mask += 96; + if (mask >= 128) + return; + } + + maskbytes = (128 - mask) / 8; /* maskbytes really are those that will be 0'ed */ + maskbits = mask % 8; + + for (i = maskbytes - 1; i >= 0; i--) + si6->sin6_addr.s6_addr[15 - i] = 0; + if (maskbits) + si6->sin6_addr.s6_addr[15 - maskbytes] &= ~((1 << (8 - maskbits)) - 1); + break; + } + default: + break; + } +} + +/*! + * @brief compare IP addresses for equality + * + * @param sa1 (r) pointer to an struct sockaddr + * @param sa2 (r) pointer to an struct sockaddr + * + * @returns Addresses are converted to strings and compared with strcmp and + * the result of strcmp is returned. + * + * @note IPv6 mapped IPv4 addresses are treated as IPv4 addresses. + */ +int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2) +{ + int ret; + char *ip1; + const char *ip2; + + ip1 = strdup(getip_string(sa1)); + ip2 = getip_string(sa2); + + ret = strcmp(ip1, ip2); + + free(ip1); + + return ret; +} + +/*! + * Tokenize IP(4/6) addresses with an optional port into address and port + * + * @param ipurl (r) IP URL string + * @param address (w) IP address + * @param port (w) IP port + * + * @returns 0 on success, -1 on failure + * + * Tokenize IPv4, IPv4:port, IPv6, [IPv6] or [IPv6:port] URL into address and + * port and return two allocated strings with the address and the port. + * + * If the function returns 0, then address point to a newly allocated + * valid address string, port may either be NULL or point to a newly + * allocated port number. + * + * If the function returns -1, then the contents of address and port are + * undefined. + */ +int tokenize_ip_port(const char *ipurl, char **address, char **port) +{ + EC_INIT; + char *p = NULL; + char *s; + + AFP_ASSERT(ipurl && address && port); + EC_NULL( p = strdup(ipurl)); + + /* Either ipv4, ipv4:port, ipv6, [ipv6] or [ipv6]:port */ + + if (!strchr(p, ':')) { + /* IPv4 address without port */ + *address = p; + p = NULL; /* prevent free() */ + *port = NULL; + EC_EXIT_STATUS(0); + } + + /* Either ipv4:port, ipv6, [ipv6] or [ipv6]:port */ + + if (strchr(p, '.')) { + /* ipv4:port */ + *address = p; + p = strchr(p, ':'); + *p = '\0'; + EC_NULL( *port = strdup(p + 1)); + p = NULL; /* prevent free() */ + EC_EXIT_STATUS(0); + } + + /* Either ipv6, [ipv6] or [ipv6]:port */ + + if (p[0] != '[') { + /* ipv6 */ + *address = p; + p = NULL; /* prevent free() */ + *port = NULL; + EC_EXIT_STATUS(0); + } + + /* [ipv6] or [ipv6]:port */ + + EC_NULL( *address = strdup(p + 1) ); + + if ((s = strchr(*address, ']')) == NULL) { + LOG(log_error, logtype_dsi, "tokenize_ip_port: malformed ipv6 address %s\n", ipurl); + EC_FAIL; + } + *s = '\0'; + /* address now points to the ipv6 address without [] */ + + if (s[1] == ':') { + /* [ipv6]:port */ + EC_NULL( *port = strdup(s + 2) ); + } else { + /* [ipv6] */ + *port = NULL; + } + +EC_CLEANUP: + if (p) + free(p); + EC_EXIT; +} + +/** + * Allocate and initialize atalk socket event struct + **/ +struct asev *asev_init(int max) +{ + struct asev *asev = calloc(1, sizeof(struct asev)); + + if (asev == NULL) { + return NULL; + } + + /* Initialize with space for all possibly active fds */ + asev->fdset = calloc(max, sizeof(struct pollfd)); + asev->data = calloc(max, sizeof(struct asev_data)); + + if (asev->fdset == NULL || asev->data == NULL) { + free(asev->fdset); + free(asev->data); + free(asev); + return NULL; + } + + asev->max = max; + asev->used = 0; + + return asev; +} + +/** + * Add a fd to a dynamic pollfd array and associated data array + * + * This uses an additional array of struct polldata which stores type + * information (enum fdtype) and a pointer to anciliary user data. + **/ +bool asev_add_fd(struct asev *asev, + int fd, + enum asev_fdtype fdtype, + void *private) +{ + if (asev == NULL) { + return false; + } + + if (!(asev->used < asev->max)) { + return false; + } + + asev->fdset[asev->used].fd = fd; + asev->fdset[asev->used].events = POLLIN; + asev->data[asev->used].fdtype = fdtype; + asev->data[asev->used].private = private; + asev->used++; + + return true; +} + +/** + * Remove fd from asev + * + * @returns true if the fd was deleted, otherwise false + **/ +bool asev_del_fd(struct asev *asev, int fd) +{ + int i; + int numafter; + + if (asev == NULL) { + return false; + } + + if (asev->used == 0) { + LOG(log_error, logtype_cnid, "asev_del_fd: empty"); + return false; + } + + for (i = 0; i < asev->used; i++) { + /* + * Scan the array for a matching fd + */ + if (asev->fdset[i].fd == fd) { + /* + * found fd + */ + if ((i + 1) == asev->used) { + /* + * it's the last (or only) array element, simply null it + */ + asev->fdset[i].fd = -1; + asev->data[i].fdtype = 0; + asev->data[i].private = NULL; + } else { + /* + * Move down by one all subsequent elements + */ + numafter = asev->used - (i + 1); + memmove(&asev->fdset[i], &asev->fdset[i+1], + numafter * sizeof(struct pollfd)); + memmove(&asev->data[i], &asev->data[i+1], + numafter * sizeof(struct asev_data)); + } + asev->used--; + return true; + } + } + + return false; +} + +/* Length of the space taken up by a padded control message of length len */ +#ifndef CMSG_SPACE +#define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len)) +#endif + +/* + * Receive a fd on a suitable socket + * @args fd (r) PF_UNIX socket to receive on + * @args nonblocking (r) 0: fd is in blocking mode - 1: fd is nonblocking, poll for 1 sec + * @returns fd on success, -1 on error + */ +int recv_fd(int fd, int nonblocking) +{ + int ret; + struct msghdr msgh; + struct iovec iov[1]; + struct cmsghdr *cmsgp = NULL; + char buf[CMSG_SPACE(sizeof(int))]; + char dbuf[80]; + struct pollfd pollfds[1]; + + pollfds[0].fd = fd; + pollfds[0].events = POLLIN; + + memset(&msgh,0,sizeof(msgh)); + memset(buf,0,sizeof(buf)); + + msgh.msg_name = NULL; + msgh.msg_namelen = 0; + + msgh.msg_iov = iov; + msgh.msg_iovlen = 1; + + iov[0].iov_base = dbuf; + iov[0].iov_len = sizeof(dbuf); + + msgh.msg_control = buf; + msgh.msg_controllen = sizeof(buf); + + if (nonblocking) { + do { + ret = poll(pollfds, 1, 2000); /* poll 2 seconds, evtl. multipe times (EINTR) */ + } while ( ret == -1 && errno == EINTR ); + if (ret != 1) + return -1; + ret = recvmsg(fd, &msgh, 0); + } else { + do { + ret = recvmsg(fd, &msgh, 0); + } while ( ret == -1 && errno == EINTR ); + } + + if ( ret == -1 ) { + return -1; + } + + for ( cmsgp = CMSG_FIRSTHDR(&msgh); cmsgp != NULL; cmsgp = CMSG_NXTHDR(&msgh,cmsgp) ) { + if ( cmsgp->cmsg_level == SOL_SOCKET && cmsgp->cmsg_type == SCM_RIGHTS ) { + return *(int *) CMSG_DATA(cmsgp); + } + } + + if ( ret == sizeof (int) ) + errno = *(int *)dbuf; /* Rcvd errno */ + else + errno = ENOENT; /* Default errno */ + + return -1; +} + +/* + * Send a fd across a suitable socket + */ +int send_fd(int socket, int fd) +{ + int ret; + struct msghdr msgh; + struct iovec iov[1]; + struct cmsghdr *cmsgp = NULL; + char *buf; + size_t size; + int er=0; + + size = CMSG_SPACE(sizeof fd); + buf = malloc(size); + if (!buf) { + LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno)); + return -1; + } + + memset(&msgh,0,sizeof (msgh)); + memset(buf,0, size); + + msgh.msg_name = NULL; + msgh.msg_namelen = 0; + + msgh.msg_iov = iov; + msgh.msg_iovlen = 1; + + iov[0].iov_base = &er; + iov[0].iov_len = sizeof(er); + + msgh.msg_control = buf; + msgh.msg_controllen = size; + + cmsgp = CMSG_FIRSTHDR(&msgh); + cmsgp->cmsg_level = SOL_SOCKET; + cmsgp->cmsg_type = SCM_RIGHTS; + cmsgp->cmsg_len = CMSG_LEN(sizeof(fd)); + + *((int *)CMSG_DATA(cmsgp)) = fd; + msgh.msg_controllen = cmsgp->cmsg_len; + + do { + ret = sendmsg(socket,&msgh, 0); + } while ( ret == -1 && errno == EINTR ); + if (ret == -1) { + LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno)); + free(buf); + return -1; + } + free(buf); + return 0; +} diff --git a/libatalk/util/strdicasecmp.c b/libatalk/util/strdicasecmp.c new file mode 100644 index 0000000..ff7c077 --- /dev/null +++ b/libatalk/util/strdicasecmp.c @@ -0,0 +1,554 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +const int _diacasemap[] = { + /* map value name */ + 0 /* 0 NUL*/, + 1 /* 1 SOH*/, + 2 /* 2 STX*/, + 3 /* 3 ETX*/, + 4 /* 4 EOT*/, + 5 /* 5 ENQ*/, + 6 /* 6 ACK*/, + 7 /* 7 BEL*/, + 8 /* 8 BS*/, + 9 /* 9 HT*/, + 10 /* 10 NL*/, + 11 /* 11 VT*/, + 12 /* 12 NP*/, + 13 /* 13 CR*/, + 14 /* 14 SO*/, + 15 /* 15 SI*/, + 16 /* 16 DLE*/, + 17 /* 17 DC1*/, + 18 /* 18 DC2*/, + 19 /* 19 DC3*/, + 20 /* 20 DC4*/, + 21 /* 21 NAK*/, + 22 /* 22 SYN*/, + 23 /* 23 ETB*/, + 24 /* 24 CAN*/, + 25 /* 25 EM*/, + 26 /* 26 SUB*/, + 27 /* 27 ESC*/, + 28 /* 28 FS*/, + 29 /* 29 GS*/, + 30 /* 30 RS*/, + 31 /* 31 US*/, + 32 /* 32 SP*/, + 33 /* 33 ! */, + 34 /* 34 " */, + 35 /* 35 # */, + 36 /* 36 $ */, + 37 /* 37 % */, + 38 /* 38 & */, + 39 /* 39 ' */, + 40 /* 40 ( */, + 41 /* 41 ) */, + 42 /* 42 * */, + 43 /* 43 + */, + 44 /* 44 , */, + 45 /* 45 - */, + 46 /* 46 . */, + 47 /* 47 / */, + 48 /* 48 0 */, + 49 /* 49 1 */, + 50 /* 50 2 */, + 51 /* 51 3 */, + 52 /* 52 4 */, + 53 /* 53 5 */, + 54 /* 54 6 */, + 55 /* 55 7 */, + 56 /* 56 8 */, + 57 /* 57 9 */, + 58 /* 58 : */, + 59 /* 59 ; */, + 60 /* 60 < */, + 61 /* 61 = */, + 62 /* 62 > */, + 63 /* 63 ? */, + 64 /* 64 @ */, + 65 /* 65 A */, + 66 /* 66 B */, + 67 /* 67 C */, + 68 /* 68 D */, + 69 /* 69 E */, + 70 /* 70 F */, + 71 /* 71 G */, + 72 /* 72 H */, + 73 /* 73 I */, + 74 /* 74 J */, + 75 /* 75 K */, + 76 /* 76 L */, + 77 /* 77 M */, + 78 /* 78 N */, + 79 /* 79 O */, + 80 /* 80 P */, + 81 /* 81 Q */, + 82 /* 82 R */, + 83 /* 83 S */, + 84 /* 84 T */, + 85 /* 85 U */, + 86 /* 86 V */, + 87 /* 87 W */, + 88 /* 88 X */, + 89 /* 89 Y */, + 90 /* 90 Z */, + 91 /* 91 [ */, + 92 /* 92 \ */, + 93 /* 93 ] */, + 94 /* 94 ^ */, + 95 /* 95 _ */, + 96 /* 96 ` */, + 65 /* 97 a */, + 66 /* 98 b */, + 67 /* 99 c */, + 68 /* 100 d */, + 69 /* 101 e */, + 70 /* 102 f */, + 71 /* 103 g */, + 72 /* 104 h */, + 73 /* 105 i */, + 74 /* 106 j */, + 75 /* 107 k */, + 76 /* 108 l */, + 77 /* 109 m */, + 78 /* 110 n */, + 79 /* 111 o */, + 80 /* 112 p */, + 81 /* 113 q */, + 82 /* 114 r */, + 83 /* 115 s */, + 84 /* 116 t */, + 85 /* 117 u */, + 86 /* 118 v */, + 87 /* 119 w */, + 88 /* 120 x */, + 89 /* 121 y */, + 90 /* 122 z */, + 123 /* 123 { */, + 124 /* 124 | */, + 125 /* 125 } */, + 126 /* 126 ~ */, + 127 /* 127 DEL*/, + 128 /* 128 Adieresis*/, + 129 /* 129 Aring*/, + 130 /* 130 Ccedilla*/, + 131 /* 131 Eacute*/, + 132 /* 132 Ntilda*/, + 133 /* 133 Odieresis*/, + 134 /* 134 Udieresis*/, + 231 /* 135 aacute*/, + 203 /* 136 agrave*/, + 229 /* 137 acircumflex*/, + 128 /* 138 adieresis*/, + 204 /* 139 atilda*/, + 129 /* 140 aring*/, + 130 /* 141 ccedilla*/, + 131 /* 142 eacute*/, + 233 /* 143 egrave*/, + 230 /* 144 ecircumflex*/, + 232 /* 145 edieresis*/, + 234 /* 146 iacute*/, + 237 /* 147 igrave*/, + 235 /* 148 icircumflex*/, + 236 /* 149 idieresis*/, + 132 /* 150 ntilda*/, + 238 /* 151 oacute*/, + 241 /* 152 ograve*/, + 239 /* 153 ocircumflex*/, + 133 /* 154 odieresis*/, + 205 /* 155 otilda*/, + 242 /* 156 uacute*/, + 244 /* 157 ugrave*/, + 243 /* 158 ucircumflex*/, + 134 /* 159 udieresis*/, + 160 /* 160 daggar*/, + 161 /* 161 ring*/, + 162 /* 162 cent*/, + 163 /* 163 sterling*/, + 164 /* 164 section*/, + 165 /* 165 bullet*/, + 166 /* 166 paragraph*/, + 167 /* 167 germandbls*/, + 168 /* 168 registered*/, + 169 /* 169 copyright*/, + 170 /* 170 trademark*/, + 171 /* 171 acute*/, + 172 /* 172 dieresis*/, + 173 /* 173 notequal*/, + 174 /* 174 AE*/, + 175 /* 175 Oslash*/, + 176 /* 176 infinity*/, + 177 /* 177 plusminus*/, + 178 /* 178 lessequal*/, + 179 /* 179 greaterequal*/, + 180 /* 180 yen*/, + 181 /* 181 mu*/, + 198 /* 182 delta*/, + 183 /* 183 Sigma*/, + 184 /* 184 Pi*/, + 184 /* 185 pi*/, + 186 /* 186 intergral*/, + 187 /* 187 ordfeminine*/, + 188 /* 188 ordmasculine*/, + 189 /* 189 Omega*/, + 174 /* 190 ae*/, + 175 /* 191 oslash*/, + 192 /* 192 questiondown*/, + 193 /* 193 exclamdown*/, + 194 /* 194 not*/, + 195 /* 195 radical*/, + 196 /* 196 florin*/, + 197 /* 197 aprox*/, + 198 /* 198 Delta*/, + 199 /* 199 guillemotleft*/, + 200 /* 200 guillemotright*/, + 201 /* 201 ellipsis*/, + 202 /* 202 */, + 203 /* 203 Agrave*/, + 204 /* 204 Atilda*/, + 205 /* 205 Otilda*/, + 206 /* 206 OE*/, + 206 /* 207 oe*/, + 208 /* 208 endash*/, + 209 /* 209 emdash*/, + 210 /* 210 quotedblleft*/, + 211 /* 211 quotedblright*/, + 212 /* 212 quoteleft*/, + 213 /* 213 quoteright*/, + 214 /* 214 divide*/, + 215 /* 215 diamond*/, + 217 /* 216 ydieresis*/, + 217 /* 217 Ydieresis*/, + 218 /* 218 fraction*/, + 219 /* 219 currency*/, + 220 /* 220 guilsinglleft*/, + 221 /* 221 guilsinglright*/, + 222 /* 222 fi*/, + 223 /* 223 fl*/, + 224 /* 224 daggardbl*/, + 225 /* 225 periodcentered*/, + 226 /* 226 quotesinglbase*/, + 227 /* 227 quotedblbase*/, + 228 /* 228 perthousand*/, + 229 /* 229 Acircumflex*/, + 230 /* 230 Ecircumflex*/, + 231 /* 231 Aaccute*/, + 232 /* 232 Edieresis*/, + 233 /* 233 Egrave*/, + 234 /* 234 Iaccute*/, + 235 /* 235 Icircumflex*/, + 236 /* 236 Idieresis*/, + 237 /* 237 Igrave*/, + 238 /* 238 Oaccute*/, + 239 /* 239 Ocircumflex*/, + 240 /* 240 apple*/, + 241 /* 241 Ograve*/, + 242 /* 242 Uaccute*/, + 243 /* 243 Ucircumflex*/, + 244 /* 244 Ugrave*/, + 245 /* 245 dotlessi*/, + 246 /* 246 circumflex*/, + 247 /* 247 tilda*/, + 248 /* 248 macron*/, + 249 /* 249 breve*/, + 250 /* 250 dotaccent*/, + 251 /* 251 ring*/, + 252 /* 252 cedilla*/, + 253 /* 253 hungarumlaut*/, + 254 /* 254 ogonek*/, + 255 /* 255 caron*/, +}; + +const int _dialowermap[] = { + /* map value name */ + 0 /* 0 NUL*/, + 1 /* 1 SOH*/, + 2 /* 2 STX*/, + 3 /* 3 ETX*/, + 4 /* 4 EOT*/, + 5 /* 5 ENQ*/, + 6 /* 6 ACK*/, + 7 /* 7 BEL*/, + 8 /* 8 BS*/, + 9 /* 9 HT*/, + 10 /* 10 NL*/, + 11 /* 11 VT*/, + 12 /* 12 NP*/, + 13 /* 13 CR*/, + 14 /* 14 SO*/, + 15 /* 15 SI*/, + 16 /* 16 DLE*/, + 17 /* 17 DC1*/, + 18 /* 18 DC2*/, + 19 /* 19 DC3*/, + 20 /* 20 DC4*/, + 21 /* 21 NAK*/, + 22 /* 22 SYN*/, + 23 /* 23 ETB*/, + 24 /* 24 CAN*/, + 25 /* 25 EM*/, + 26 /* 26 SUB*/, + 27 /* 27 ESC*/, + 28 /* 28 FS*/, + 29 /* 29 GS*/, + 30 /* 30 RS*/, + 31 /* 31 US*/, + 32 /* 32 SP*/, + 33 /* 33 ! */, + 34 /* 34 " */, + 35 /* 35 # */, + 36 /* 36 $ */, + 37 /* 37 % */, + 38 /* 38 & */, + 39 /* 39 ' */, + 40 /* 40 ( */, + 41 /* 41 ) */, + 42 /* 42 * */, + 43 /* 43 + */, + 44 /* 44 , */, + 45 /* 45 - */, + 46 /* 46 . */, + 47 /* 47 / */, + 48 /* 48 0 */, + 49 /* 49 1 */, + 50 /* 50 2 */, + 51 /* 51 3 */, + 52 /* 52 4 */, + 53 /* 53 5 */, + 54 /* 54 6 */, + 55 /* 55 7 */, + 56 /* 56 8 */, + 57 /* 57 9 */, + 58 /* 58 : */, + 59 /* 59 ; */, + 60 /* 60 < */, + 61 /* 61 = */, + 62 /* 62 > */, + 63 /* 63 ? */, + 64 /* 64 @ */, + 97 /* 65 A */, + 98 /* 66 B */, + 99 /* 67 C */, + 100 /* 68 D */, + 101 /* 69 E */, + 102 /* 70 F */, + 103 /* 71 G */, + 104 /* 72 H */, + 105 /* 73 I */, + 106 /* 74 J */, + 107 /* 75 K */, + 108 /* 76 L */, + 109 /* 77 M */, + 110 /* 78 N */, + 111 /* 79 O */, + 112 /* 80 P */, + 113 /* 81 Q */, + 114 /* 82 R */, + 115 /* 83 S */, + 116 /* 84 T */, + 117 /* 85 U */, + 118 /* 86 V */, + 119 /* 87 W */, + 120 /* 88 X */, + 121 /* 89 Y */, + 122 /* 90 Z */, + 91 /* 91 [ */, + 92 /* 92 \ */, + 93 /* 93 ] */, + 94 /* 94 ^ */, + 95 /* 95 _ */, + 96 /* 96 ` */, + 97 /* 97 a */, + 98 /* 98 b */, + 99 /* 99 c */, + 100 /* 100 d */, + 101 /* 101 e */, + 102 /* 102 f */, + 103 /* 103 g */, + 104 /* 104 h */, + 105 /* 105 i */, + 106 /* 106 j */, + 107 /* 107 k */, + 108 /* 108 l */, + 109 /* 109 m */, + 110 /* 110 n */, + 111 /* 111 o */, + 112 /* 112 p */, + 113 /* 113 q */, + 114 /* 114 r */, + 115 /* 115 s */, + 116 /* 116 t */, + 117 /* 117 u */, + 118 /* 118 v */, + 119 /* 119 w */, + 120 /* 120 x */, + 121 /* 121 y */, + 122 /* 122 z */, + 123 /* 123 { */, + 124 /* 124 | */, + 125 /* 125 } */, + 126 /* 126 ~ */, + 127 /* 127 DEL*/, + 138 /* 128 Adieresis*/, + 140 /* 129 Aring*/, + 141 /* 130 Ccedilla*/, + 142 /* 131 Eacute*/, + 150 /* 132 Ntilda*/, + 154 /* 133 Odieresis*/, + 159 /* 134 Udieresis*/, + 135 /* 135 aacute*/, + 136 /* 136 agrave*/, + 137 /* 137 acircumflex*/, + 138 /* 138 adieresis*/, + 139 /* 139 atilda*/, + 140 /* 140 aring*/, + 141 /* 141 ccedilla*/, + 142 /* 142 eacute*/, + 143 /* 143 egrave*/, + 144 /* 144 ecircumflex*/, + 145 /* 145 edieresis*/, + 146 /* 146 iacute*/, + 147 /* 147 igrave*/, + 148 /* 148 icircumflex*/, + 149 /* 149 idieresis*/, + 132 /* 150 ntilda*/, + 151 /* 151 oacute*/, + 152 /* 152 ograve*/, + 153 /* 153 ocircumflex*/, + 154 /* 154 odieresis*/, + 155 /* 155 otilda*/, + 156 /* 156 uacute*/, + 157 /* 157 ugrave*/, + 158 /* 158 ucircumflex*/, + 159 /* 159 udieresis*/, + 160 /* 160 daggar*/, + 161 /* 161 ring*/, + 162 /* 162 cent*/, + 163 /* 163 sterling*/, + 164 /* 164 section*/, + 165 /* 165 bullet*/, + 166 /* 166 paragraph*/, + 167 /* 167 germandbls*/, + 168 /* 168 registered*/, + 169 /* 169 copyright*/, + 170 /* 170 trademark*/, + 171 /* 171 acute*/, + 172 /* 172 dieresis*/, + 173 /* 173 notequal*/, + 190 /* 174 AE*/, + 191 /* 175 Oslash*/, + 176 /* 176 infinity*/, + 177 /* 177 plusminus*/, + 178 /* 178 lessequal*/, + 179 /* 179 greaterequal*/, + 180 /* 180 yen*/, + 181 /* 181 mu*/, + 198 /* 182 delta*/, + 183 /* 183 Sigma*/, + 185 /* 184 Pi*/, + 185 /* 185 pi*/, + 186 /* 186 intergral*/, + 187 /* 187 ordfeminine*/, + 188 /* 188 ordmasculine*/, + 189 /* 189 Omega*/, + 190 /* 190 ae*/, + 191 /* 191 oslash*/, + 192 /* 192 questiondown*/, + 193 /* 193 exclamdown*/, + 194 /* 194 not*/, + 195 /* 195 radical*/, + 196 /* 196 florin*/, + 197 /* 197 aprox*/, + 198 /* 198 Delta*/, + 199 /* 199 guillemotleft*/, + 200 /* 200 guillemotright*/, + 201 /* 201 ellipsis*/, + 202 /* 202 */, + 136 /* 203 Agrave*/, + 139 /* 204 Atilda*/, + 155 /* 205 Otilda*/, + 207 /* 206 OE*/, + 207 /* 207 oe*/, + 208 /* 208 endash*/, + 209 /* 209 emdash*/, + 210 /* 210 quotedblleft*/, + 211 /* 211 quotedblright*/, + 212 /* 212 quoteleft*/, + 213 /* 213 quoteright*/, + 214 /* 214 divide*/, + 215 /* 215 diamond*/, + 217 /* 216 ydieresis*/, + 217 /* 217 Ydieresis*/, + 218 /* 218 fraction*/, + 219 /* 219 currency*/, + 220 /* 220 guilsinglleft*/, + 221 /* 221 guilsinglright*/, + 222 /* 222 fi*/, + 223 /* 223 fl*/, + 224 /* 224 daggardbl*/, + 225 /* 225 periodcentered*/, + 226 /* 226 quotesinglbase*/, + 227 /* 227 quotedblbase*/, + 228 /* 228 perthousand*/, + 137 /* 229 Acircumflex*/, + 144 /* 230 Ecircumflex*/, + 135 /* 231 Aacute*/, + 145 /* 232 Edieresis*/, + 143 /* 233 Egrave*/, + 146 /* 234 Iaccute*/, + 148 /* 235 Icircumflex*/, + 149 /* 236 Idieresis*/, + 147 /* 237 Igrave*/, + 151 /* 238 Oacute*/, + 153 /* 239 Ocircumflex*/, + 240 /* 240 apple*/, + 152 /* 241 Ograve*/, + 156 /* 242 Uacute*/, + 158 /* 243 Ucircumflex*/, + 157 /* 244 Ugrave*/, + 245 /* 245 dotlessi*/, + 246 /* 246 circumflex*/, + 247 /* 247 tilda*/, + 248 /* 248 macron*/, + 249 /* 249 breve*/, + 250 /* 250 dotaccent*/, + 251 /* 251 ring*/, + 252 /* 252 cedilla*/, + 253 /* 253 hungarumlaut*/, + 254 /* 254 ogonek*/, + 255 /* 255 caron*/, +}; + +int strdiacasecmp( const char *s1, const char *s2 ) +{ + while ( _diacasemap[ (unsigned char) *s1 ] == + _diacasemap[ (unsigned char) *s2++ ] ) { + if ( *s1++ == '\0' ) { + return( 0 ); + } + } + return( _diacasemap[ (unsigned char) *s1 ] - + _diacasemap[ (unsigned char) *--s2 ] ); +} + +int strndiacasecmp( const char *s1, const char *s2, size_t n ) +{ + while ( n > 0 && + _diacasemap[ (unsigned char) *s1 ] == + _diacasemap[ (unsigned char) *s2++ ] ) { + if ( *s1++ == '\0' ) { + return( 0 ); + } + n--; + } + + if (n == 0) + return 0; + return _diacasemap[ (unsigned char) *s1 ] - + _diacasemap[ (unsigned char) *--s2 ]; +} diff --git a/libatalk/util/unix.c b/libatalk/util/unix.c new file mode 100644 index 0000000..4572cad --- /dev/null +++ b/libatalk/util/unix.c @@ -0,0 +1,556 @@ +/* + Copyright (c) 2010 Frank Lahm + + 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. +*/ + +/*! + * @file + * Netatalk utility functions + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* close all FDs >= a specified value */ +static void closeall(int fd) +{ + int fdlimit = sysconf(_SC_OPEN_MAX); + + while (fd < fdlimit) + close(fd++); +} + +/*! + * Run command in a child and wait for it to finish + */ +int run_cmd(const char *cmd, char **cmd_argv) +{ + EC_INIT; + pid_t pid, wpid; + sigset_t sigs, oldsigs; + int status = 0; + + sigfillset(&sigs); + pthread_sigmask(SIG_SETMASK, &sigs, &oldsigs); + + if ((pid = fork()) < 0) { + LOG(log_error, logtype_default, "run_cmd: fork: %s", strerror(errno)); + return -1; + } + + if (pid == 0) { + /* child */ + closeall(3); + execvp("mv", cmd_argv); + } + + /* parent */ + while ((wpid = waitpid(pid, &status, 0)) < 0) { + if (errno == EINTR) + continue; + break; + } + if (wpid != pid) { + LOG(log_error, logtype_default, "waitpid(%d): %s", (int)pid, strerror(errno)); + EC_FAIL; + } + + if (WIFEXITED(status)) + status = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + status = WTERMSIG(status); + + LOG(log_note, logtype_default, "run_cmd(\"%s\"): status: %d", cmd, status); + +EC_CLEANUP: + if (status != 0) + ret = status; + pthread_sigmask(SIG_SETMASK, &oldsigs, NULL); + EC_EXIT; +} + +/*! + * Daemonize + * + * Fork, exit parent, setsid(), optionally chdir("/"), optionally close all fds + * + * returns -1 on failure, but you can't do much except exit in that case + * since we may already have forked + */ +int daemonize(int nochdir, int noclose) +{ + switch (fork()) { + case 0: + break; + case -1: + return -1; + default: + _exit(0); + } + + if (setsid() < 0) + return -1; + + switch (fork()) { + case 0: + break; + case -1: + return -1; + default: + _exit(0); + } + + if (!nochdir) + chdir("/"); + + if (!noclose) { + closeall(0); + open("/dev/null",O_RDWR); + dup(0); + dup(0); + } + + return 0; +} + +static uid_t saved_uid = -1; + +/* + * seteuid(0) and back, if either fails and panic != 0 we PANIC + */ +void become_root(void) +{ + if (getuid() == 0) { + saved_uid = geteuid(); + if (seteuid(0) != 0) + AFP_PANIC("Can't seteuid(0)"); + } +} + +void unbecome_root(void) +{ + if (getuid() == 0) { + if (saved_uid == -1 || seteuid(saved_uid) < 0) + AFP_PANIC("Can't seteuid back"); + saved_uid = -1; + } +} + +/*! + * @brief get cwd in static buffer + * + * @returns pointer to path or pointer to error messages on error + */ +const char *getcwdpath(void) +{ + static char cwd[MAXPATHLEN + 1]; + char *p; + + if ((p = getcwd(cwd, MAXPATHLEN)) != NULL) + return p; + else + return strerror(errno); +} + +/*! + * @brief Request absolute path + * + * @returns Absolute filesystem path to object + */ +const char *fullpathname(const char *name) +{ + static char wd[MAXPATHLEN + 1]; + + if (name[0] == '/') + return name; + + if (getcwd(wd , MAXPATHLEN)) { + strlcat(wd, "/", MAXPATHLEN); + strlcat(wd, name, MAXPATHLEN); + } else { + strlcpy(wd, name, MAXPATHLEN); + } + + return wd; +} + +/*! + * Takes a buffer with a path, strips slashs, returns basename + * + * @param p (rw) path + * path may be + * "[/][dir/[...]]file" + * or + * "[/][dir/[...]]dir/[/]" + * Result is "file" or "dir" + * + * @returns pointer to basename in path buffer, buffer is possibly modified + */ +char *stripped_slashes_basename(char *p) +{ + int i = strlen(p) - 1; + while (i > 0 && p[i] == '/') + p[i--] = 0; + return (strrchr(p, '/') ? strrchr(p, '/') + 1 : p); +} + +/********************************************************************************* + * chdir(), chmod(), chown(), stat() wrappers taking an additional option. + * Currently the only used options are O_NOFOLLOW, used to switch between symlink + * behaviour, and O_NETATALK_ACL for ochmod() indicating chmod_acl() shall be + * called which does special ACL handling depending on the filesytem + *********************************************************************************/ + +int ostat(const char *path, struct stat *buf, int options) +{ + if (options & O_NOFOLLOW) + return lstat(path, buf); + else + return stat(path, buf); +} + +int ochown(const char *path, uid_t owner, gid_t group, int options) +{ + if (options & O_NOFOLLOW) + return lchown(path, owner, group); + else + return chown(path, owner, group); +} + +/*! + * chmod() wrapper for symlink and ACL handling + * + * @param path (r) path + * @param mode (r) requested mode + * @param sb (r) stat() of path or NULL + * @param option (r) O_NOFOLLOW | O_NETATALK_ACL + * + * Options description: + * O_NOFOLLOW: don't chmod() symlinks, do nothing, return 0 + * O_NETATALK_ACL: call chmod_acl() instead of chmod() + * O_IGNORE: ignore chmod() request, directly return 0 + */ +int ochmod(char *path, mode_t mode, const struct stat *st, int options) +{ + struct stat sb; + + if (options & O_IGNORE) + return 0; + + if (!st) { + if (lstat(path, &sb) != 0) + return -1; + st = &sb; + } + + if (options & O_NOFOLLOW) + if (S_ISLNK(st->st_mode)) + return 0; + + if (options & O_NETATALK_ACL) { + return chmod_acl(path, mode); + } else { + return chmod(path, mode); + } +} + +/* + * @brief ostat/fsstatat multiplexer + * + * ostatat mulitplexes ostat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored. + * + * @param dirfd (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD + * @param path (r) pathname + * @param st (rw) pointer to struct stat + */ +int ostatat(int dirfd, const char *path, struct stat *st, int options) +{ +#ifdef HAVE_ATFUNCS + if (dirfd == -1) + dirfd = AT_FDCWD; + return fstatat(dirfd, path, st, (options & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0); +#else + return ostat(path, st, options); +#endif + + /* DEADC0DE */ + return -1; +} + +/*! + * @brief symlink safe chdir replacement + * + * Only chdirs to dir if it doesn't contain symlinks or if symlink checking + * is disabled + * + * @returns 1 if a path element is a symlink, 0 otherwise, -1 on syserror + */ +int ochdir(const char *dir, int options) +{ + char buf[MAXPATHLEN+1]; + char cwd[MAXPATHLEN+1]; + char *test; + int i; + + if (!(options & O_NOFOLLOW)) + return chdir(dir); + + /* + dir is a canonical path (without "../" "./" "//" ) + but may end with a / + */ + *cwd = 0; + if (*dir != '/') { + if (getcwd(cwd, MAXPATHLEN) == NULL) + return -1; + } + if (chdir(dir) != 0) + return -1; + + /* + * Cases: + * chdir request | realpath result | ret + * (after getwcwd) | | + * ======================================= + * /a/b/. | /a/b | 0 + * /a/b/. | /c | 1 + * /a/b/. | /c/d/e/f | 1 + */ + if (getcwd(buf, MAXPATHLEN) == NULL) + return 1; + + i = 0; + if (*cwd) { + /* relative path requested, + * Same directory? + */ + for (; cwd[i]; i++) { + if (buf[i] != cwd[i]) + return 1; + } + if (buf[i]) { + if (buf[i] != '/') + return 1; + i++; + } + } + + test = &buf[i]; + for (i = 0; test[i]; i++) { + if (test[i] != dir[i]) { + return 1; + } + } + /* trailing '/' ? */ + if (!dir[i]) + return 0; + + if (dir[i] != '/') + return 1; + + i++; + if (dir[i]) + return 1; + + return 0; +} + +/*! + * Store n random bytes an buf + */ +void randombytes(void *buf, int n) +{ + char *p = (char *)buf; + int fd, i; + struct timeval tv; + + if ((fd = open("/dev/urandom", O_RDONLY)) != -1) { + /* generate from /dev/urandom */ + if (read(fd, buf, n) != n) { + close(fd); + fd = -1; + } else { + close(fd); + /* fd now != -1, so srandom wont be called below */ + } + } + + if (fd == -1) { + gettimeofday(&tv, NULL); + srandom((unsigned int)tv.tv_usec); + for (i=0 ; i < n ; i++) + p[i] = random() & 0xFF; + } + + return; +} + +int gmem(gid_t gid, int ngroups, gid_t *groups) +{ + int i; + + for ( i = 0; i < ngroups; i++ ) { + if ( groups[ i ] == gid ) { + return( 1 ); + } + } + return( 0 ); +} + +/* + * realpath() replacement that always allocates storage for returned path + */ +char *realpath_safe(const char *path) +{ + char *resolved_path; + +#ifdef REALPATH_TAKES_NULL + if ((resolved_path = realpath(path, NULL)) == NULL) { + LOG(log_debug, logtype_afpd, "realpath() cannot resolve path \"%s\"", path); + return NULL; + } + return resolved_path; +#else + if ((resolved_path = malloc(MAXPATHLEN+1)) == NULL) + return NULL; + if (realpath(path, resolved_path) == NULL) { + free(resolved_path); + LOG(log_debug, logtype_afpd, "realpath() cannot resolve path \"%s\"", path); + return NULL; + } + /* Safe some memory */ + char *tmp; + if ((tmp = strdup(resolved_path)) == NULL) { + free(resolved_path); + return NULL; + } + free(resolved_path); + resolved_path = tmp; + return resolved_path; +#endif +} + +/** + * Returns pointer to static buffer with basename of path + **/ +const char *basename_safe(const char *path) +{ + static char buf[MAXPATHLEN+1]; + strlcpy(buf, path, MAXPATHLEN); + return basename(buf); +} + +/** + * extended strtok allows the quoted strings + * modified strtok.c in glibc 2.0.6 + **/ +char *strtok_quote(char *s, const char *delim) +{ + static char *olds = NULL; + char *token; + + if (s == NULL) + s = olds; + + /* Scan leading delimiters. */ + s += strspn (s, delim); + if (*s == '\0') + return NULL; + + /* Find the end of the token. */ + token = s; + + if (token[0] == '\"') { + token++; + s = strpbrk (token, "\""); + } else { + s = strpbrk (token, delim); + } + + if (s == NULL) { + /* This token finishes the string. */ + olds = strchr (token, '\0'); + } else { + /* Terminate the token and make OLDS point past it. */ + *s = '\0'; + olds = s + 1; + } + return token; +} + +int set_groups(AFPObj *obj, struct passwd *pwd) +{ + if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) + LOG(log_error, logtype_afpd, "initgroups(%s, %d): %s", pwd->pw_name, pwd->pw_gid, strerror(errno)); + + if ((obj->ngroups = getgroups(0, NULL)) < 0) { + LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno)); + return -1; + } + + if (obj->groups) + free(obj->groups); + if (NULL == (obj->groups = calloc(obj->ngroups, sizeof(gid_t))) ) { + LOG(log_error, logtype_afpd, "login: %s calloc: %d", obj->ngroups); + return -1; + } + + if ((obj->ngroups = getgroups(obj->ngroups, obj->groups)) < 0 ) { + LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno)); + return -1; + } + + return 0; +} + +#define GROUPSTR_BUFSIZE 1024 +const char *print_groups(int ngroups, gid_t *groups) +{ + static char groupsstr[GROUPSTR_BUFSIZE]; + int i; + char *s = groupsstr; + + if (ngroups == 0) + return "-"; + + for (i = 0; (i < ngroups) && (s < &groupsstr[GROUPSTR_BUFSIZE]); i++) { + s += snprintf(s, &groupsstr[GROUPSTR_BUFSIZE] - s, " %u", groups[i]); + } + + return groupsstr; +} diff --git a/libatalk/vfs/Makefile.am b/libatalk/vfs/Makefile.am new file mode 100644 index 0000000..aa62aeb --- /dev/null +++ b/libatalk/vfs/Makefile.am @@ -0,0 +1,9 @@ +# Makefile.am for libatalk/vfs/ + +noinst_LTLIBRARIES = libvfs.la + +libvfs_la_SOURCES = vfs.c unix.c ea_ad.c ea_sys.c extattr.c + +if HAVE_ACLS +libvfs_la_SOURCES += acl.c +endif diff --git a/libatalk/vfs/Makefile.in b/libatalk/vfs/Makefile.in new file mode 100644 index 0000000..5863f32 --- /dev/null +++ b/libatalk/vfs/Makefile.in @@ -0,0 +1,672 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libatalk/vfs/ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_ACLS_TRUE@am__append_1 = acl.c +subdir = libatalk/vfs +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/macros/afs-check.m4 \ + $(top_srcdir)/macros/ax_pthread.m4 \ + $(top_srcdir)/macros/cnid-backend.m4 \ + $(top_srcdir)/macros/config-checks.m4 \ + $(top_srcdir)/macros/db3-check.m4 \ + $(top_srcdir)/macros/grep-check.m4 \ + $(top_srcdir)/macros/gssapi-check.m4 \ + $(top_srcdir)/macros/iconv.m4 \ + $(top_srcdir)/macros/largefile-check.m4 \ + $(top_srcdir)/macros/libgcrypt.m4 \ + $(top_srcdir)/macros/libtool.m4 \ + $(top_srcdir)/macros/ltoptions.m4 \ + $(top_srcdir)/macros/ltsugar.m4 \ + $(top_srcdir)/macros/ltversion.m4 \ + $(top_srcdir)/macros/lt~obsolete.m4 \ + $(top_srcdir)/macros/netatalk.m4 \ + $(top_srcdir)/macros/pam-check.m4 \ + $(top_srcdir)/macros/perl-check.m4 \ + $(top_srcdir)/macros/ps-check.m4 \ + $(top_srcdir)/macros/quota-check.m4 \ + $(top_srcdir)/macros/ssl-check.m4 \ + $(top_srcdir)/macros/summary.m4 \ + $(top_srcdir)/macros/tcp-wrappers.m4 \ + $(top_srcdir)/macros/util.m4 $(top_srcdir)/macros/zeroconf.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libvfs_la_LIBADD = +am__libvfs_la_SOURCES_DIST = vfs.c unix.c ea_ad.c ea_sys.c extattr.c \ + acl.c +@HAVE_ACLS_TRUE@am__objects_1 = acl.lo +am_libvfs_la_OBJECTS = vfs.lo unix.lo ea_ad.lo ea_sys.lo extattr.lo \ + $(am__objects_1) +libvfs_la_OBJECTS = $(am_libvfs_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libvfs_la_SOURCES) +DIST_SOURCES = $(am__libvfs_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACL_LIBS = @ACL_LIBS@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AVAHI_CFLAGS = @AVAHI_CFLAGS@ +AVAHI_LIBS = @AVAHI_LIBS@ +AVAHI_TPOLL_CFLAGS = @AVAHI_TPOLL_CFLAGS@ +AVAHI_TPOLL_LIBS = @AVAHI_TPOLL_LIBS@ +AWK = @AWK@ +BDB_BIN = @BDB_BIN@ +BDB_CFLAGS = @BDB_CFLAGS@ +BDB_LIBS = @BDB_LIBS@ +BDB_PATH = @BDB_PATH@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ +DBUS_GLIB_LIBS = @DBUS_GLIB_LIBS@ +DBUS_GTHREAD_CFLAGS = @DBUS_GTHREAD_CFLAGS@ +DBUS_GTHREAD_LIBS = @DBUS_GTHREAD_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFAULT_CNID_SCHEME = @DEFAULT_CNID_SCHEME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCBOOK_ROOT = @DOCBOOK_ROOT@ +DSYMUTIL = @DSYMUTIL@ +DTRACE_LIBS = @DTRACE_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LDFLAGS = @GSSAPI_LDFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +ICONV_CFLAGS = @ICONV_CFLAGS@ +ICONV_LIBS = @ICONV_LIBS@ +INIT_DIR = @INIT_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_CFLAGS = @LDAP_CFLAGS@ +LDAP_LDFLAGS = @LDAP_LDFLAGS@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ +LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NETATALK_VERSION = @NETATALK_VERSION@ +NETA_LDCONFIG = @NETA_LDCONFIG@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OVERWRITE_CONFIG = @OVERWRITE_CONFIG@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAMDIR = @PAMDIR@ +PAM_ACCOUNT = @PAM_ACCOUNT@ +PAM_AUTH = @PAM_AUTH@ +PAM_CFLAGS = @PAM_CFLAGS@ +PAM_DIRECTIVE = @PAM_DIRECTIVE@ +PAM_LIBS = @PAM_LIBS@ +PAM_PASSWORD = @PAM_PASSWORD@ +PAM_SESSION = @PAM_SESSION@ +PATH_NETATALK_LOCK = @PATH_NETATALK_LOCK@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGCONFDIR = @PKGCONFDIR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PS = @PS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SERVERTEXT = @SERVERTEXT@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +TDB_CFLAGS = @TDB_CFLAGS@ +TDB_LIBS = @TDB_LIBS@ +TRACKER_CFLAGS = @TRACKER_CFLAGS@ +TRACKER_LIBS = @TRACKER_LIBS@ +TRACKER_MINER_CFLAGS = @TRACKER_MINER_CFLAGS@ +TRACKER_MINER_LIBS = @TRACKER_MINER_LIBS@ +UAMS_PATH = @UAMS_PATH@ +VERSION = @VERSION@ +WRAP_LIBS = @WRAP_LIBS@ +XSLTPROC = @XSLTPROC@ +XSLTPROC_FLAGS = @XSLTPROC_FLAGS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZEROCONF_CFLAGS = @ZEROCONF_CFLAGS@ +ZEROCONF_LIBS = @ZEROCONF_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +atalk_cv_have_dtrace = @atalk_cv_have_dtrace@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +compiled_backends = @compiled_backends@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libvfs.la +libvfs_la_SOURCES = vfs.c unix.c ea_ad.c ea_sys.c extattr.c \ + $(am__append_1) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libatalk/vfs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libatalk/vfs/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libvfs.la: $(libvfs_la_OBJECTS) $(libvfs_la_DEPENDENCIES) $(EXTRA_libvfs_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libvfs_la_OBJECTS) $(libvfs_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ea_ad.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ea_sys.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extattr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfs.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# 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/libatalk/vfs/acl.c b/libatalk/vfs/acl.c new file mode 100644 index 0000000..027aba1 --- /dev/null +++ b/libatalk/vfs/acl.c @@ -0,0 +1,137 @@ +/* + Copyright (c) 2009 Frank Lahm + Copyright (c) 2010 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_NFSV4_ACLS + +/* Removes all non-trivial ACLs from object. Returns full AFPERR code. */ +int remove_acl_vfs(const char *name) +{ + int ret,i, ace_count, trivial_aces, new_aces_count; + ace_t *old_aces = NULL; + ace_t *new_aces = NULL; + + LOG(log_debug9, logtype_afpd, "remove_acl: BEGIN"); + + /* Get existing ACL and count trivial ACEs */ + if ((ace_count = get_nfsv4_acl(name, &old_aces)) == -1) + return AFPERR_MISC; + trivial_aces = 0; + for ( i=0; i < ace_count; i++) { + if (old_aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE)) + trivial_aces++; + } + + /* malloc buffer for new ACL */ + if ((new_aces = malloc(trivial_aces * sizeof(ace_t))) == NULL) { + LOG(log_error, logtype_afpd, "remove_acl: malloc %s", strerror(errno)); + ret = AFPERR_MISC; + goto exit; + } + + /* Now copy the trivial ACEs */ + new_aces_count = 0; + for (i=0; i < ace_count; i++) { + if (old_aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE)) { + memcpy(&new_aces[new_aces_count], &old_aces[i], sizeof(ace_t)); + new_aces_count++; + } + } + + if ( (acl(name, ACE_SETACL, trivial_aces, new_aces)) == 0) + ret = AFP_OK; + else { + LOG(log_error, logtype_afpd, "set_acl: error setting acl: %s", strerror(errno)); + if (errno == (EACCES | EPERM)) + ret = AFPERR_ACCESS; + else if (errno == ENOENT) + ret = AFPERR_NOITEM; + else + ret = AFPERR_MISC; + } + +exit: + free(old_aces); + free(new_aces); + + LOG(log_debug9, logtype_afpd, "remove_acl: END"); + return ret; +} + +#endif /* HAVE_NFSV4_ACLS */ + +#ifdef HAVE_POSIX_ACLS +/*! + * Remove any ACL_USER, ACL_GROUP, ACL_MASK or ACL_TYPE_DEFAULT ACEs from an object + * + * @param name (r) filesystem object name + * + * @returns AFP error code, AFP_OK (= 0) on success, AFPERR_MISC on error + */ +int remove_acl_vfs(const char *name) +{ + EC_INIT; + + struct stat st; + acl_t acl = NULL; + acl_entry_t e; + acl_tag_t tag; + int entry_id = ACL_FIRST_ENTRY; + + + /* Remove default ACL if it's a dir */ + EC_ZERO_ERR(stat(name, &st), AFPERR_MISC); + if (S_ISDIR(st.st_mode)) { + EC_NULL_LOG_ERR(acl = acl_init(0), AFPERR_MISC); + EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, acl), AFPERR_MISC); + EC_ZERO_LOG_ERR(acl_free(acl), AFPERR_MISC); + acl = NULL; + } + + /* Now get ACL and remove ACL_MASK, ACL_USER or ACL_GROUP entries, then re-set + * the ACL again. acl_calc_mask() must not be called because there is no need + * for an ACL_MASK entry in a basic ACL. */ + EC_NULL_LOG_ERR(acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC); + for ( ; acl_get_entry(acl, entry_id, &e) == 1; entry_id = ACL_NEXT_ENTRY) { + EC_ZERO_LOG_ERR(acl_get_tag_type(e, &tag), AFPERR_MISC); + if (tag == ACL_USER || tag == ACL_GROUP || tag == ACL_MASK) + EC_ZERO_LOG_ERR(acl_delete_entry(acl, e), AFPERR_MISC); + } + EC_ZERO_LOG_ERR(acl_valid(acl), AFPERR_MISC); + EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, acl), AFPERR_MISC); + +EC_CLEANUP: + if (errno == ENOENT) EC_STATUS(0); + if (acl) acl_free(acl); + + EC_EXIT; +} +#endif /* HAVE_POSIX_ACLS */ diff --git a/libatalk/vfs/ea_ad.c b/libatalk/vfs/ea_ad.c new file mode 100644 index 0000000..5b99a5c --- /dev/null +++ b/libatalk/vfs/ea_ad.c @@ -0,0 +1,1771 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Store Extended Attributes inside .AppleDouble folders as follows: + * + * filename "fileWithEAs" with EAs "testEA1" and "testEA2" + * + * - create header with with the format struct adouble_ea_ondisk, the file is written to + * ".AppleDouble/fileWithEAs::EA" + * - store EAs in files "fileWithEAs::EA::testEA1" and "fileWithEAs::EA::testEA2" + */ + +/* + * Build mode for EA header from file mode + */ +static inline mode_t ea_header_mode(mode_t mode) +{ + /* Same as ad_hf_mode(mode) */ + mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); + /* Owner must be able to open, read and w-lock it, in order to chmod from eg 0000 -> 0xxxx*/ + mode |= S_IRUSR | S_IWUSR; + return mode; +} + +/* + * Build mode for EA file from file mode + */ +static inline mode_t ea_mode(mode_t mode) +{ + /* Same as ad_hf_mode(mode) */ + mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); + return mode; +} + +/* + Taken form afpd/desktop.c +*/ +static char *mtoupath(const struct vol *vol, const char *mpath) +{ + static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */ + const char *m; + char *u; + size_t inplen; + size_t outlen; + uint16_t flags = CONV_ESCAPEHEX; + + if (!mpath) + return NULL; + + if ( *mpath == '\0' ) { + return( "." ); + } + + m = mpath; + u = upath; + + inplen = strlen(m); + outlen = MAXPATHLEN; + + if ((size_t)-1 == (outlen = convert_charset(CH_UTF8_MAC, + vol->v_volcharset, + vol->v_maccharset, + m, inplen, u, outlen, &flags)) ) { + return NULL; + } + + return( upath ); +} + + +/* + * Function: unpack_header + * + * Purpose: unpack and verify header file data buffer at ea->ea_data into struct ea + * + * Arguments: + * + * ea (rw) handle to struct ea + * + * Returns: 0 on success, -1 on error + * + * Effects: + * + * Verifies magic and version. + */ +static int unpack_header(struct ea * restrict ea) +{ + int ret = 0; + unsigned int count = 0; + uint16_t uint16; + uint32_t uint32; + char *buf; + + /* Check magic and version */ + buf = ea->ea_data; + memcpy(&uint32, buf, sizeof(uint32_t)); + if (uint32 != htonl(EA_MAGIC)) { + LOG(log_error, logtype_afpd, "unpack_header: wrong magic 0x%08x", uint32); + ret = -1; + goto exit; + } + buf += 4; + memcpy(&uint16, buf, sizeof(uint16_t)); + if (uint16 != htons(EA_VERSION)) { + LOG(log_error, logtype_afpd, "unpack_header: wrong version 0x%04x", uint16); + ret = -1; + goto exit; + } + buf += 2; + + /* Get EA count */ + memcpy(&uint16, buf, sizeof(uint16_t)); + ea->ea_count = ntohs(uint16); + LOG(log_debug, logtype_afpd, "unpack_header: number of EAs: %u", ea->ea_count); + buf += 2; + + if (ea->ea_count == 0) + return 0; + + /* Allocate storage for the ea_entries array */ + ea->ea_entries = malloc(sizeof(struct ea_entry) * ea->ea_count); + if ( ! ea->ea_entries) { + LOG(log_error, logtype_afpd, "unpack_header: OOM"); + ret = -1; + goto exit; + } + + buf = ea->ea_data + EA_HEADER_SIZE; + while (count < ea->ea_count) { + memcpy(&uint32, buf, 4); /* EA size */ + buf += 4; + (*(ea->ea_entries))[count].ea_size = ntohl(uint32); + (*(ea->ea_entries))[count].ea_name = strdup(buf); + if (! (*(ea->ea_entries))[count].ea_name) { + LOG(log_error, logtype_afpd, "unpack_header: OOM"); + ret = -1; + goto exit; + } + (*(ea->ea_entries))[count].ea_namelen = strlen((*(ea->ea_entries))[count].ea_name); + buf += (*(ea->ea_entries))[count].ea_namelen + 1; + + LOG(log_maxdebug, logtype_afpd, "unpack_header: entry no:%u,\"%s\", size: %u, namelen: %u", count, + (*(ea->ea_entries))[count].ea_name, + (*(ea->ea_entries))[count].ea_size, + (*(ea->ea_entries))[count].ea_namelen); + + count++; + } + +exit: + return ret; +} + +/* + * Function: pack_header + * + * Purpose: pack everything from struct ea into buffer at ea->ea_data + * + * Arguments: + * + * ea (rw) handle to struct ea + * + * Returns: 0 on success, -1 on error + * + * Effects: + * + * adjust ea->ea_count in case an ea entry deletetion is detected + */ +static int pack_header(struct ea * restrict ea) +{ + unsigned int count = 0, eacount = 0; + uint16_t uint16; + uint32_t uint32; + size_t bufsize = EA_HEADER_SIZE; + + char *buf = ea->ea_data + EA_HEADER_SIZE; + + LOG(log_debug, logtype_afpd, "pack_header('%s'): ea_count: %u, ea_size: %u", + ea->filename, ea->ea_count, ea->ea_size); + + if (ea->ea_count == 0) + /* nothing to do, magic, version and count are still valid in buffer */ + return 0; + + while(count < ea->ea_count) { /* the names */ + /* Check if its a deleted entry */ + if ( ! ((*ea->ea_entries)[count].ea_name)) { + count++; + continue; + } + + bufsize += (*(ea->ea_entries))[count].ea_namelen + 1; + count++; + eacount++; + } + + bufsize += (eacount * 4); /* header + ea_size for each EA */ + if (bufsize > ea->ea_size) { + /* we must realloc */ + if ( ! (buf = realloc(ea->ea_data, bufsize)) ) { + LOG(log_error, logtype_afpd, "pack_header: OOM"); + return -1; + } + ea->ea_data = buf; + } + ea->ea_size = bufsize; + + /* copy count */ + uint16 = htons(eacount); + memcpy(ea->ea_data + EA_COUNT_OFF, &uint16, 2); + + count = 0; + buf = ea->ea_data + EA_HEADER_SIZE; + while (count < ea->ea_count) { + /* Check if its a deleted entry */ + if ( ! ((*ea->ea_entries)[count].ea_name)) { + count++; + continue; + } + + /* First: EA size */ + uint32 = htonl((*(ea->ea_entries))[count].ea_size); + memcpy(buf, &uint32, 4); + buf += 4; + + /* Second: EA name as C-string */ + strcpy(buf, (*(ea->ea_entries))[count].ea_name); + buf += (*(ea->ea_entries))[count].ea_namelen + 1; + + LOG(log_maxdebug, logtype_afpd, "pack_header: entry no:%u,\"%s\", size: %u, namelen: %u", count, + (*(ea->ea_entries))[count].ea_name, + (*(ea->ea_entries))[count].ea_size, + (*(ea->ea_entries))[count].ea_namelen); + + count++; + } + + ea->ea_count = eacount; + + LOG(log_debug, logtype_afpd, "pack_header('%s'): ea_count: %u, ea_size: %u", + ea->filename, ea->ea_count, ea->ea_size); + + return 0; +} + +/* + * Function: ea_addentry + * + * Purpose: add one EA into ea->ea_entries[] + * + * Arguments: + * + * ea (rw) pointer to struct ea + * attruname (r) name of EA + * attrsize (r) size of ea + * bitmap (r) bitmap from FP func + * + * Returns: new number of EA entries, -1 on error + * + * Effects: + * + * Grow array ea->ea_entries[]. If ea->ea_entries is still NULL, start allocating. + * Otherwise realloc and put entry at the end. Increments ea->ea_count. + */ +static int ea_addentry(struct ea * restrict ea, + const char * restrict attruname, + size_t attrsize, + int bitmap) +{ + int ea_existed = 0; + unsigned int count = 0; + void *tmprealloc; + + /* First check if an EA of the requested name already exist */ + if (ea->ea_count > 0) { + while (count < ea->ea_count) { + if (strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) { + ea_existed = 1; + LOG(log_debug, logtype_afpd, "ea_addentry('%s', bitmap:0x%x): exists", attruname, bitmap); + if (bitmap & kXAttrCreate) + /* its like O_CREAT|O_EXCL -> fail */ + return -1; + (*(ea->ea_entries))[count].ea_size = attrsize; + return 0; + } + count++; + } + } + + if ((bitmap & kXAttrReplace) && ! ea_existed) + /* replace was requested, but EA didn't exist */ + return -1; + + if (ea->ea_count == 0) { + ea->ea_entries = malloc(sizeof(struct ea_entry)); + if ( ! ea->ea_entries) { + LOG(log_error, logtype_afpd, "ea_addentry: OOM"); + return -1; + } + } else if (! ea_existed) { + tmprealloc = realloc(ea->ea_entries, sizeof(struct ea_entry) * (ea->ea_count + 1)); + if ( ! tmprealloc) { + LOG(log_error, logtype_afpd, "ea_addentry: OOM"); + return -1; + } + ea->ea_entries = tmprealloc; + } + + /* We've grown the array, now store the entry */ + (*(ea->ea_entries))[ea->ea_count].ea_size = attrsize; + (*(ea->ea_entries))[ea->ea_count].ea_name = strdup(attruname); + if ( ! (*(ea->ea_entries))[ea->ea_count].ea_name) { + LOG(log_error, logtype_afpd, "ea_addentry: OOM"); + goto error; + } + (*(ea->ea_entries))[ea->ea_count].ea_namelen = strlen(attruname); + + ea->ea_count++; + return ea->ea_count; + +error: + if (ea->ea_count == 0 && ea->ea_entries) { + /* We just allocated storage but had an error somewhere -> free storage*/ + free(ea->ea_entries); + ea->ea_entries = NULL; + } + ea->ea_count = 0; + return -1; +} + +/* + * Function: create_ea_header + * + * Purpose: create EA header file, only called from ea_open + * + * Arguments: + * + * uname (r) filename for which we have to create a header + * ea (rw) ea handle with already allocated storage pointed to + * by ea->ea_data + * + * Returns: fd of open header file on success, -1 on error, errno semantics: + * EEXIST: open with O_CREAT | O_EXCL failed + * + * Effects: + * + * Creates EA header file and initialize ea->ea_data buffer. + * Possibe race condition with other afpd processes: + * we were called because header file didn't exist in eg. ea_open. We then + * try to create a file with O_CREAT | O_EXCL, but the whole process in not atomic. + * What do we do then? Someone else is in the process of creating the header too, but + * it might not have finished it. That means we cant just open, read and use it! + * We therefor currently just break with an error. + * On return the header file is still r/w locked. + */ +static int create_ea_header(const char * restrict uname, + struct ea * restrict ea) +{ + int fd = -1, err = 0; + char *ptr; + uint16_t uint16; + uint32_t uint32; + + if ((fd = open(uname, O_RDWR | O_CREAT | O_EXCL, 0666 & ~ea->vol->v_umask)) == -1) { + LOG(log_error, logtype_afpd, "ea_create: open race condition with ea header for file: %s", uname); + return -1; + } + + /* lock it */ + if ((write_lock(fd, 0, SEEK_SET, 0)) != 0) { + LOG(log_error, logtype_afpd, "ea_create: lock race condition with ea header for file: %s", uname); + err = -1; + goto exit; + } + + /* Now init it */ + ptr = ea->ea_data; + uint32 = htonl(EA_MAGIC); + memcpy(ptr, &uint32, sizeof(uint32_t)); + ptr += EA_MAGIC_LEN; + + uint16 = htons(EA_VERSION); + memcpy(ptr, &uint16, sizeof(uint16_t)); + ptr += EA_VERSION_LEN; + + memset(ptr, 0, 2); /* count */ + + ea->ea_size = EA_HEADER_SIZE; + ea->ea_inited = EA_INITED; + +exit: + if (err != 0) { + close(fd); + fd = -1; + } + return fd; +} + +/* + * Function: write_ea + * + * Purpose: write an EA to disk + * + * Arguments: + * + * ea (r) struct ea handle + * attruname (r) EA name + * ibuf (r) buffer with EA content + * attrsize (r) size of EA + * + * Returns: 0 on success, -1 on error + * + * Effects: + * + * Creates/overwrites EA file. + * + */ +static int write_ea(const struct ea * restrict ea, + const char * restrict attruname, + const char * restrict ibuf, + size_t attrsize) +{ + int fd = -1, ret = AFP_OK; + struct stat st; + char *eaname; + + if ((eaname = ea_path(ea, attruname, 1)) == NULL) { + LOG(log_error, logtype_afpd, "write_ea('%s'): ea_path error", attruname); + return AFPERR_MISC; + } + + LOG(log_maxdebug, logtype_afpd, "write_ea('%s')", eaname); + + /* Check if it exists, remove if yes*/ + if ((stat(eaname, &st)) == 0) { + if ((unlink(eaname)) != 0) { + if (errno == EACCES) + return AFPERR_ACCESS; + else + return AFPERR_MISC; + } + } + + if ((fd = open(eaname, O_RDWR | O_CREAT | O_EXCL, 0666 & ~ea->vol->v_umask)) == -1) { + LOG(log_error, logtype_afpd, "write_ea: open race condition: %s", eaname); + return -1; + } + + /* lock it */ + if ((write_lock(fd, 0, SEEK_SET, 0)) != 0) { + LOG(log_error, logtype_afpd, "write_ea: open race condition: %s", eaname); + ret = -1; + goto exit; + } + + if (write(fd, ibuf, attrsize) != (ssize_t)attrsize) { + LOG(log_error, logtype_afpd, "write_ea('%s'): write: %s", eaname, strerror(errno)); + ret = -1; + goto exit; + } + +exit: + if (fd != -1) + close(fd); /* and unlock */ + return ret; +} + +/* + * Function: ea_delentry + * + * Purpose: delete one EA from ea->ea_entries[] + * + * Arguments: + * + * ea (rw) pointer to struct ea + * attruname (r) EA name + * + * Returns: new number of EA entries, -1 on error + * + * Effects: + * + * Remove entry from ea->ea_entries[]. Decrement ea->ea_count. + * Marks it as unused just by freeing name and setting it to NULL. + * ea_close and pack_buffer must honor this. + */ +static int ea_delentry(struct ea * restrict ea, const char * restrict attruname) +{ + int ret = 0; + unsigned int count = 0; + + if (ea->ea_count == 0) { + LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion", + attruname); + return -1; + } + + while (count < ea->ea_count) { + /* search matching EA */ + if ((*ea->ea_entries)[count].ea_name && + strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) { + free((*ea->ea_entries)[count].ea_name); + (*ea->ea_entries)[count].ea_name = NULL; + + LOG(log_debug, logtype_afpd, "ea_delentry('%s'): deleted no %u/%u", + attruname, count + 1, ea->ea_count); + + break; + } + count++; + } + + return ret; +} + +/* + * Function: delete_ea_file + * + * Purpose: delete EA file from disk + * + * Arguments: + * + * ea (r) struct ea handle + * attruname (r) EA name + * + * Returns: 0 on success, -1 on error + */ +static int delete_ea_file(const struct ea * restrict ea, const char *eaname) +{ + int ret = 0; + char *eafile; + struct stat st; + + if ((eafile = ea_path(ea, eaname, 1)) == NULL) { + LOG(log_error, logtype_afpd, "delete_ea_file('%s'): ea_path error", eaname); + return -1; + } + + /* Check if it exists, remove if yes*/ + if ((stat(eafile, &st)) == 0) { + if ((unlink(eafile)) != 0) { + LOG(log_error, logtype_afpd, "delete_ea_file('%s'): unlink: %s", + eafile, strerror(errno)); + ret = -1; + } else + LOG(log_debug, logtype_afpd, "delete_ea_file('%s'): success", eafile); + } + + return ret; +} + +/************************************************************************************* + * ea_path, ea_open and ea_close are only global so that dbd can call them + *************************************************************************************/ + +/* + * Function: ea_path + * + * Purpose: return name of ea header filename + * + * Arguments: + * + * ea (r) ea handle + * eaname (r) name of EA or NULL + * macname (r) if != 0 call mtoupath on eaname + * + * Returns: pointer to name in static buffer, NULL on error + * + * Effects: + * + * Calls ad_open, copies buffer, appends "::EA" and if supplied append eanme + * Files: "file" -> "file/.AppleDouble/file::EA" + * Dirs: "dir" -> "dir/.AppleDouble/.Parent::EA" + * "file" with EA "myEA" -> "file/.AppleDouble/file::EA:myEA" + */ +char *ea_path(const struct ea * restrict ea, const char * restrict eaname, int macname) +{ + const char *adname; + static char pathbuf[MAXPATHLEN + 1]; + + /* get name of a adouble file from uname */ + adname = ea->vol->ad_path(ea->filename, (ea->ea_flags & EA_DIR) ? ADFLAGS_DIR : 0); + /* copy it so we can work with it */ + strlcpy(pathbuf, adname, MAXPATHLEN + 1); + /* append "::EA" */ + strlcat(pathbuf, "::EA", MAXPATHLEN + 1); + + if (eaname) { + strlcat(pathbuf, "::", MAXPATHLEN + 1); + if (macname) + if ((eaname = mtoupath(ea->vol, eaname)) == NULL) + return NULL; + strlcat(pathbuf, eaname, MAXPATHLEN + 1); + } + + return pathbuf; +} + +/* + * Function: ea_open + * + * Purpose: open EA header file, create if it doesnt exits and called with O_CREATE + * + * Arguments: + * + * vol (r) current volume + * uname (r) filename for which we have to open a header + * flags (r) EA_CREATE: create if it doesn't exist (without it won't be created) + * EA_RDONLY: open read only + * EA_RDWR: open read/write + * Eiterh EA_RDONLY or EA_RDWR MUST be requested + * ea (w) pointer to a struct ea that we fill + * + * Returns: 0 on success + * -1 on misc error with errno = EFAULT + * -2 if no EA header exists with errno = ENOENT + * + * Effects: + * + * opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size. + * number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags. + * file is either read or write locked depending on the open flags. + * When you're done with struct ea you must call ea_close on it. + */ +int ea_open(const struct vol * restrict vol, + const char * restrict uname, + eaflags_t eaflags, + struct ea * restrict ea) +{ + int ret = 0; + char *eaname; + struct stat st; + + /* Enforce usage rules! */ + if ( ! (eaflags & (EA_RDONLY | EA_RDWR))) { + LOG(log_error, logtype_afpd, "ea_open: called without EA_RDONLY | EA_RDWR", uname); + return -1; + } + + /* Set it all to 0 */ + memset(ea, 0, sizeof(struct ea)); + + ea->vol = vol; /* ea_close needs it */ + ea->ea_flags = eaflags; + ea->dirfd = -1; /* no *at (cf openat) semantics by default */ + + /* Dont care for errors, eg when removing the file is already gone */ + if (!stat(uname, &st) && S_ISDIR(st.st_mode)) + ea->ea_flags |= EA_DIR; + + if ( ! (ea->filename = strdup(uname))) { + LOG(log_error, logtype_afpd, "ea_open: OOM"); + return -1; + } + + eaname = ea_path(ea, NULL, 0); + LOG(log_maxdebug, logtype_afpd, "ea_open: ea_path: %s", eaname); + + /* Check if it exists, if not create it if EA_CREATE is in eaflags */ + if ((stat(eaname, &st)) != 0) { + if (errno == ENOENT) { + + /* It doesnt exist */ + + if ( ! (eaflags & EA_CREATE)) { + /* creation was not requested, so return with error */ + ret = -2; + goto exit; + } + + /* Now create a header file */ + + /* malloc buffer for minimal on disk data */ + ea->ea_data = malloc(EA_HEADER_SIZE); + if (! ea->ea_data) { + LOG(log_error, logtype_afpd, "ea_open: OOM"); + ret = -1; + goto exit; + } + + /* create it */ + ea->ea_fd = create_ea_header(eaname, ea); + if (ea->ea_fd == -1) { + ret = -1; + goto exit; + } + + return 0; + + } else {/* errno != ENOENT */ + ret = -1; + goto exit; + } + } + + /* header file exists, so read and parse it */ + + /* malloc buffer where we read disk file into */ + if (st.st_size < EA_HEADER_SIZE) { + LOG(log_error, logtype_afpd, "ea_open('%s'): bogus EA header file", eaname); + ret = -1; + goto exit; + } + ea->ea_size = st.st_size; + ea->ea_data = malloc(st.st_size); + if (! ea->ea_data) { + LOG(log_error, logtype_afpd, "ea_open: OOM"); + ret = -1; + goto exit; + } + + /* Now lock, open and read header file from disk */ + if ((ea->ea_fd = open(eaname, (ea->ea_flags & EA_RDWR) ? O_RDWR : O_RDONLY)) == -1) { + LOG(log_error, logtype_afpd, "ea_open('%s'): error: %s", eaname, strerror(errno)); + ret = -1; + goto exit; + } + + /* lock it */ + if (ea->ea_flags & EA_RDONLY) { + /* read lock */ + if ((read_lock(ea->ea_fd, 0, SEEK_SET, 0)) != 0) { + LOG(log_error, logtype_afpd, "ea_open: lock error on header: %s", eaname); + ret = -1; + goto exit; + } + } else { /* EA_RDWR */ + /* write lock */ + if ((write_lock(ea->ea_fd, 0, SEEK_SET, 0)) != 0) { + LOG(log_error, logtype_afpd, "ea_open: lock error on header: %s", eaname); + ret = -1; + goto exit; + } + } + + /* read it */ + if (read(ea->ea_fd, ea->ea_data, ea->ea_size) != (ssize_t)ea->ea_size) { + LOG(log_error, logtype_afpd, "ea_open: short read on header: %s", eaname); + ret = -1; + goto exit; + } + + if ((unpack_header(ea)) != 0) { + LOG(log_error, logtype_afpd, "ea_open: error unpacking header for: %s", eaname); + ret = -1; + goto exit; + } + +exit: + switch (ret) { + case 0: + ea->ea_inited = EA_INITED; + break; + case -1: + errno = EFAULT; /* force some errno distinguishable from ENOENT */ + /* fall through */ + case -2: + if (ea->ea_data) { + free(ea->ea_data); + ea->ea_data = NULL; + } + if (ea->ea_fd) { + close(ea->ea_fd); + ea->ea_fd = -1; + } + break; + } + + return ret; +} + +/* + * Function: ea_openat + * + * Purpose: openat like wrapper for ea_open, takes a additional file descriptor + * + * Arguments: + * + * vol (r) current volume + * sfd (r) openat like file descriptor + * uname (r) filename for which we have to open a header + * flags (r) EA_CREATE: create if it doesn't exist (without it won't be created) + * EA_RDONLY: open read only + * EA_RDWR: open read/write + * Eiterh EA_RDONLY or EA_RDWR MUST be requested + * ea (w) pointer to a struct ea that we fill + * + * Returns: 0 on success + * -1 on misc error with errno = EFAULT + * -2 if no EA header exists with errno = ENOENT + * + * Effects: + * + * opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size. + * number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags. + * file is either read or write locked depending on the open flags. + * When you're done with struct ea you must call ea_close on it. + */ +int ea_openat(const struct vol * restrict vol, + int dirfd, + const char * restrict uname, + eaflags_t eaflags, + struct ea * restrict ea) +{ + int ret = 0; + int cwdfd = -1; + + if (dirfd != -1) { + if (((cwdfd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) { + ret = -1; + goto exit; + } + } + + ret = ea_open(vol, uname, eaflags, ea); + ea->dirfd = dirfd; + + if (dirfd != -1) { + if (fchdir(cwdfd) != 0) { + LOG(log_error, logtype_afpd, "ea_openat: cant chdir back, exiting"); + exit(EXITERR_SYS); + } + } + + +exit: + if (cwdfd != -1) + close(cwdfd); + + return ret; + +} + +/* + * Function: ea_close + * + * Purpose: flushes and closes an ea handle + * + * Arguments: + * + * ea (rw) pointer to ea handle + * + * Returns: 0 on success, -1 on error + * + * Effects: + * + * Flushes and then closes and frees all resouces held by ea handle. + * Pack data in ea into ea_data, then write ea_data to disk + */ +int ea_close(struct ea * restrict ea) +{ + int ret = 0; + unsigned int count = 0; + char *eaname; + struct stat st; + + LOG(log_debug, logtype_afpd, "ea_close('%s')", ea->filename); + + if (ea->ea_inited != EA_INITED) { + LOG(log_warning, logtype_afpd, "ea_close('%s'): non initialized ea", ea->filename); + return 0; + } + + /* pack header and write it to disk if it was opened EA_RDWR*/ + if (ea->ea_flags & EA_RDWR) { + if ((pack_header(ea)) != 0) { + LOG(log_error, logtype_afpd, "ea_close: pack header"); + ret = -1; + } else { + if (ea->ea_count == 0) { + /* Check if EA header exists and remove it */ + eaname = ea_path(ea, NULL, 0); + if ((statat(ea->dirfd, eaname, &st)) == 0) { + if ((netatalk_unlinkat(ea->dirfd, eaname)) != 0) { + LOG(log_error, logtype_afpd, "ea_close('%s'): unlink: %s", + eaname, strerror(errno)); + ret = -1; + } + else + LOG(log_debug, logtype_afpd, "ea_close(unlink '%s'): success", eaname); + } else { + /* stat error */ + if (errno != ENOENT) { + LOG(log_error, logtype_afpd, "ea_close('%s'): stat: %s", + eaname, strerror(errno)); + ret = -1; + } + } + } else { /* ea->ea_count > 0 */ + if ((lseek(ea->ea_fd, 0, SEEK_SET)) == -1) { + LOG(log_error, logtype_afpd, "ea_close: lseek: %s", strerror(errno)); + ret = -1; + goto exit; + } + + if ((ftruncate(ea->ea_fd, 0)) == -1) { + LOG(log_error, logtype_afpd, "ea_close: ftruncate: %s", strerror(errno)); + ret = -1; + goto exit; + } + + if (write(ea->ea_fd, ea->ea_data, ea->ea_size) != (ssize_t)ea->ea_size) { + LOG(log_error, logtype_afpd, "ea_close: write: %s", strerror(errno)); + ret = -1; + } + } + } + } + +exit: + /* free names */ + while(count < ea->ea_count) { + if ( (*ea->ea_entries)[count].ea_name ) { + free((*ea->ea_entries)[count].ea_name); + (*ea->ea_entries)[count].ea_name = NULL; + } + count++; + } + ea->ea_count = 0; + + if (ea->filename) { + free(ea->filename); + ea->filename = NULL; + } + + if (ea->ea_entries) { + free(ea->ea_entries); + ea->ea_entries = NULL; + } + + if (ea->ea_data) { + free(ea->ea_data); + ea->ea_data = NULL; + } + if (ea->ea_fd != -1) { + close(ea->ea_fd); /* also releases the fcntl lock */ + ea->ea_fd = -1; + } + + return 0; +} + + + +/************************************************************************************ + * VFS funcs called from afp_ea* funcs + ************************************************************************************/ + +/* + * Function: get_easize + * + * Purpose: get size of an EA + * + * Arguments: + * + * vol (r) current volume + * rbuf (w) DSI reply buffer + * rbuflen (rw) current length of data in reply buffer + * uname (r) filename + * oflag (r) link and create flag + * attruname (r) name of attribute + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Copies EA size into rbuf in network order. Increments *rbuflen +4. + */ +int get_easize(VFS_FUNC_ARGS_EA_GETSIZE) +{ + int ret = AFPERR_MISC; + unsigned int count = 0; + uint32_t uint32; + struct ea ea; + + LOG(log_debug, logtype_afpd, "get_easize: file: %s", uname); + + if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) { + if (errno != ENOENT) + LOG(log_error, logtype_afpd, "get_easize: error calling ea_open for file: %s", uname); + + memset(rbuf, 0, 4); + *rbuflen += 4; + return ret; + } + + while (count < ea.ea_count) { + if (strcmp(attruname, (*ea.ea_entries)[count].ea_name) == 0) { + uint32 = htonl((*ea.ea_entries)[count].ea_size); + memcpy(rbuf, &uint32, 4); + *rbuflen += 4; + ret = AFP_OK; + + LOG(log_debug, logtype_afpd, "get_easize(\"%s\"): size: %u", + attruname, (*ea.ea_entries)[count].ea_size); + break; + } + count++; + } + + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "get_easize: error closing ea handle for file: %s", uname); + return AFPERR_MISC; + } + + return ret; +} + +/* + * Function: get_eacontent + * + * Purpose: copy EA into rbuf + * + * Arguments: + * + * vol (r) current volume + * rbuf (w) DSI reply buffer + * rbuflen (rw) current length of data in reply buffer + * uname (r) filename + * oflag (r) link and create flag + * attruname (r) name of attribute + * maxreply (r) maximum EA size as of current specs/real-life + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Copies EA into rbuf. Increments *rbuflen accordingly. + */ +int get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) +{ + int ret = AFPERR_MISC; + unsigned int count = 0; + uint32_t uint32; + size_t toread; + struct ea ea; + char *eafile; + + LOG(log_debug, logtype_afpd, "get_eacontent('%s/%s')", uname, attruname); + + if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) { + if (errno != ENOENT) + LOG(log_error, logtype_afpd, "get_eacontent('%s'): ea_open error", uname); + memset(rbuf, 0, 4); + *rbuflen += 4; + return ret; + } + + while (count < ea.ea_count) { + if (strcmp(attruname, (*ea.ea_entries)[count].ea_name) == 0) { + if ( (eafile = ea_path(&ea, attruname, 1)) == NULL) { + ret = AFPERR_MISC; + break; + } + + if ((fd = open(eafile, O_RDONLY)) == -1) { + LOG(log_error, logtype_afpd, "get_eacontent('%s'): open error: %s", uname, strerror(errno)); + ret = AFPERR_MISC; + break; + } + + /* Check how much the client wants, give him what we think is right */ + maxreply -= MAX_REPLY_EXTRA_BYTES; + if (maxreply > MAX_EA_SIZE) + maxreply = MAX_EA_SIZE; + toread = (maxreply < (*ea.ea_entries)[count].ea_size) ? maxreply : (*ea.ea_entries)[count].ea_size; + LOG(log_debug, logtype_afpd, "get_eacontent('%s'): sending %u bytes", attruname, toread); + + /* Put length of EA data in reply buffer */ + uint32 = htonl(toread); + memcpy(rbuf, &uint32, 4); + rbuf += 4; + *rbuflen += 4; + + if (read(fd, rbuf, toread) != (ssize_t)toread) { + LOG(log_error, logtype_afpd, "get_eacontent('%s/%s'): short read", uname, attruname); + close(fd); + ret = AFPERR_MISC; + break; + } + *rbuflen += toread; + close(fd); + + ret = AFP_OK; + break; + } + count++; + } + + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "get_eacontent('%s'): error closing ea handle", uname); + return AFPERR_MISC; + } + + return ret; + +} + +/* + * Function: list_eas + * + * Purpose: copy names of EAs into attrnamebuf + * + * Arguments: + * + * vol (r) current volume + * attrnamebuf (w) store names a consecutive C strings here + * buflen (rw) length of names in attrnamebuf + * uname (r) filename + * oflag (r) link and create flag + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Copies names of all EAs of uname as consecutive C strings into rbuf. + * Increments *buflen accordingly. + */ +int list_eas(VFS_FUNC_ARGS_EA_LIST) +{ + unsigned int count = 0; + int attrbuflen = *buflen, ret = AFP_OK, len; + char *buf = attrnamebuf; + struct ea ea; + + LOG(log_debug, logtype_afpd, "list_eas: file: %s", uname); + + if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) { + if (errno != ENOENT) { + LOG(log_error, logtype_afpd, "list_eas: error calling ea_open for file: %s", uname); + return AFPERR_MISC; + } + else + return AFP_OK; + } + + while (count < ea.ea_count) { + /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */ + if ( ( len = convert_string(vol->v_volcharset, + CH_UTF8_MAC, + (*ea.ea_entries)[count].ea_name, + (*ea.ea_entries)[count].ea_namelen, + buf + attrbuflen, + 255)) + <= 0 ) { + ret = AFPERR_MISC; + goto exit; + } + if (len == 255) + /* convert_string didn't 0-terminate */ + attrnamebuf[attrbuflen + 255] = 0; + + LOG(log_debug7, logtype_afpd, "list_eas(%s): EA: %s", + uname, (*ea.ea_entries)[count].ea_name); + + attrbuflen += len + 1; + if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) { + /* Next EA name could overflow, so bail out with error. + FIXME: evantually malloc/memcpy/realloc whatever. + Is it worth it ? */ + LOG(log_warning, logtype_afpd, "list_eas(%s): running out of buffer for EA names", uname); + ret = AFPERR_MISC; + goto exit; + } + count++; + } + +exit: + *buflen = attrbuflen; + + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "list_eas: error closing ea handle for file: %s", uname); + return AFPERR_MISC; + } + + return ret; +} + +/* + * Function: set_ea + * + * Purpose: set a Solaris native EA + * + * Arguments: + * + * vol (r) current volume + * uname (r) filename + * attruname (r) EA name + * ibuf (r) buffer with EA content + * attrsize (r) length EA in ibuf + * oflag (r) link and create flag + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Copies names of all EAs of uname as consecutive C strings into rbuf. + * Increments *rbuflen accordingly. + */ +int set_ea(VFS_FUNC_ARGS_EA_SET) +{ + int ret = AFP_OK; + struct ea ea; + + LOG(log_debug, logtype_afpd, "set_ea: file: %s", uname); + + if ((ea_open(vol, uname, EA_CREATE | EA_RDWR, &ea)) != 0) { + LOG(log_error, logtype_afpd, "set_ea('%s'): ea_open error", uname); + return AFPERR_MISC; + } + + if ((ea_addentry(&ea, attruname, attrsize, oflag)) == -1) { + LOG(log_error, logtype_afpd, "set_ea('%s'): ea_addentry error", uname); + ret = AFPERR_MISC; + goto exit; + } + + if ((write_ea(&ea, attruname, ibuf, attrsize)) != 0) { + LOG(log_error, logtype_afpd, "set_ea('%s'): write_ea error", uname); + ret = AFPERR_MISC; + goto exit; + } + +exit: + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "set_ea('%s'): ea_close error", uname); + ret = AFPERR_MISC; + goto exit; + } + + return ret; +} + +/* + * Function: remove_ea + * + * Purpose: remove a EA from a file + * + * Arguments: + * + * vol (r) current volume + * uname (r) filename + * attruname (r) EA name + * oflag (r) link and create flag + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Removes EA attruname from file uname. + */ +int remove_ea(VFS_FUNC_ARGS_EA_REMOVE) +{ + int ret = AFP_OK; + struct ea ea; + + LOG(log_debug, logtype_afpd, "remove_ea('%s/%s')", uname, attruname); + + if ((ea_open(vol, uname, EA_RDWR, &ea)) != 0) { + LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_open error", uname); + return AFPERR_MISC; + } + + if ((ea_delentry(&ea, attruname)) == -1) { + LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_delentry error", uname); + ret = AFPERR_MISC; + goto exit; + } + + if ((delete_ea_file(&ea, attruname)) != 0) { + LOG(log_error, logtype_afpd, "remove_ea('%s'): delete_ea error", uname); + ret = AFPERR_MISC; + goto exit; + } + +exit: + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_close error", uname); + ret = AFPERR_MISC; + goto exit; + } + + return ret; +} + +/****************************************************************************************** + * EA VFS funcs that deal with file/dir cp/mv/rm + ******************************************************************************************/ + +int ea_deletefile(VFS_FUNC_ARGS_DELETEFILE) +{ + unsigned int count = 0; + int ret = AFP_OK; + int cwd = -1; + struct ea ea; + + LOG(log_debug, logtype_afpd, "ea_deletefile('%s')", file); + + /* Open EA stuff */ + if ((ea_openat(vol, dirfd, file, EA_RDWR, &ea)) != 0) { + if (errno == ENOENT) + /* no EA files, nothing to do */ + return AFP_OK; + else { + LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error calling ea_open", file); + return AFPERR_MISC; + } + } + + if (dirfd != -1) { + if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) { + ret = AFPERR_MISC; + goto exit; + } + } + + while (count < ea.ea_count) { + if ((delete_ea_file(&ea, (*ea.ea_entries)[count].ea_name)) != 0) { + ret = AFPERR_MISC; + continue; + } + free((*ea.ea_entries)[count].ea_name); + (*ea.ea_entries)[count].ea_name = NULL; + count++; + } + + /* ea_close removes the EA header file for us because all names are NULL */ + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error closing ea handle", file); + ret = AFPERR_MISC; + } + + if (dirfd != -1 && fchdir(cwd) != 0) { + LOG(log_error, logtype_afpd, "ea_deletefile: cant chdir back. exit!"); + exit(EXITERR_SYS); + } + +exit: + if (cwd != -1) + close(cwd); + + return ret; +} + +int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE) +{ + unsigned int count = 0; + int ret = AFP_OK; + size_t easize; + char srceapath[ MAXPATHLEN + 1]; + char *eapath; + char *eaname; + struct ea srcea; + struct ea dstea; + struct adouble ad; + + LOG(log_debug, logtype_afpd, "ea_renamefile('%s'/'%s')", src, dst); + + + /* Open EA stuff */ + if ((ea_openat(vol, dirfd, src, EA_RDWR, &srcea)) != 0) { + if (errno == ENOENT) + /* no EA files, nothing to do */ + return AFP_OK; + else { + LOG(log_error, logtype_afpd, "ea_renamefile('%s'/'%s'): ea_open error: '%s'", src, dst, src); + return AFPERR_MISC; + } + } + + if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) { + if (errno == ENOENT) { + /* Possibly the .AppleDouble folder didn't exist, we create it and try again */ + ad_init(&ad, vol); + if ((ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666)) != 0) { + LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): ad_open error: '%s'", src, dst, dst); + ret = AFPERR_MISC; + goto exit; + } + ad_close(&ad, ADFLAGS_HF); + if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) { + ret = AFPERR_MISC; + goto exit; + } + } + } + + /* Loop through all EAs: */ + while (count < srcea.ea_count) { + /* Move EA */ + eaname = (*srcea.ea_entries)[count].ea_name; + easize = (*srcea.ea_entries)[count].ea_size; + + /* Build src and dst paths for rename() */ + if ((eapath = ea_path(&srcea, eaname, 1)) == NULL) { + ret = AFPERR_MISC; + goto exit; + } + strcpy(srceapath, eapath); + if ((eapath = ea_path(&dstea, eaname, 1)) == NULL) { + ret = AFPERR_MISC; + goto exit; + } + + LOG(log_maxdebug, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'", + src, dst, srceapath, eapath); + + /* Add EA to dstea */ + if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) { + LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'", + src, dst, srceapath, eapath); + ret = AFPERR_MISC; + goto exit; + } + + /* Remove EA entry from srcea */ + if ((ea_delentry(&srcea, eaname)) == -1) { + LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'", + src, dst, srceapath, eapath); + ea_delentry(&dstea, eaname); + ret = AFPERR_MISC; + goto exit; + } + + /* Now rename the EA */ + if ((unix_rename(dirfd, srceapath, -1, eapath)) < 0) { + LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'", + src, dst, srceapath, eapath); + ret = AFPERR_MISC; + goto exit; + } + + count++; + } + + +exit: + ea_close(&srcea); + ea_close(&dstea); + return ret; +} + +int ea_copyfile(VFS_FUNC_ARGS_COPYFILE) +{ + unsigned int count = 0; + int ret = AFP_OK; + size_t easize; + char srceapath[ MAXPATHLEN + 1]; + char *eapath; + char *eaname; + struct ea srcea; + struct ea dstea; + struct adouble ad; + + LOG(log_debug, logtype_afpd, "ea_copyfile('%s'/'%s')", src, dst); + + /* Open EA stuff */ + if ((ea_openat(vol, sfd, src, EA_RDWR, &srcea)) != 0) { + if (errno == ENOENT) + /* no EA files, nothing to do */ + return AFP_OK; + else { + LOG(log_error, logtype_afpd, "ea_copyfile('%s'/'%s'): ea_open error: '%s'", src, dst, src); + return AFPERR_MISC; + } + } + + if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) { + if (errno == ENOENT) { + /* Possibly the .AppleDouble folder didn't exist, we create it and try again */ + ad_init(&ad, vol); + if ((ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666)) != 0) { + LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ad_open error: '%s'", src, dst, dst); + ret = AFPERR_MISC; + goto exit; + } + ad_close(&ad, ADFLAGS_HF); + if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) { + ret = AFPERR_MISC; + goto exit; + } + } + } + + /* Loop through all EAs: */ + while (count < srcea.ea_count) { + /* Copy EA */ + eaname = (*srcea.ea_entries)[count].ea_name; + easize = (*srcea.ea_entries)[count].ea_size; + + /* Build src and dst paths for copy_file() */ + if ((eapath = ea_path(&srcea, eaname, 1)) == NULL) { + ret = AFPERR_MISC; + goto exit; + } + strcpy(srceapath, eapath); + if ((eapath = ea_path(&dstea, eaname, 1)) == NULL) { + ret = AFPERR_MISC; + goto exit; + } + + LOG(log_maxdebug, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'", + src, dst, srceapath, eapath); + + /* Add EA to dstea */ + if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) { + LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ea_addentry('%s') error", + src, dst, eaname); + ret = AFPERR_MISC; + goto exit; + } + + /* Now copy the EA */ + if ((copy_file(sfd, srceapath, eapath, (0666 & ~vol->v_umask))) < 0) { + LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'", + src, dst, srceapath, eapath); + ret = AFPERR_MISC; + goto exit; + } + + count++; + } + +exit: + ea_close(&srcea); + ea_close(&dstea); + return ret; +} + +int ea_chown(VFS_FUNC_ARGS_CHOWN) +{ + + unsigned int count = 0; + int ret = AFP_OK; + char *eaname; + struct ea ea; + + LOG(log_debug, logtype_afpd, "ea_chown('%s')", path); + /* Open EA stuff */ + if ((ea_open(vol, path, EA_RDWR, &ea)) != 0) { + if (errno == ENOENT) + /* no EA files, nothing to do */ + return AFP_OK; + else { + LOG(log_error, logtype_afpd, "ea_chown('%s'): error calling ea_open", path); + return AFPERR_MISC; + } + } + + if ((ochown(ea_path(&ea, NULL, 0), uid, gid, vol_syml_opt(vol))) != 0) { + switch (errno) { + case EPERM: + case EACCES: + ret = AFPERR_ACCESS; + goto exit; + default: + ret = AFPERR_MISC; + goto exit; + } + } + + while (count < ea.ea_count) { + if ((eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 1)) == NULL) { + ret = AFPERR_MISC; + goto exit; + } + if ((ochown(eaname, uid, gid, vol_syml_opt(vol))) != 0) { + switch (errno) { + case EPERM: + case EACCES: + ret = AFPERR_ACCESS; + goto exit; + default: + ret = AFPERR_MISC; + goto exit; + } + continue; + } + + count++; + } + +exit: + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "ea_chown('%s'): error closing ea handle", path); + return AFPERR_MISC; + } + + return ret; +} + +int ea_chmod_file(VFS_FUNC_ARGS_SETFILEMODE) +{ + + unsigned int count = 0; + int ret = AFP_OK; + const char *eaname; + struct ea ea; + + LOG(log_debug, logtype_afpd, "ea_chmod_file('%s')", name); + /* Open EA stuff */ + if ((ea_open(vol, name, EA_RDWR, &ea)) != 0) { + if (errno == ENOENT) + /* no EA files, nothing to do */ + return AFP_OK; + else + return AFPERR_MISC; + } + + /* Set mode on EA header file */ + if ((setfilmode(vol, ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL)) != 0) { + LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno)); + switch (errno) { + case EPERM: + case EACCES: + ret = AFPERR_ACCESS; + goto exit; + default: + ret = AFPERR_MISC; + goto exit; + } + } + + /* Set mode on EA files */ + while (count < ea.ea_count) { + if ((eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 1)) == NULL) { + ret = AFPERR_MISC; + goto exit; + } + if ((setfilmode(vol, eaname, ea_mode(mode), NULL)) != 0) { + LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", eaname, strerror(errno)); + switch (errno) { + case EPERM: + case EACCES: + ret = AFPERR_ACCESS; + goto exit; + default: + ret = AFPERR_MISC; + goto exit; + } + continue; + } + + count++; + } + +exit: + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): error closing ea handle", name); + return AFPERR_MISC; + } + + return ret; +} + +int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE) +{ + + int ret = AFP_OK; + unsigned int count = 0; + const char *eaname; + const char *eaname_safe = NULL; + struct ea ea; + + LOG(log_debug, logtype_afpd, "ea_chmod_dir('%s')", name); + /* .AppleDouble already might be inaccesible, so we must run as id 0 */ + become_root(); + + /* Open EA stuff */ + if ((ea_open(vol, name, EA_RDWR, &ea)) != 0) { + /* ENOENT --> no EA files, nothing to do */ + if (errno != ENOENT) + ret = AFPERR_MISC; + unbecome_root(); + return ret; + } + + /* Set mode on EA header */ + if ((setfilmode(vol, ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL)) != 0) { + LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno)); + switch (errno) { + case EPERM: + case EACCES: + ret = AFPERR_ACCESS; + goto exit; + default: + ret = AFPERR_MISC; + goto exit; + } + } + + /* Set mode on EA files */ + while (count < ea.ea_count) { + eaname = (*ea.ea_entries)[count].ea_name; + /* + * Be careful with EA names from the EA header! + * Eg NFS users might have access to them, can inject paths using ../ or /..... + * FIXME: + * Until the EA code escapes / in EA name requests from the client, these therefor wont work. + */ + if ((eaname_safe = strrchr(eaname, '/'))) { + LOG(log_warning, logtype_afpd, "ea_chmod_dir('%s'): contains a slash", eaname); + eaname = eaname_safe; + } + if ((eaname = ea_path(&ea, eaname, 1)) == NULL) { + ret = AFPERR_MISC; + goto exit; + } + if ((setfilmode(vol, eaname, ea_mode(mode), NULL)) != 0) { + LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", eaname, strerror(errno)); + switch (errno) { + case EPERM: + case EACCES: + ret = AFPERR_ACCESS; + goto exit; + default: + ret = AFPERR_MISC; + goto exit; + } + continue; + } + + count++; + } + +exit: + unbecome_root(); + + if ((ea_close(&ea)) != 0) { + LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): error closing ea handle", name); + return AFPERR_MISC; + } + + return ret; +} diff --git a/libatalk/vfs/ea_sys.c b/libatalk/vfs/ea_sys.c new file mode 100644 index 0000000..7ed8729 --- /dev/null +++ b/libatalk/vfs/ea_sys.c @@ -0,0 +1,567 @@ +/* + Copyright (c) 2009 Frank Lahm + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********************************************************************************** + * EA VFS funcs for storing EAs in nativa filesystem EAs + **********************************************************************************/ + +/* + * Function: sys_get_easize + * + * Purpose: get size of a native EA + * + * Arguments: + * + * vol (r) current volume + * rbuf (w) DSI reply buffer + * rbuflen (rw) current length of data in reply buffer + * uname (r) filename + * oflag (r) link and create flag + * attruname (r) name of attribute + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Copies EA size into rbuf in network order. Increments *rbuflen +4. + */ +int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE) +{ + ssize_t ret; + uint32_t attrsize; + + LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\"", uname, attruname); + + /* PBaranski fix */ + if (fd != -1) { + LOG(log_debug, logtype_afpd, "sys_get_easize(%s): file is already opened", uname); + ret = sys_fgetxattr(fd, attruname, rbuf +4, 0); + } else { + if ((oflag & O_NOFOLLOW) ) { + ret = sys_lgetxattr(uname, attruname, rbuf +4, 0); + } + else { + ret = sys_getxattr(uname, attruname, rbuf +4, 0); + } + } + /* PBaranski fix */ + + + if (ret == -1) { + memset(rbuf, 0, 4); + *rbuflen += 4; + switch(errno) { + case OPEN_NOFOLLOW_ERRNO: + /* its a symlink and client requested O_NOFOLLOW */ + LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): symlink with kXAttrNoFollow", uname); + return AFPERR_MISC; + + case ENOATTR: + case ENOENT: + if (vol->v_obj->afp_version >= 34) + return AFPERR_NOITEM; + return AFPERR_MISC; + + default: + LOG(log_debug, logtype_afpd, "sys_getextattr_size: error: %s", strerror(errno)); + return AFPERR_MISC; + } + } + + if (ret > MAX_EA_SIZE) + ret = MAX_EA_SIZE; + + /* Start building reply packet */ + LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, ret); + + /* length of attribute data */ + attrsize = htonl((uint32_t)ret); + memcpy(rbuf, &attrsize, 4); + *rbuflen += 4; + + ret = AFP_OK; + return ret; +} + +/* + * Function: sys_get_eacontent + * + * Purpose: copy native EA into rbuf + * + * Arguments: + * + * vol (r) current volume + * rbuf (w) DSI reply buffer + * rbuflen (rw) current length of data in reply buffer + * uname (r) filename + * oflag (r) link and create flag + * attruname (r) name of attribute + * maxreply (r) maximum EA size as of current specs/real-life + * fd (r) file descriptor + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Copies EA into rbuf. Increments *rbuflen accordingly. + */ +int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) +{ + ssize_t ret; + uint32_t attrsize; + + /* Start building reply packet */ + + maxreply -= MAX_REPLY_EXTRA_BYTES; + + if (maxreply > MAX_EA_SIZE) + maxreply = MAX_EA_SIZE; + + LOG(log_debug7, logtype_afpd, "sys_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply); + + /* PBaranski fix */ + if (fd != -1) { + LOG(log_debug, logtype_afpd, "sys_get_eacontent(%s): file is already opened", uname); + ret = sys_fgetxattr(fd, attruname, rbuf +4, maxreply); + } else { + if ((oflag & O_NOFOLLOW) ) { + ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply); + } + else { + ret = sys_getxattr(uname, attruname, rbuf +4, maxreply); + } + } + /* PBaranski fix */ + + if (ret == -1) { + memset(rbuf, 0, 4); + *rbuflen += 4; + switch(errno) { + case OPEN_NOFOLLOW_ERRNO: + /* its a symlink and client requested O_NOFOLLOW */ + LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): symlink with kXAttrNoFollow", uname); + return AFPERR_MISC; + + case ENOATTR: + if (vol->v_obj->afp_version >= 34) + return AFPERR_NOITEM; + return AFPERR_MISC; + + default: + LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): error: %s", attruname, strerror(errno)); + return AFPERR_MISC; + } + } + + /* remember where we must store length of attribute data in rbuf */ + *rbuflen += 4 +ret; + + attrsize = htonl((uint32_t)ret); + memcpy(rbuf, &attrsize, 4); + + return AFP_OK; +} + +/* + * Function: sys_list_eas + * + * Purpose: copy names of native EAs into attrnamebuf + * + * Arguments: + * + * vol (r) current volume + * attrnamebuf (w) store names a consecutive C strings here + * buflen (rw) length of names in attrnamebuf + * uname (r) filename + * oflag (r) link and create flag + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Copies names of all EAs of uname as consecutive C strings into rbuf. + * Increments *rbuflen accordingly. + * We hide the adouble:ea extended attributes here, but we currently + * allow reading, writing and deleteting them. + */ +int sys_list_eas(VFS_FUNC_ARGS_EA_LIST) +{ + ssize_t attrbuflen = *buflen; + int ret, len, nlen; + char *buf; + char *ptr; + struct adouble ad, *adp; + + buf = malloc(ATTRNAMEBUFSIZ); + if (!buf) + return AFPERR_MISC; + + /* PBaranski fix */ + if ( fd != -1) { + LOG(log_debug, logtype_afpd, "sys_list_eas(%s): file is already opened", uname); + ret = sys_flistxattr(fd, uname, buf, ATTRNAMEBUFSIZ); + } else { + if ((oflag & O_NOFOLLOW)) { + ret = sys_llistxattr(uname, buf, ATTRNAMEBUFSIZ); + } + else { + ret = sys_listxattr(uname, buf, ATTRNAMEBUFSIZ); + } + } + /* PBaranski fix */ + + if (ret == -1) switch(errno) { + case OPEN_NOFOLLOW_ERRNO: + /* its a symlink and client requested O_NOFOLLOW, we pretend 0 EAs */ + LOG(log_debug, logtype_afpd, "sys_list_extattr(%s): symlink with kXAttrNoFollow", uname); + ret = AFP_OK; + goto exit; + default: + LOG(log_debug, logtype_afpd, "sys_list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno)); + ret = AFPERR_MISC; + goto exit; + } + + ptr = buf; + while (ret > 0) { + len = strlen(ptr); + if (NOT_NETATALK_EA(ptr)) { + /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */ + if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) { + ret = AFPERR_MISC; + goto exit; + } + + LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr); + + attrbuflen += nlen + 1; + if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) { + /* Next EA name could overflow, so bail out with error. + FIXME: evantually malloc/memcpy/realloc whatever. + Is it worth it ? */ + LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname); + ret = AFPERR_MISC; + goto exit; + } + } + ret -= len + 1; + ptr += len + 1; + } + + ret = AFP_OK; + +exit: + free(buf); + *buflen = attrbuflen; + return ret; +} + +/* + * Function: sys_set_ea + * + * Purpose: set a native EA + * + * Arguments: + * + * vol (r) current volume + * uname (r) filename + * attruname (r) EA name + * ibuf (r) buffer with EA content + * attrsize (r) length EA in ibuf + * oflag (r) link and create flag + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + */ +int sys_set_ea(VFS_FUNC_ARGS_EA_SET) +{ + int attr_flag; + int ret; + + attr_flag = 0; + if ((oflag & O_CREAT) ) + attr_flag |= XATTR_CREATE; + + else if ((oflag & O_TRUNC) ) + attr_flag |= XATTR_REPLACE; + + /* PBaranski fix */ + if ( fd != -1) { + LOG(log_debug, logtype_afpd, "sys_set_ea(%s): file is already opened", uname); + ret = sys_fsetxattr(fd, attruname, ibuf, attrsize, attr_flag); + } else { + if ((oflag & O_NOFOLLOW) ) { + ret = sys_lsetxattr(uname, attruname, ibuf, attrsize,attr_flag); + } + else { + ret = sys_setxattr(uname, attruname, ibuf, attrsize, attr_flag); + } + } + /* PBaranski fix */ + + if (ret == -1) { + switch(errno) { + case OPEN_NOFOLLOW_ERRNO: + /* its a symlink and client requested O_NOFOLLOW */ + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s\", ea:'%s'): symlink with kXAttrNoFollow", + uname, attruname); + return AFP_OK; + case EEXIST: + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists", + getcwdpath(), uname, attruname); + return AFPERR_EXIST; + case ENOATTR: + case ENOENT: + if ((attr_flag & XATTR_REPLACE) && (vol->v_obj->afp_version >= 34)) + return AFPERR_NOITEM; + return AFPERR_MISC; + default: + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s', size: %u, flags: %s|%s|%s): %s", + getcwdpath(), uname, attruname, attrsize, + oflag & O_CREAT ? "XATTR_CREATE" : "-", + oflag & O_TRUNC ? "XATTR_REPLACE" : "-", + oflag & O_NOFOLLOW ? "O_NOFOLLOW" : "-", + strerror(errno)); + return AFPERR_MISC; + } + } + + return AFP_OK; +} + +/* + * Function: sys_remove_ea + * + * Purpose: remove a native EA + * + * Arguments: + * + * vol (r) current volume + * uname (r) filename + * attruname (r) EA name + * oflag (r) link and create flag + * fd (r) file descriptor + * + * Returns: AFP code: AFP_OK on success or appropiate AFP error code + * + * Effects: + * + * Removes EA attruname from file uname. + */ +int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE) +{ + int ret; + + /* PBaranski fix */ + if ( fd != -1) { + LOG(log_debug, logtype_afpd, "sys_remove_ea(%s): file is already opened", uname); + ret = sys_fremovexattr(fd, uname, attruname); + } else { + if ((oflag & O_NOFOLLOW) ) { + ret = sys_lremovexattr(uname, attruname); + } + else { + ret = sys_removexattr(uname, attruname); + } + } + /* PBaranski fix */ + + if (ret == -1) { + switch(errno) { + case OPEN_NOFOLLOW_ERRNO: + /* its a symlink and client requested O_NOFOLLOW */ + LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): symlink with kXAttrNoFollow", uname); + return AFP_OK; + default: + LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): error: %s", uname, attruname, strerror(errno)); + return AFPERR_MISC; + } + } + + return AFP_OK; +} + +/* + * @brief Copy EAs + * + * @note Supports *at semantics, therfor switches back and forth between sfd and cwd + */ +int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE) +{ + int ret = 0; + int cwd = -1; + ssize_t size; + char *names = NULL, *end_names, *name, *value = NULL; + unsigned int setxattr_ENOTSUP = 0; + + if (sfd != -1) { + if ((cwd = open(".", O_RDONLY)) == -1) { + LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant open cwd: %s", + strerror(errno)); + ret = -1; + goto getout; + } + } + + if (sfd != -1) { + if (fchdir(sfd) == -1) { + LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to sfd: %s", + strerror(errno)); + ret = -1; + goto getout; + } + } + + size = sys_listxattr(src, NULL, 0); + if (size < 0) { + if (errno != ENOSYS && errno != ENOTSUP) { + ret = -1; + } + goto getout; + } + names = malloc(size+1); + if (names == NULL) { + ret = -1; + goto getout; + } + size = sys_listxattr(src, names, size); + if (size < 0) { + ret = -1; + goto getout; + } else { + names[size] = '\0'; + end_names = names + size; + } + + if (sfd != -1) { + if (fchdir(cwd) == -1) { + LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to cwd: %s", + strerror(errno)); + ret = -1; + goto getout; + } + } + + for (name = names; name != end_names; name = strchr(name, '\0') + 1) { + void *old_value; + + /* check if this attribute shall be preserved */ + if (!*name) + continue; + + if (STRCMP(name, ==, AD_EA_META)) + continue; + + if (sfd != -1) { + if (fchdir(sfd) == -1) { + LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to sfd: %s", + strerror(errno)); + ret = -1; + goto getout; + } + } + + size = sys_getxattr (src, name, NULL, 0); + if (size < 0) { + ret = -1; + continue; + } + value = realloc(old_value = value, size); + if (size != 0 && value == NULL) { + free(old_value); + ret = -1; + } + size = sys_getxattr(src, name, value, size); + if (size < 0) { + ret = -1; + continue; + } + + if (sfd != -1) { + if (fchdir(cwd) == -1) { + LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to cwd: %s", + strerror(errno)); + ret = -1; + goto getout; + } + } + + if (sys_setxattr(dst, name, value, size, 0) != 0) { + if (errno == ENOTSUP) + setxattr_ENOTSUP++; + else { + if (errno == ENOSYS) { + ret = -1; + /* no hope of getting any further */ + break; + } else { + ret = -1; + } + } + } + } + if (setxattr_ENOTSUP) { + errno = ENOTSUP; + ret = -1; + } + +getout: + if (cwd != -1) + close(cwd); + + free(value); + free(names); + + if (ret == -1) { + switch(errno) { + case ENOENT: + /* no attribute */ + break; + case EACCES: + LOG(log_debug, logtype_afpd, "sys_ea_copyfile(%s, %s): error: %s", src, dst, strerror(errno)); + return AFPERR_ACCESS; + default: + LOG(log_error, logtype_afpd, "sys_ea_copyfile(%s, %s): error: %s", src, dst, strerror(errno)); + return AFPERR_MISC; + } + } + + return AFP_OK; +} diff --git a/libatalk/vfs/extattr.c b/libatalk/vfs/extattr.c new file mode 100644 index 0000000..9e45bb8 --- /dev/null +++ b/libatalk/vfs/extattr.c @@ -0,0 +1,1039 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2005 + Copyright (C) Timur Bakeyev 2005 + Copyright (C) Bjoern Jacke 2006-2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + sys_copyxattr modified from LGPL2.1 libattr copyright + Copyright (C) 2001-2002 Silicon Graphics, Inc. All Rights Reserved. + Copyright (C) 2001 Andreas Gruenbacher. + + Samba 3.0.28, modified for netatalk. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#if HAVE_ATTR_XATTR_H +#include +#elif HAVE_SYS_XATTR_H +#include +#endif + +#ifdef HAVE_SYS_EA_H +#include +#endif + +#ifdef HAVE_ATTROPEN + +#include +#endif + +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +/******** Solaris EA helper function prototypes ********/ +#ifdef HAVE_ATTROPEN +#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH +static int solaris_write_xattr(int attrfd, const char *value, size_t size); +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size); +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size); +static int solaris_unlinkat(int attrdirfd, const char *name); +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode); +static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode); +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode); +#endif + +/************************************************************************** + Wrappers for extented attribute calls. Based on the Linux package with + support for IRIX and (Net|Free)BSD also. Expand as other systems have them. +****************************************************************************/ +static char attr_name[256 +5] = "user."; + +static const char *prefix(const char *uname) +{ +#if defined(HAVE_ATTROPEN) + return uname; +#else + strlcpy(attr_name +5, uname, 256); + return attr_name; +#endif +} + +int sys_getxattrfd(int fd, const char *uname, int oflag, ...) +{ +#if defined HAVE_ATTROPEN + int eafd; + va_list args; + mode_t mode = 0; + + if (oflag & O_CREAT) { + va_start(args, oflag); + mode = va_arg(args, mode_t); + va_end(args); + } + + if (oflag & O_CREAT) + eafd = solaris_openat(fd, uname, oflag | O_XATTR, mode); + else + eafd = solaris_openat(fd, uname, oflag | O_XATTR, mode); + + return eafd; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size) +{ + const char *name = prefix(uname); + +#if defined(HAVE_GETXATTR) +#ifndef XATTR_ADD_OPT + return getxattr(path, name, value, size); +#else + int options = 0; + return getxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_GETEA) + return getea(path, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FILE) + ssize_t retval; + /* + * The BSD implementation has a nasty habit of silently truncating + * the returned value to the size of the buffer, so we have to check + * that the buffer is large enough to fit the returned value. + */ + if((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) { + if (size == 0) + /* size == 0 means only return size */ + return retval; + if (retval > size) { + errno = ERANGE; + return -1; + } + if ((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0) + return retval; + } + + LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)); + return -1; +#elif defined(HAVE_ATTR_GET) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_attropen(path, name, O_RDONLY, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_fgetxattr (int filedes, const char *uname, void *value, size_t size) +{ + const char *name = prefix(uname); + +#if defined(HAVE_FGETXATTR) +#ifndef XATTR_ADD_OPT + return fgetxattr(filedes, name, value, size); +#else + int options = 0; + return fgetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_FGETEA) + return fgetea(filedes, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FD) + char *s; + ssize_t retval; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1; + + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) { + if(retval > size) { + errno = ERANGE; + return -1; + } + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0) + return retval; + } + + LOG(log_debug, logtype_default, "sys_fgetxattr: extattr_get_fd(): %s", strerror(errno)); + return -1; +#elif defined(HAVE_ATTR_GETF) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size) +{ + const char *name = prefix(uname); + +#if defined(HAVE_LGETXATTR) + return lgetxattr(path, name, value, size); +#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return getxattr(path, name, value, size, 0, options); +#elif defined(HAVE_LGETEA) + return lgetea(path, name, value, size); +#elif defined(HAVE_EXTATTR_GET_LINK) + ssize_t retval; + + retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0); + if (retval == -1) { + LOG(log_maxdebug, logtype_default, "extattr_get_link(): %s", + strerror(errno)); + return -1; + } + if (size == 0) + /* Only interested in size of xattr */ + return retval; + if (retval > size) { + errno = ERANGE; + return -1; + } + return extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size); + +#elif defined(HAVE_ATTR_GET) + int retval, flags = ATTR_DONTFOLLOW; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_attropen(path, name, O_RDONLY | O_NOFOLLOW, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +#if defined(HAVE_EXTATTR_LIST_FILE) + +#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1) + +static struct { + int space; + const char *name; + size_t len; +} +extattr[] = { + { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("") }, + { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("") }, +}; + +typedef union { + const char *path; + int filedes; +} extattr_arg; + +static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size) +{ + ssize_t list_size; + int i, len; + + switch(type) { +#if defined(HAVE_EXTATTR_LIST_FILE) + case 0: + list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size); + break; +#endif +#if defined(HAVE_EXTATTR_LIST_LINK) + case 1: + list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size); + break; +#endif +#if defined(HAVE_EXTATTR_LIST_FD) + case 2: + list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size); + break; +#endif + default: + errno = ENOSYS; + return -1; + } + + /* Some error happend. Errno should be set by the previous call */ + if(list_size < 0) + return -1; + + /* No attributes */ + if(list_size == 0) + return 0; + + /* XXX: Call with an empty buffer may be used to calculate + necessary buffer size. Unfortunately, we can't say, how + many attributes were returned, so here is the potential + problem with the emulation. + */ + if(list == NULL) + return list_size; + + /* Buffer is too small to fit the results */ + if(list_size > size) { + errno = ERANGE; + return -1; + } + + /* Convert from pascal strings to C strings */ + len = list[0]; + memmove(list, list + 1, list_size); + + for(i = len; i < list_size; ) { + LOG(log_maxdebug, logtype_afpd, "len: %d, i: %d", len, i); + + len = list[i]; + list[i] = '\0'; + i += len + 1; + } + + return list_size; +} + +#endif + +#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) +static char attr_buffer[ATTR_MAX_VALUELEN]; + +static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags) +{ + int retval = 0, index; + attrlist_cursor_t *cursor = 0; + int total_size = 0; + attrlist_t * al = (attrlist_t *)attr_buffer; + attrlist_ent_t *ae; + size_t ent_size, left = size; + char *bp = list; + + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("user."); + if (left >= ent_size) { + strncpy(bp, "user.", sizeof("user.")); + strncat(bp, ae->a_name, ent_size - sizeof("user.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + if (retval == 0) { + flags |= ATTR_ROOT; + cursor = 0; + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("system."); + if (left >= ent_size) { + strncpy(bp, "system.", sizeof("system.")); + strncat(bp, ae->a_name, ent_size - sizeof("system.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + } + return (ssize_t)(retval ? retval : total_size); +} + +#endif + +#if defined(HAVE_LISTXATTR) +static ssize_t remove_user(ssize_t ret, char *list, size_t size) +{ + size_t len; + char *ptr; + char *ptr1; + ssize_t ptrsize; + + if (ret <= 0 || size == 0) + return ret; + ptrsize = ret; + ptr = ptr1 = list; + while (ptrsize > 0) { + len = strlen(ptr1) +1; + ptrsize -= len; + if (strncmp(ptr1, "user.",5)) { + ptr1 += len; + continue; + } + memmove(ptr, ptr1 +5, len -5); + ptr += len -5; + ptr1 += len; + } + return ptr -list; +} +#endif + +ssize_t sys_listxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_LISTXATTR) + ssize_t ret; + +#ifndef XATTR_ADD_OPT + ret = listxattr(path, list, size); +#else + int options = 0; + ret = listxattr(path, list, size, options); +#endif + return remove_user(ret, list, size); + +#elif defined(HAVE_LISTEA) + return listea(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_FILE) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(0, arg, list, size); +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) + return irix_attr_list(path, 0, list, size, 0); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_flistxattr (int filedes, const char *path, char *list, size_t size) +{ +#if defined(HAVE_LISTXATTR) + ssize_t ret; + +#ifndef XATTR_ADD_OPT + ret = listxattr(path, list, size); +#else + int options = 0; + ret = listxattr(path, list, size, options); +#endif + return remove_user(ret, list, size); + +#elif defined(HAVE_LISTEA) + return listea(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_FILE) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(0, arg, list, size); +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) + return irix_attr_list(path, 0, list, size, 0); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropenat(filedes, path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_llistxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_LLISTXATTR) + ssize_t ret; + + ret = llistxattr(path, list, size); + return remove_user(ret, list, size); +#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT) + ssize_t ret; + int options = XATTR_NOFOLLOW; + + ret = listxattr(path, list, size, options); + return remove_user(ret, list, size); + +#elif defined(HAVE_LLISTEA) + return llistea(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_LINK) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(1, arg, list, size); +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) + return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY | O_NOFOLLOW, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_removexattr (const char *path, const char *uname) +{ + const char *name = prefix(uname); +#if defined(HAVE_REMOVEXATTR) +#ifndef XATTR_ADD_OPT + return removexattr(path, name); +#else + int options = 0; + return removexattr(path, name, options); +#endif +#elif defined(HAVE_REMOVEEA) + return removeea(path, name); +#elif defined(HAVE_EXTATTR_DELETE_FILE) + return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname); +#elif defined(HAVE_ATTR_REMOVE) + int flags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_fremovexattr (int filedes, const char *path, const char *uname) +{ + const char *name = prefix(uname); +#if defined(HAVE_REMOVEXATTR) +#ifndef XATTR_ADD_OPT + return removexattr(path, name); +#else + int options = 0; + return removexattr(path, name, options); +#endif +#elif defined(HAVE_REMOVEEA) + return removeea(path, name); +#elif defined(HAVE_EXTATTR_DELETE_FILE) + return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname); +#elif defined(HAVE_ATTR_REMOVE) + int flags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropenat(filedes, path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lremovexattr (const char *path, const char *uname) +{ + const char *name = prefix(uname); +#if defined(HAVE_LREMOVEXATTR) + return lremovexattr(path, name); +#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return removexattr(path, name, options); +#elif defined(HAVE_LREMOVEEA) + return lremoveea(path, name); +#elif defined(HAVE_EXTATTR_DELETE_LINK) + return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, uname); +#elif defined(HAVE_ATTR_REMOVE) + int flags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY | O_NOFOLLOW, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags) +{ + const char *name = prefix(uname); +#if defined(HAVE_SETXATTR) +#ifndef XATTR_ADD_OPT + return setxattr(path, name, value, size, flags); +#else + int options = 0; + return setxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_SETEA) + return setea(path, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_FILE) + int retval = 0; + if (flags) { + /* Check attribute existence */ + retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_file(path, EXTATTR_NAMESPACE_USER, uname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SET) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_fsetxattr (int filedes, const char *uname, const void *value, size_t size, int flags) +{ + const char *name = prefix(uname); + +#if defined(HAVE_FSETXATTR) +#ifndef XATTR_ADD_OPT + return fsetxattr(filedes, name, value, size, flags); +#else + int options = 0; + return fsetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_FSETEA) + return fsetea(filedes, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_FD) + char *s; + int retval = 0; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1; + if (flags) { + /* Check attribute existence */ + retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SETF) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_setf(filedes, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | O_XATTR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags) +{ + const char *name = prefix(uname); +#if defined(HAVE_LSETXATTR) + return lsetxattr(path, name, value, size, flags); +#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return setxattr(path, name, value, size, 0, options); +#elif defined(LSETEA) + return lsetea(path, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_LINK) + int retval = 0; + if (flags) { + /* Check attribute existence */ + retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + + retval = extattr_set_link(path, EXTATTR_NAMESPACE_USER, uname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SET) + int myflags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | O_NOFOLLOW; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +/************************************************************************** + helper functions for Solaris' EA support +****************************************************************************/ +#ifdef HAVE_ATTROPEN +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size) +{ + struct stat sbuf; + + if (fstat(attrfd, &sbuf) == -1) { + return -1; + } + + /* This is to return the current size of the named extended attribute */ + if (size == 0) { + return sbuf.st_size; + } + + /* check size and read xattr */ + if (sbuf.st_size > size) { + return -1; + } + + return read(attrfd, value, sbuf.st_size); +} + +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size) +{ + ssize_t len = 0; + DIR *dirp; + struct dirent *de; + int newfd = dup(attrdirfd); + /* CAUTION: The originating file descriptor should not be + used again following the call to fdopendir(). + For that reason we dup() the file descriptor + here to make things more clear. */ + dirp = fdopendir(newfd); + + while ((de = readdir(dirp))) { + size_t listlen; + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || + !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw")) + { + /* we don't want "." and ".." here: */ + LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name); + continue; + } + + listlen = strlen(de->d_name); + if (size == 0) { + /* return the current size of the list of extended attribute names*/ + len += listlen + 1; + } else { + /* check size and copy entry + nul into list. */ + if ((len + listlen + 1) > size) { + errno = ERANGE; + len = -1; + break; + } else { + strcpy(list + len, de->d_name); + len += listlen; + list[len] = '\0'; + ++len; + } + } + } + + if (closedir(dirp) == -1) { + LOG(log_error, logtype_default, "closedir dirp: %s",strerror(errno)); + return -1; + } + return len; +} + +static int solaris_unlinkat(int attrdirfd, const char *name) +{ + if (unlinkat(attrdirfd, name, 0) == -1) { + return -1; + } + return 0; +} + +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode) +{ + EC_INIT; + int filedes = -1, eafd = -1; + + if ((filedes = open(path, O_RDONLY | (oflag & O_NOFOLLOW), mode)) == -1) { + switch (errno) { + case ENOENT: + case EEXIST: + case OPEN_NOFOLLOW_ERRNO: + EC_FAIL; + default: + LOG(log_debug, logtype_default, "open(\"%s\"): %s", fullpathname(path), strerror(errno)); + EC_FAIL; + } + } + + if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) { + switch (errno) { + case ENOENT: + case EEXIST: + EC_FAIL; + default: + LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno)); + EC_FAIL; + } + } + +EC_CLEANUP: + if (filedes != -1) + close(filedes); + if (ret != 0) { + if (eafd != -1) + close(eafd); + eafd = -1; + } + return eafd; +} + +static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode) +{ + EC_INIT; + int eafd = -1; + + if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) { + switch (errno) { + case ENOENT: + case EEXIST: + EC_FAIL; + default: + LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno)); + EC_FAIL; + } + } + +EC_CLEANUP: + if (ret != 0) { + if (eafd != -1) + close(eafd); + eafd = -1; + } + return eafd; +} + + +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode) +{ + int filedes; + + if ((filedes = openat(fildes, path, oflag, mode)) == -1) { + switch (errno) { + case ENOENT: + case EEXIST: + case EACCES: + break; + default: + LOG(log_debug, logtype_default, "openat(\"%s\"): %s", + path, strerror(errno)); + errno = ENOATTR; + break; + } + } + return filedes; +} + +static int solaris_write_xattr(int attrfd, const char *value, size_t size) +{ + if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) { + return 0; + } else { + LOG(log_error, logtype_default, "solaris_write_xattr: %s", + strerror(errno)); + return -1; + } +} + +#endif /*HAVE_ATTROPEN*/ + diff --git a/libatalk/vfs/unix.c b/libatalk/vfs/unix.c new file mode 100644 index 0000000..846aa72 --- /dev/null +++ b/libatalk/vfs/unix.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 1990,1993 Regents of The University of Michigan. + * All Rights Reserved. See COPYRIGHT. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ------------------------- */ +int dir_rx_set(mode_t mode) +{ + return (mode & (S_IXUSR | S_IRUSR)) == (S_IXUSR | S_IRUSR); +} + +/* --------------------- */ +int setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat *st) +{ + struct stat sb; + mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO; /* rwx for owner group and other, by default */ + + if (!st) { + if (lstat(name, &sb) != 0) + return -1; + st = &sb; + } + + mode |= st->st_mode & ~mask; /* keep other bits from previous mode */ + + if (ochmod((char *)name, + mode & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM ) { + return -1; + } + return 0; +} + +/* + * @brief system rmdir with afp error code. + * + * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this. + */ +int netatalk_rmdir_all_errors(int dirfd, const char *name) +{ + int err; + +#ifdef HAVE_ATFUNCS + if (dirfd == -1) + dirfd = AT_FDCWD; + err = unlinkat(dirfd, name, AT_REMOVEDIR); +#else + err = rmdir(name); +#endif + + if (err < 0) { + switch ( errno ) { + case ENOENT : + return AFPERR_NOOBJ; + case ENOTEMPTY : + case EEXIST: + return AFPERR_DIRNEMPT; + case EPERM: + case EACCES : + return AFPERR_ACCESS; + case EROFS: + return AFPERR_VLOCK; + default : + return AFPERR_PARAM; + } + } + return AFP_OK; +} + +/* + * @brief System rmdir with afp error code, but ENOENT is not an error. + * + * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this. + */ +int netatalk_rmdir(int dirfd, const char *name) +{ + int ret = netatalk_rmdir_all_errors(dirfd, name); + if (ret == AFPERR_NOOBJ) + return AFP_OK; + return ret; +} + +/* ------------------- + system unlink with afp error code. + ENOENT is not an error. +*/ +int netatalk_unlink(const char *name) +{ + if (unlink(name) < 0) { + switch (errno) { + case ENOENT : + break; + case EROFS: + return AFPERR_VLOCK; + case EPERM: + case EACCES : + return AFPERR_ACCESS; + default : + return AFPERR_PARAM; + } + } + return AFP_OK; +} + +/************************************************************************** + * *at semnatics support functions (like openat, renameat standard funcs) + **************************************************************************/ + +/* Copy all file data from one file fd to another */ +int copy_file_fd(int sfd, int dfd) +{ + EC_INIT; + ssize_t cc; + size_t buflen; + char filebuf[NETATALK_DIOSZ_STACK]; + + while ((cc = read(sfd, filebuf, sizeof(filebuf)))) { + if (cc < 0) { + if (errno == EINTR) + continue; + LOG(log_error, logtype_afpd, "copy_file_fd: %s", strerror(errno)); + EC_FAIL; + } + + buflen = cc; + while (buflen > 0) { + if ((cc = write(dfd, filebuf, buflen)) < 0) { + if (errno == EINTR) + continue; + LOG(log_error, logtype_afpd, "copy_file_fd: %s", strerror(errno)); + EC_FAIL; + } + buflen -= cc; + } + } + +EC_CLEANUP: + EC_EXIT; +} + +/* + * Supports *at semantics if HAVE_ATFUNCS, pass dirfd=-1 to ignore this + */ +int copy_file(int dirfd, const char *src, const char *dst, mode_t mode) +{ + int ret = 0; + int sfd = -1; + int dfd = -1; + +#ifdef HAVE_ATFUNCS + if (dirfd == -1) + dirfd = AT_FDCWD; + sfd = openat(dirfd, src, O_RDONLY); +#else + sfd = open(src, O_RDONLY); +#endif + if (sfd < 0) { + LOG(log_info, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s", + src, dst, src, strerror(errno)); + return -1; + } + + if ((dfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0) { + LOG(log_info, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s", + src, dst, dst, strerror(errno)); + ret = -1; + goto exit; + } + + ret = copy_file_fd(sfd, dfd); + +exit: + if (sfd != -1) + close(sfd); + + if (dfd != -1) { + int err; + + err = close(dfd); + if (!ret && err) { + /* don't bother to report an error if there's already one */ + LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): close '%s' error: %s", + src, dst, dst, strerror(errno)); + ret = -1; + } + } + + return ret; +} + +/*! + * Copy an EA from one file to another + * + * Supports *at semantics if HAVE_ATFUNCS, pass dirfd=-1 to ignore this + */ +int copy_ea(const char *ea, int dirfd, const char *src, const char *dst, mode_t mode) +{ + EC_INIT; + int sfd = -1; + int dfd = -1; + size_t easize; + char *eabuf = NULL; + +#ifdef HAVE_ATFUNCS + if (dirfd == -1) + dirfd = AT_FDCWD; + EC_NEG1_LOG( sfd = openat(dirfd, src, O_RDONLY) ); +#else + EC_NEG1_LOG( sfd = open(src, O_RDONLY) ); +#endif + EC_NEG1_LOG( dfd = open(dst, O_WRONLY, mode) ); + + if ((easize = sys_fgetxattr(sfd, ea, NULL, 0)) > 0) { + EC_NULL_LOG( eabuf = malloc(easize)); + EC_NEG1_LOG( easize = sys_fgetxattr(sfd, ea, eabuf, easize) ); + EC_NEG1_LOG( easize = sys_fsetxattr(dfd, ea, eabuf, easize, 0) ); + } + +EC_CLEANUP: + if (sfd != -1) + close(sfd); + if (dfd != -1) + close(dfd); + free(eabuf); + EC_EXIT; +} + +/* + * at wrapper for netatalk_unlink + */ +int netatalk_unlinkat(int dirfd, const char *name) +{ +#ifdef HAVE_ATFUNCS + if (dirfd == -1) + dirfd = AT_FDCWD; + + if (unlinkat(dirfd, name, 0) < 0) { + switch (errno) { + case ENOENT : + break; + case EROFS: + return AFPERR_VLOCK; + case EPERM: + case EACCES : + return AFPERR_ACCESS; + default : + return AFPERR_PARAM; + } + } + return AFP_OK; +#else + return netatalk_unlink(name); +#endif + + /* DEADC0DE */ + return 0; +} + +/* + * @brief This is equivalent of unix rename() + * + * unix_rename mulitplexes rename and renameat. If we dont HAVE_ATFUNCS, sfd and dfd + * are ignored. + * + * @param sfd (r) if we HAVE_ATFUNCS, -1 gives AT_FDCWD + * @param oldpath (r) guess what + * @param dfd (r) same as sfd + * @param newpath (r) guess what + */ +int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath) +{ +#ifdef HAVE_ATFUNCS + if (sfd == -1) + sfd = AT_FDCWD; + if (dfd == -1) + dfd = AT_FDCWD; + + if (renameat(sfd, oldpath, dfd, newpath) < 0) + return -1; +#else + if (rename(oldpath, newpath) < 0) + return -1; +#endif /* HAVE_ATFUNCS */ + + return 0; +} + +/* + * @brief stat/fsstatat multiplexer + * + * statat mulitplexes stat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored. + * + * @param dirfd (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD + * @param path (r) pathname + * @param st (rw) pointer to struct stat + */ +int statat(int dirfd, const char *path, struct stat *st) +{ +#ifdef HAVE_ATFUNCS + if (dirfd == -1) + dirfd = AT_FDCWD; + return (fstatat(dirfd, path, st, 0)); +#else + return (stat(path, st)); +#endif + + /* DEADC0DE */ + return -1; +} + +/* + * @brief opendir wrapper for *at semantics support + * + * opendirat chdirs to dirfd if dirfd != -1 before calling opendir on path. + * + * @param dirfd (r) if != -1, chdir(dirfd) before opendir(path) + * @param path (r) pathname + */ +DIR *opendirat(int dirfd, const char *path) +{ + DIR *ret; + int cwd = -1; + + if (dirfd != -1) { + if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) { + ret = NULL; + goto exit; + } + } + + ret = opendir(path); + + if (dirfd != -1 && fchdir(cwd) != 0) { + LOG(log_error, logtype_afpd, "opendirat: cant chdir back. exit!"); + exit(EXITERR_SYS); + } + +exit: + if (cwd != -1) + close(cwd); + + return ret; +} diff --git a/libatalk/vfs/vfs.c b/libatalk/vfs/vfs.c new file mode 100644 index 0000000..0d1961c --- /dev/null +++ b/libatalk/vfs/vfs.c @@ -0,0 +1,885 @@ +/* + Copyright (c) 2004 Didier Gautheron + Copyright (c) 2009 Frank Lahm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct perm { + uid_t uid; + gid_t gid; +}; + +typedef int (*rf_loop)(const struct vol *, struct dirent *, char *, void *, int); + +/* ----------------------------- */ +static int +for_each_adouble(const char *from, const char *name, rf_loop fn, const struct vol *vol, void *data, int flag) +{ + char buf[ MAXPATHLEN + 1]; + char *m; + DIR *dp; + struct dirent *de; + int ret; + + + if (NULL == ( dp = opendir( name)) ) { + if (!flag) { + LOG(log_error, logtype_afpd, "%s: opendir %s: %s", from, fullpathname(name),strerror(errno) ); + return -1; + } + return 0; + } + strlcpy( buf, name, sizeof(buf)); + strlcat( buf, "/", sizeof(buf) ); + m = strchr( buf, '\0' ); + ret = 0; + while ((de = readdir(dp))) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { + continue; + } + + strlcat(buf, de->d_name, sizeof(buf)); + if (fn && (ret = fn(vol, de, buf, data, flag))) { + closedir(dp); + return ret; + } + *m = 0; + } + closedir(dp); + return ret; +} + +static int netatalk_name(const char *name) +{ + return strcmp(name,".AppleDB") && strcmp(name,".AppleDesktop"); +} + +/******************************************************************************* + * classic adouble format + *******************************************************************************/ + +static int validupath_adouble(VFS_FUNC_ARGS_VALIDUPATH) +{ + if (name[0] != '.') + return 1; + + return netatalk_name(name) && strcmp(name,".AppleDouble") && strcasecmp(name,".Parent"); +} + +/* ----------------- */ +static int RF_chown_adouble(VFS_FUNC_ARGS_CHOWN) +{ + struct stat st; + const char *ad_p; + + ad_p = vol->ad_path(path, ADFLAGS_HF ); + + if ( stat( ad_p, &st ) < 0 ) + return 0; /* ignore */ + + return chown( ad_p, uid, gid ); +} + +/* ----------------- */ +static int RF_renamedir_adouble(VFS_FUNC_ARGS_RENAMEDIR) +{ + return 0; +} + +/* ----------------- */ +static int deletecurdir_adouble_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_) +{ + struct stat st; + int err; + + /* bail if the file exists in the current directory. + * note: this will not fail with dangling symlinks */ + + if (lstat(de->d_name, &st) == 0) + return AFPERR_DIRNEMPT; + + if ((err = netatalk_unlink(name))) + return err; + + return 0; +} + +static int RF_deletecurdir_adouble(VFS_FUNC_ARGS_DELETECURDIR) +{ + int err; + + /* delete stray .AppleDouble files. this happens to get .Parent files + as well. */ + if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_adouble_loop, vol, NULL, 1))) + return err; + return netatalk_rmdir(-1, ".AppleDouble" ); +} + +/* ----------------- */ +static int adouble_setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat *st) +{ + return setfilmode(vol, name, ad_hf_mode(mode), st); +} + +static int RF_setfilmode_adouble(VFS_FUNC_ARGS_SETFILEMODE) +{ + return adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_HF ), mode, st); +} + +/* ----------------- */ +static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE) +{ + const char *adouble = vol->ad_path(name, ADFLAGS_DIR ); + + if (dir_rx_set(mode)) { + if (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0) + return -1; + } + + if (adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_DIR ), mode, st) < 0) + return -1; + + if (!dir_rx_set(mode)) { + if (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0) + return -1 ; + } + return 0; +} + +/* ----------------- */ +static int setdirmode_adouble_loop(const struct vol *vol, struct dirent *de _U_, char *name, void *data, int flag) +{ + mode_t hf_mode = *(mode_t *)data; + struct stat st; + + if (ostat(name, &st, vol_syml_opt(vol)) < 0 ) { + if (flag) + return 0; + LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", name, strerror(errno) ); + } + else if (!S_ISDIR(st.st_mode)) { + if (setfilmode(vol, name, hf_mode, &st) < 0) { + /* FIXME what do we do then? */ + } + } + return 0; +} + +static int RF_setdirmode_adouble(VFS_FUNC_ARGS_SETDIRMODE) +{ + mode_t hf_mode = ad_hf_mode(mode); + const char *adouble = vol->ad_path(name, ADFLAGS_DIR ); + const char *adouble_p = ad_dir(adouble); + + if (dir_rx_set(mode)) { + if (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0) + return -1; + } + + if (for_each_adouble("setdirmode", adouble_p, setdirmode_adouble_loop, vol, &hf_mode, 0)) + return -1; + + if (!dir_rx_set(mode)) { + if (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0) + return -1 ; + } + return 0; +} + +static int RF_setdirowner_adouble(VFS_FUNC_ARGS_SETDIROWNER) +{ + if (lchown(".AppleDouble", uid, gid) < 0 && errno != EPERM ) { + LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s", + uid, gid,fullpathname(".AppleDouble"), strerror(errno)); + } + return 0; +} + +/* ----------------- */ +static int RF_deletefile_adouble(VFS_FUNC_ARGS_DELETEFILE) +{ + return netatalk_unlinkat(dirfd, vol->ad_path(file, ADFLAGS_HF)); +} + +/* ----------------- */ +static int RF_renamefile_adouble(VFS_FUNC_ARGS_RENAMEFILE) +{ + char adsrc[ MAXPATHLEN + 1]; + int err = 0; + + strcpy( adsrc, vol->ad_path(src, 0 )); + if (unix_rename(dirfd, adsrc, -1, vol->ad_path(dst, 0 )) < 0) { + struct stat st; + + err = errno; + if (errno == ENOENT) { + struct adouble ad; + + if (ostatat(dirfd, adsrc, &st, vol_syml_opt(vol))) /* source has no ressource fork, */ + return 0; + + /* We are here because : + * -there's no dest folder. + * -there's no .AppleDouble in the dest folder. + * if we use the struct adouble passed in parameter it will not + * create .AppleDouble if the file is already opened, so we + * use a diff one, it's not a pb,ie it's not the same file, yet. + */ + ad_init(&ad, vol); + if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) == 0) { + ad_close(&ad, ADFLAGS_HF); + if (!unix_rename(dirfd, adsrc, -1, vol->ad_path(dst, 0 )) ) + err = 0; + else + err = errno; + } + else { /* it's something else, bail out */ + err = errno; + } + } + } + if (err) { + errno = err; + return -1; + } + return 0; +} + +static int RF_copyfile_adouble(VFS_FUNC_ARGS_COPYFILE) +/* const struct vol *vol, int sfd, const char *src, const char *dst */ +{ + EC_INIT; + bstring s = NULL, d = NULL; + char *dup1 = NULL; + char *dup2 = NULL; + char *dup3 = NULL; + char *dup4 = NULL; + const char *name = NULL; + const char *dir = NULL; + + struct stat st; + EC_ZERO(stat(dst, &st)); + + if (S_ISDIR(st.st_mode)) { + /* build src path to AppleDouble file*/ + EC_NULL(s = bfromcstr(src)); + EC_ZERO(bcatcstr(s, "/.AppleDouble/.Parent")); + + /* build dst path to AppleDouble file*/ + EC_NULL(d = bfromcstr(dst)); + EC_ZERO(bcatcstr(d, "/.AppleDouble/.Parent")); + } else { + /* get basename */ + + /* build src path to AppleDouble file*/ + EC_NULL(dup1 = strdup(src)); + EC_NULL(name = basename(strdup(dup1))); + + EC_NULL(dup2 = strdup(src)); + EC_NULL(dir = dirname(dup2)); + EC_NULL(s = bfromcstr(dir)); + EC_ZERO(bcatcstr(s, "/.AppleDouble/")); + EC_ZERO(bcatcstr(s, name)); + + /* build dst path to AppleDouble file*/ + EC_NULL(dup4 = strdup(dst)); + EC_NULL(name = basename(strdup(dup4))); + + EC_NULL(dup3 = strdup(dst)); + EC_NULL(dir = dirname(dup3)); + EC_NULL(d = bfromcstr(dir)); + EC_ZERO(bcatcstr(d, "/.AppleDouble/")); + EC_ZERO(bcatcstr(d, name)); + } + + /* ignore errors */ + if (copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666) != 0) + if (errno != ENOENT) + EC_FAIL; + +EC_CLEANUP: + bdestroy(s); + bdestroy(d); + if (dup1) free(dup1); + if (dup2) free(dup2); + if (dup3) free(dup3); + if (dup4) free(dup4); + + EC_EXIT; +} + +#ifdef HAVE_NFSV4_ACLS +static int RF_solaris_acl(VFS_FUNC_ARGS_ACL) +{ + static char buf[ MAXPATHLEN + 1]; + struct stat st; + int len; + + if ((stat(path, &st)) != 0) { + if (errno == ENOENT) + return AFP_OK; + return AFPERR_MISC; + } + if (!S_ISDIR(st.st_mode)) { + /* set ACL on ressource fork */ + if ((acl(vol->ad_path(path, ADFLAGS_HF), cmd, count, aces)) != 0) + return AFPERR_MISC; + } + return AFP_OK; +} + +static int RF_solaris_remove_acl(VFS_FUNC_ARGS_REMOVE_ACL) +{ + int ret; + static char buf[ MAXPATHLEN + 1]; + int len; + + if (dir) + return AFP_OK; + + /* remove ACL from ressource fork */ + if ((ret = remove_acl_vfs(vol->ad_path(path, ADFLAGS_HF))) != AFP_OK) { + if (errno == ENOENT) + return AFP_OK; + return ret; + } + + return AFP_OK; +} +#endif + +#ifdef HAVE_POSIX_ACLS +static int RF_posix_acl(VFS_FUNC_ARGS_ACL) +{ + EC_INIT; + struct stat st; + + if (stat(path, &st) == -1) + EC_FAIL; + + if (!S_ISDIR(st.st_mode)) { + /* set ACL on ressource fork */ + EC_ZERO_ERR( acl_set_file(vol->ad_path(path, ADFLAGS_HF), type, acl), AFPERR_MISC ); + } + +EC_CLEANUP: + if (errno == ENOENT) + EC_STATUS(AFP_OK); + EC_EXIT; +} + +static int RF_posix_remove_acl(VFS_FUNC_ARGS_REMOVE_ACL) +{ + EC_INIT; + + if (dir) + EC_EXIT_STATUS(AFP_OK); + + /* remove ACL from ressource fork */ + EC_ZERO_ERR( remove_acl_vfs(vol->ad_path(path, ADFLAGS_HF)), AFPERR_MISC ); + +EC_CLEANUP: + if (errno == ENOENT) + EC_STATUS(AFP_OK); + EC_EXIT; +} +#endif + +/************************************************************************* + * EA adouble format + ************************************************************************/ +static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH) +{ + if (name[0] != '.') + return 1; + +#ifndef HAVE_EAFD + if (name[1] == '_') + return ad_valid_header_osx(name); +#endif + return netatalk_name(name); +} + +/* ----------------- */ +static int RF_chown_ea(VFS_FUNC_ARGS_CHOWN) +{ +#ifndef HAVE_EAFD + return chown(vol->ad_path(path, ADFLAGS_HF ), uid, gid); +#endif + return 0; +} + +/* ---------------- */ +static int RF_renamedir_ea(VFS_FUNC_ARGS_RENAMEDIR) +{ + return 0; +} + +/* Returns 1 if the entry is NOT an ._ file */ +static int deletecurdir_ea_osx_chkifempty_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_) +{ + if (de->d_name[0] != '.' || de->d_name[0] == '_') + return 1; + + return 0; +} + +static int deletecurdir_ea_osx_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_) +{ + int ret; + struct stat sb; + + if (strncmp(name, "._", strlen("._")) == 0) { + if (lstat(name, &sb) != 0) + return -1; + if (S_ISREG(sb.st_mode)) + if ((ret = netatalk_unlink(name)) != 0) + return ret; + } + + return 0; +} + +/* ---------------- */ +static int RF_deletecurdir_ea(VFS_FUNC_ARGS_DELETECURDIR) +{ +#ifndef HAVE_EAFD + int err; + /* delete stray ._AppleDouble files */ + if ((err = for_each_adouble("deletecurdir_ea_osx", ".", + deletecurdir_ea_osx_loop, + vol, NULL, 0)) != 0) + return err; + +#endif + return 0; +} + +/* ---------------- */ +static int RF_setdirunixmode_ea(VFS_FUNC_ARGS_SETDIRUNIXMODE) +{ +#ifndef HAVE_EAFD +#endif + return 0; +} + +static int RF_setfilmode_ea(VFS_FUNC_ARGS_SETFILEMODE) +{ +#ifndef HAVE_EAFD + return adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_HF ), mode, st); +#endif + return 0; +} + +/* ---------------- */ +static int RF_setdirmode_ea(VFS_FUNC_ARGS_SETDIRMODE) +{ +#ifndef HAVE_EAFD +#endif + return 0; +} + +/* ---------------- */ +static int RF_setdirowner_ea(VFS_FUNC_ARGS_SETDIROWNER) +{ +#ifndef HAVE_EAFD +#endif + return 0; +} + +static int RF_deletefile_ea(VFS_FUNC_ARGS_DELETEFILE) +{ +#ifndef HAVE_EAFD + return netatalk_unlinkat(dirfd, vol->ad_path(file, ADFLAGS_HF)); +#endif + return 0; +} +static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE) +{ +#ifdef HAVE_EAFD + /* the EA VFS module does this all for us */ + return 0; +#endif + + EC_INIT; + bstring s = NULL, d = NULL; + char *dup1 = NULL; + char *dup2 = NULL; + char *dup3 = NULL; + char *dup4 = NULL; + const char *name = NULL; + const char *dir = NULL; + + /* get basename */ + + /* build src path to ._ file*/ + EC_NULL(dup1 = strdup(src)); + EC_NULL(name = basename(strdup(dup1))); + + EC_NULL(dup2 = strdup(src)); + EC_NULL(dir = dirname(dup2)); + EC_NULL(s = bfromcstr(dir)); + EC_ZERO(bcatcstr(s, "/._")); + EC_ZERO(bcatcstr(s, name)); + + /* build dst path to ._file*/ + EC_NULL(dup4 = strdup(dst)); + EC_NULL(name = basename(strdup(dup4))); + + EC_NULL(dup3 = strdup(dst)); + EC_NULL(dir = dirname(dup3)); + EC_NULL(d = bfromcstr(dir)); + EC_ZERO(bcatcstr(d, "/._")); + EC_ZERO(bcatcstr(d, name)); + + if (copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666) != 0) { + switch (errno) { + case ENOENT: + break; + default: + LOG(log_error, logtype_afpd, "[VFS] copyfile(\"%s\" -> \"%s\"): %s", + cfrombstr(s), cfrombstr(d), strerror(errno)); + EC_FAIL; + + } + } + +EC_CLEANUP: + bdestroy(s); + bdestroy(d); + free(dup1); + free(dup2); + free(dup3); + free(dup4); + EC_EXIT; +} + +/* ---------------- */ +static int RF_renamefile_ea(VFS_FUNC_ARGS_RENAMEFILE) +{ +#ifndef HAVE_EAFD + char adsrc[ MAXPATHLEN + 1]; + int err = 0; + + strcpy( adsrc, vol->ad_path(src, 0 )); + + if (unix_rename(dirfd, adsrc, -1, vol->ad_path(dst, 0 )) < 0) { + struct stat st; + + err = errno; + if (errno == ENOENT && ostatat(dirfd, adsrc, &st, vol_syml_opt(vol))) /* source has no ressource fork, */ + return 0; + errno = err; + return -1; + } + return 0; +#endif + return 0; +} + +/******************************************************************************************** + * VFS chaining + ********************************************************************************************/ + +/* + * Up until we really start stacking many VFS modules on top of one another or use + * dynamic module loading like we do for UAMs, up until then we just stack VFS modules + * via an fixed size array. + * All VFS funcs must return AFP_ERR codes. When a func in the chain returns an error + * this error code will be returned to the caller, BUT the chain in followed and all + * following funcs are called in order to give them a chance. + */ + +/* + * Define most VFS funcs with macros as they all do the same. + * Only "ad_path" and "validupath" will NOT do stacking and only + * call the func from the first module. + */ + +#define VFS_MFUNC(name, args, vars) \ + static int vfs_ ## name(args) \ + { \ + int i = 0, ret = AFP_OK, err; \ + while (vol->vfs_modules[i]) { \ + if (vol->vfs_modules[i]->vfs_ ## name) { \ + err = vol->vfs_modules[i]->vfs_ ## name (vars); \ + if ((ret == AFP_OK) && (err != AFP_OK)) \ + ret = err; \ + } \ + i ++; \ + } \ + return ret; \ + } + +VFS_MFUNC(chown, VFS_FUNC_ARGS_CHOWN, VFS_FUNC_VARS_CHOWN) +VFS_MFUNC(renamedir, VFS_FUNC_ARGS_RENAMEDIR, VFS_FUNC_VARS_RENAMEDIR) +VFS_MFUNC(deletecurdir, VFS_FUNC_ARGS_DELETECURDIR, VFS_FUNC_VARS_DELETECURDIR) +VFS_MFUNC(setfilmode, VFS_FUNC_ARGS_SETFILEMODE, VFS_FUNC_VARS_SETFILEMODE) +VFS_MFUNC(setdirmode, VFS_FUNC_ARGS_SETDIRMODE, VFS_FUNC_VARS_SETDIRMODE) +VFS_MFUNC(setdirunixmode, VFS_FUNC_ARGS_SETDIRUNIXMODE, VFS_FUNC_VARS_SETDIRUNIXMODE) +VFS_MFUNC(setdirowner, VFS_FUNC_ARGS_SETDIROWNER, VFS_FUNC_VARS_SETDIROWNER) +VFS_MFUNC(deletefile, VFS_FUNC_ARGS_DELETEFILE, VFS_FUNC_VARS_DELETEFILE) +VFS_MFUNC(renamefile, VFS_FUNC_ARGS_RENAMEFILE, VFS_FUNC_VARS_RENAMEFILE) +VFS_MFUNC(copyfile, VFS_FUNC_ARGS_COPYFILE, VFS_FUNC_VARS_COPYFILE) +#ifdef HAVE_ACLS +VFS_MFUNC(acl, VFS_FUNC_ARGS_ACL, VFS_FUNC_VARS_ACL) +VFS_MFUNC(remove_acl, VFS_FUNC_ARGS_REMOVE_ACL, VFS_FUNC_VARS_REMOVE_ACL) +#endif +VFS_MFUNC(ea_getsize, VFS_FUNC_ARGS_EA_GETSIZE, VFS_FUNC_VARS_EA_GETSIZE) +VFS_MFUNC(ea_getcontent, VFS_FUNC_ARGS_EA_GETCONTENT, VFS_FUNC_VARS_EA_GETCONTENT) +VFS_MFUNC(ea_list, VFS_FUNC_ARGS_EA_LIST, VFS_FUNC_VARS_EA_LIST) +VFS_MFUNC(ea_set, VFS_FUNC_ARGS_EA_SET, VFS_FUNC_VARS_EA_SET) +VFS_MFUNC(ea_remove, VFS_FUNC_ARGS_EA_REMOVE, VFS_FUNC_VARS_EA_REMOVE) + +static int vfs_validupath(VFS_FUNC_ARGS_VALIDUPATH) +{ + return vol->vfs_modules[0]->vfs_validupath(VFS_FUNC_VARS_VALIDUPATH); +} + +/* + * These function pointers get called from the lib users via vol->vfs->func. + * These funcs are defined via the macros above. + */ +static struct vfs_ops vfs_master_funcs = { + vfs_validupath, + vfs_chown, + vfs_renamedir, + vfs_deletecurdir, + vfs_setfilmode, + vfs_setdirmode, + vfs_setdirunixmode, + vfs_setdirowner, + vfs_deletefile, + vfs_renamefile, + vfs_copyfile, +#ifdef HAVE_ACLS + vfs_acl, + vfs_remove_acl, +#endif + vfs_ea_getsize, + vfs_ea_getcontent, + vfs_ea_list, + vfs_ea_set, + vfs_ea_remove +}; + +/* + * Primary adouble modules: v2, ea + */ + +static struct vfs_ops netatalk_adouble_v2 = { + /* vfs_validupath: */ validupath_adouble, + /* vfs_chown: */ RF_chown_adouble, + /* vfs_renamedir: */ RF_renamedir_adouble, + /* vfs_deletecurdir: */ RF_deletecurdir_adouble, + /* vfs_setfilmode: */ RF_setfilmode_adouble, + /* vfs_setdirmode: */ RF_setdirmode_adouble, + /* vfs_setdirunixmode:*/ RF_setdirunixmode_adouble, + /* vfs_setdirowner: */ RF_setdirowner_adouble, + /* vfs_deletefile: */ RF_deletefile_adouble, + /* vfs_renamefile: */ RF_renamefile_adouble, + /* vfs_copyfile: */ RF_copyfile_adouble, + NULL +}; + +static struct vfs_ops netatalk_adouble_ea = { + /* vfs_validupath: */ validupath_ea, + /* vfs_chown: */ RF_chown_ea, + /* vfs_renamedir: */ RF_renamedir_ea, + /* vfs_deletecurdir: */ RF_deletecurdir_ea, + /* vfs_setfilmode: */ RF_setfilmode_ea, + /* vfs_setdirmode: */ RF_setdirmode_ea, + /* vfs_setdirunixmode:*/ RF_setdirunixmode_ea, + /* vfs_setdirowner: */ RF_setdirowner_ea, + /* vfs_deletefile: */ RF_deletefile_ea, + /* vfs_renamefile: */ RF_renamefile_ea, + /* vfs_copyfile: */ RF_copyfile_ea, + NULL +}; + +/* + * Secondary vfs modules for Extended Attributes + */ + +static struct vfs_ops netatalk_ea_adouble = { + /* vfs_validupath: */ NULL, + /* vfs_chown: */ ea_chown, + /* vfs_renamedir: */ NULL, /* ok */ + /* vfs_deletecurdir: */ NULL, /* ok */ + /* vfs_setfilmode: */ ea_chmod_file, + /* vfs_setdirmode: */ NULL, /* ok */ + /* vfs_setdirunixmode:*/ ea_chmod_dir, + /* vfs_setdirowner: */ NULL, /* ok */ + /* vfs_deletefile: */ ea_deletefile, + /* vfs_renamefile: */ ea_renamefile, + /* vfs_copyfile */ ea_copyfile, +#ifdef HAVE_ACLS + /* vfs_acl: */ NULL, + /* vfs_remove_acl */ NULL, +#endif + /* vfs_getsize */ get_easize, + /* vfs_getcontent */ get_eacontent, + /* vfs_list */ list_eas, + /* vfs_set */ set_ea, + /* vfs_remove */ remove_ea +}; + +static struct vfs_ops netatalk_ea_sys = { + /* validupath: */ NULL, + /* rf_chown: */ NULL, + /* rf_renamedir: */ NULL, + /* rf_deletecurdir: */ NULL, + /* rf_setfilmode: */ NULL, + /* rf_setdirmode: */ NULL, + /* rf_setdirunixmode: */ NULL, + /* rf_setdirowner: */ NULL, + /* rf_deletefile: */ NULL, + /* rf_renamefile: */ NULL, + /* vfs_copyfile: */ sys_ea_copyfile, +#ifdef HAVE_ACLS + /* rf_acl: */ NULL, + /* rf_remove_acl */ NULL, +#endif + /* ea_getsize */ sys_get_easize, + /* ea_getcontent */ sys_get_eacontent, + /* ea_list */ sys_list_eas, + /* ea_set */ sys_set_ea, + /* ea_remove */ sys_remove_ea +}; + +/* + * Tertiary VFS modules for ACLs + */ + +#ifdef HAVE_NFSV4_ACLS +static struct vfs_ops netatalk_solaris_acl_adouble = { + /* validupath: */ NULL, + /* rf_chown: */ NULL, + /* rf_renamedir: */ NULL, + /* rf_deletecurdir: */ NULL, + /* rf_setfilmode: */ NULL, + /* rf_setdirmode: */ NULL, + /* rf_setdirunixmode: */ NULL, + /* rf_setdirowner: */ NULL, + /* rf_deletefile: */ NULL, + /* rf_renamefile: */ NULL, + /* vfs_copyfile */ NULL, + /* rf_acl: */ RF_solaris_acl, + /* rf_remove_acl */ RF_solaris_remove_acl, + NULL +}; +#endif + +#ifdef HAVE_POSIX_ACLS +static struct vfs_ops netatalk_posix_acl_adouble = { + /* validupath: */ NULL, + /* rf_chown: */ NULL, + /* rf_renamedir: */ NULL, + /* rf_deletecurdir: */ NULL, + /* rf_setfilmode: */ NULL, + /* rf_setdirmode: */ NULL, + /* rf_setdirunixmode: */ NULL, + /* rf_setdirowner: */ NULL, + /* rf_deletefile: */ NULL, + /* rf_renamefile: */ NULL, + /* vfs_copyfile */ NULL, + /* rf_acl: */ RF_posix_acl, + /* rf_remove_acl */ RF_posix_remove_acl, + NULL +}; +#endif + +/* ---------------- */ +void initvol_vfs(struct vol *vol) +{ + vol->vfs = &vfs_master_funcs; + + /* Default adouble stuff */ + if (vol->v_adouble == AD_VERSION2) { + vol->vfs_modules[0] = &netatalk_adouble_v2; + vol->ad_path = ad_path; + } else { + vol->vfs_modules[0] = &netatalk_adouble_ea; +#ifdef HAVE_EAFD + vol->ad_path = ad_path_ea; +#else + vol->ad_path = ad_path_osx; +#endif + } + + /* Extended Attributes */ + if (vol->v_vfs_ea == AFPVOL_EA_SYS) { + LOG(log_debug, logtype_afpd, "initvol_vfs: enabling EA support with native EAs"); + vol->vfs_modules[1] = &netatalk_ea_sys; + } else if (vol->v_vfs_ea == AFPVOL_EA_AD) { + LOG(log_debug, logtype_afpd, "initvol_vfs: enabling EA support with adouble files"); + vol->vfs_modules[1] = &netatalk_ea_adouble; + } else { + LOG(log_debug, logtype_afpd, "initvol_vfs: volume without EA support"); + } + + /* ACLs */ +#ifdef HAVE_NFSV4_ACLS + vol->vfs_modules[2] = &netatalk_solaris_acl_adouble; +#endif +#ifdef HAVE_POSIX_ACLS + vol->vfs_modules[2] = &netatalk_posix_acl_adouble; +#endif + +} diff --git a/libevent/ChangeLog b/libevent/ChangeLog new file mode 100644 index 0000000..f09e724 --- /dev/null +++ b/libevent/ChangeLog @@ -0,0 +1,1245 @@ +Changes in version 2.0.18-stable (22 Mar 2012) +BUGFIXES (core): + o Make uses of open() close-on-exec safe by introducing an internal evutil_open_closeonexec. (d2b5f72 Ross Lagerwall, 03dce42) + +BUGFIXES (kqueue): + o Properly zero the kevent in kq_setup_kevent() (c2c7b39 Sebastian Hahn) + +BUILD FIXES: + o Added OPENSSL_LDFLAGS env variable which is appended to SSL checks. (9278196 Mark Ellzey) + o Changed OPENSSL_LDFLAGS to OPENSSL_LIBADD (2d67b63 Mark Ellzey) + o Don't do clang version detection when disabling some flags (083296b Sebastian Hahn) + +BUGFIXES (dns): + o Stop crashing in evdns when nameserver probes give a weird error (bec5068) + + +Changes in version 2.0.17-stable (10 Feb 2012) + +BUGFIXES (core): + o Be absolutely sure to clear pncalls before leaving event_signal_closure (11f36a5) + o check for sysctl before we use it (358c745 Mike Frysinger) + o Remove bogus casts of socket to int before calling ev_callback (f032516) + o Make evconnlistener work around bug in older Linux when getting nmapped (ecfc720) + o Fix a list corruption bug when using event_reinit() with signals present (6e41cdc) + o Fix a fd leak in event_reinit() (3f18ad1) + o Do a memberwise comparison of threading function tables (c94a5f2 Nate R) + o Use C-style comments in C source files (for compatibility with compilers such as xlc on AIX). (d84d917 Greg Hewgill) + o Avoid crash when freeing event_iocp and using event_set_mem_functions (19715a6 + o In the kqueue backend, do not report EBADF as an EV_READ (5d7bfa1 Nicholas Marriott) + +BUGFIXES (evbuffer and bufferevents): + o Fix behavior of evbuffer_peek(buf,-1,NULL,NULL,0) (c986f23 Zack Weinberg) + o Loop on filtering SSL reads until we are blocked or exhausted. (5b4b812) + +BUGFIXES (evhttp): + o Force strict validation of HTTP version in response. (790f6b3 Catalin Patulea) + +BUGFIXES (evdns): + o evdns: fix a bug in circular-queue implementation (d6094b1) + +BUILD FIXES: + o Fix a silly compilation error with the sun compiler (1927776 Colin Watt) + o Suppress a gcc warning from ignoring fwrite return in http-sample.c (7206e8c) + +DOCUMENTATION FIXES: + o Slightly clarify evbuffer_peek documentation (7bbf6ca) + o Update copyright notices to 2012 (e49e289) + +NEW APIS: + o Backport evhttp_connection_get_bufferevent to Libevent 2.0 (da70fa7 Arno Bakker) + +TESTS AND TEST FIXES: + o Fix a race condition in the dns/bufferevent_connect_hostname test. (cba48c7) + o Add function to check referential integrity of an event_base (27737d5) + o Check event_base correctness at end of each unit test (3312b02) + o Workaround in the unit tests for an apparent epoll bug in Linux 3.2 (dab9187) + o Better workaround for Linux 3.2 edge-triggered epoll bug (9f9e259) + +Changes in version 2.0.16-stable (18 Nov 2011) +BUGFIXES (core): + o More detailed message in case of libevent self-debugging failure. (9e6a4ef Leonid Evdokimov) + o epoll: close fd on alloc fail at initialization (1aee718 Jamie Iles) + o Fix compile warning from saying event2/*.h inside a comment (447b0ba) + o Warn when unable to construct base because of failing make_base_notifiable (4e797f3) + o Don't try to make notifiable event_base when no threading fns are configured (e787413) + +BUGFIXES (evbuffer): + o unit test for remove_buffer bug (90bd620 Greg Hazel) + o Fix an evbuffer crash in evbuffer_remove_buffer() (c37069c) + +BUGFIXES (bufferevent_openssl): + o Refactor amount-to-read calculations in buffervent_ssl consider_reading() (a186e73 Mark Ellzey) + o Move SSL rate-limit enforcement into bytes_to_read() (96c562f) + o Avoid spinning on OpenSSL reads (2aa036f Mark Ellzey) + +BUGFIXES (dns) + o Empty DNS reply with OK status is another way to say NODATA. (21a08d6 Leonid Evdokimov) + +TESTING: + o Tests for 94fba5b and f72e8f6 (d58c15e Leonid Evdokimov) + o Test for commit aff6ba1 (f7841bf Leonid Evdokimov) + o Style and comment tweaks for dns/leak* tests (5e42202) + o improve test to remove at least one buffer from src (7eb52eb Greg Hazel) + +DOCUMENTATION: + o Add note about evhttp_send_reply_end to its doxygen (724bfb5) + o Update copyright dates to 2011. (3c824bd) + o Fix typo in whatsnew-2.0.txt (674bc6a Mansour Moufid) + o Improve win32 behavior of dns-sample.c code (a3f320e Gisle Vanem) + + + +Changes in version 2.0.15-stable (12 Oct 2011) +BUGFIXES (DNS): + o DNS: add ttl for negative answers using RFC 2308 idea. (f72e8f6 Leonid Evdokimov) + o Add DNS_ERR_NODATA error code to handle empty replies. (94fba5b Leonid Evdokimov) + +BUFGIXES (bufferevents and evbuffers): + o Make evbuffer callbacks get the right n_added value after evbuffer_add (1ef1f68 Alex) + o Prefer mmap to sendfile unless a DRAINS_TO_FD flag is set. Allows add_file to work with SSL. (0ba0af9) + +BUGFIXES (event loop): + o When a signal callback is activated to run multiple times, allow event_base_loopbreak to work even before they all have run. (4e8eb6a) + +DOCUMENTATION FIXES: + o Fix docstring in dns.h (2b6eae5 Leonid Evdokimov) + o refer to non-deprecated evdns functions in comments (ba5c27d Greg Hazel) + +BUILD AND TESTING FIXES: + o le-proxy and regress depend on openssl directly (9ae061a Sergey Avseyev) + o Use _SOURCES, not _sources, in sample/Makefile.am (7f82382) + o Fixed compiler warnings for unchecked read/write calls. (c3b62fd Mark Ellzey) + o Make write-checking fixes use tt_fail_perror (2b76847) + o Fix some "value never used" warnings with gcc 4.6.1 (39c0cf7) + + + +Changes in version 2.0.14-stable (31 Aug 2011) +BUGFIXES (bufferevents and evbuffers): + o Propagate errors on the underlying bufferevent to the user. (4a34394 Joachim Bauch) + o Ignore OpenSSL deprecation warnings on OS X (5d1b255 Sebastian Hahn) + o Fix handling of group rate limits under 64 bytes of burst (6d5440e) + o Solaris sendfile: correctly detect amount of data sent (643922e Michael Herf) + o Make rate limiting work with common_timeout logic (5b18f13) + o clear read watermark on underlying bufferevent when creating filtering bev to fix potentially failing fragmented ssl handshakes (54f7e61 Joachim Bauch) + +BUGFIXES (IOCP): + o IOCP: don't launch reads or writes on an unconnected socket (495c227) + o Make IOCP rate-limiting group support stricter and less surprising. (a98da7b) + o Have test-ratelim.c support IOCP (0ff2c5a) + o Make overlapped reads result in evbuffer callbacks getting invoked (6acfbdd) + o Correctly terminate IO on an async bufferevent on bufferevent_free (e6af35d) + +BUGFIXES (other): + o Fix evsig_dealloc memory leak with debugging turned on. (9b724b2 Leonid Evdokimov) + o Fix request_finished memory leak with debugging turned on. (aff6ba1 Leonid Evdokimov) + +BUILD AND TESTING FIXES: + o Allow OS-neutral builds for platforms where some versions have arc4random_buf (b442302 Mitchell Livingston) + o Try to fix 'make distcheck' errors when building out-of-tree (04656ea Dave Hart) + o Clean up some problems identified by Coverity. (7c11e51 Harlan Stenn) + + +Changes in version 2.0.13-stable (18 Jul 2011) +BUGFIXES + o Avoid race-condition when initializing global locks (b683cae) + o Fix bug in SSL bufferevents backed by a bev with a write high-watermarks (e050703 Joachim Bauch) + o Speed up invoke_callbacks on evbuffers when there are no callbacks (f87f568 Mark Ellzey) + o Avoid a segfault when all methods are disabled or broken (27ce38b) + o Fix incorrect results from evbuffer_search_eol(EOL_LF) (4461f1a) + o Add some missing checks for mm_calloc failures (89d5e09) + o Replace an assertion for event_base_free(NULL) with a check-and-warn (09fe97d) + o Report kqueue ebadf, epipe, and eperm as EV_READ events (1fd34ab) + o Check if the `evhttp_new_object' function in `http.c' returns NULL. (446cc7a Mansour Moufid) + o Use the correct printf args when formatting size_t (3203f88) + o Complain if the caller tries to change threading cbs after setting them (cb6ecee) + +DOCUMENTATION FIXES AND IMPROVEMENTS + o Revise the event/evbuffer/bufferevent doxygen for clarity and accuracy (2888fac) + o Update Doxyfile to produce more useful output (aea0555) + +TEST FIXES + o Fix up test_evutil_snprintf (caf695a) + o Fix tinytest invocation from windows shell (57def34 Ed Day) + +BUILD FIXES + o Use AM_CPPFLAGS in sample/Makefile.am, not AM_CFLAGS (4a5c82d) + o Fix select.c compilation on systems with no NFDBITS (49d1136) + o Fix a few warnings on OpenBSD (8ee9f9c Nicholas Marriott) + o Don't break when building tests from git without python installed (b031adf) + o Don't install event_rpcgen.py when --disable-libevent-install is used (e23cda3 Harlan Stenn) + o Fix AIX build issue with TAILQ_FOREACH definition (e934096) + + +Changes in version 2.0.12-stable (4 Jun 2011) +BUGFIXES + o Fix a warn-and-fail bug in kqueue by providing kevent() room to report errors (28317a0) + o Fix an assert-inducing fencepost bug in the select backend (d90149d) + o Fix failing http assertion introducd in commit 0d6622e (0848814 Kevin Ko) + o Fix a bug that prevented us from configuring IPv6 nameservers. (74760f1) + o Prevent size_t overflow in evhttp_htmlescape. (06c51cd Mansour Moufid) + o Added several checks for under/overflow conditions in evhttp_handle_chunked_read (a279272 Mark Ellzey) + o Added overflow checks in evhttp_read_body and evhttp_get_body (84560fc Mark Ellzey) + +DOCUMENTATION: + o Add missing words to EVLOOP_NONBLOCK documentation (9556a7d) + +BUILD FIXES + o libssl depends on libcrypto, not the other way around. (274dd03 Peter Rosin) + o Libtool brings in the dependencies of libevent_openssl.la automatically (7b819f2 Peter Rosin) + o Use OPENSSL_LIBS in Makefile.am (292092e Sebastian Hahn) + o Move the win32 detection in configure.in (ceb03b9 Sebastian Hahn) + o Correctly detect openssl on windows (6619385 Sebastian Hahn) + o Fix a compile warning with zlib 1.2.4 and 1.2.5 (5786b91 Sebastian Hahn) + o Fix compilation with GCC 2, which had no __builtin_expect (09d39a1 Dave Hart) + o Fix new warnings from GCC 4.6 (06a714f) + o Link with -lshell32 and -ladvapi32 on Win32. (86090ee Peter Rosin) + o Make the tests build when OpenSSL is not available. (07c41be Peter Rosin) + o Bring in the compile script from automake, if needed. (f3c7a4c Peter Rosin) + o MSVC does not provide S_ISDIR, so provide it manually. (70be7d1 Peter Rosin) + o unistd.h and sys/time.h might not exist. (fe93022 Peter Rosin) + o Make sure TINYTEST_LOCAL is defined when building tinytest.c (8fa030c Peter Rosin) + o Fix winsock2.h #include issues with MSVC (3d768dc Peter Rosin) + o Use evutil_gettimeofday instead of relying on the system gettimeofday. (0de87fe Peter Rosin) + o Always use evutil_snprintf, even if OS provides it (d1b2d11 Sebastian Hahn) + o InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x0403. (816115a Peter Rosin) + o cygwin: make it possible to build DLLs (d54d3fc) + + + +Changes in version 2.0.11-stable (27 Apr 2011) + [Autogenerated from the Git log, sorted and cleaned by hand.] +BUGFIXES: + o Fix evport handling of POLLHUP and POLLERR (b42ce4b) + o Fix compilation on Windows with NDEBUG (cb8059d) + o Check for POLLERR, POLLHUP and POLLNVAL for Solaris event ports (0144886 Trond Norbye) + o Detect and handle more allocation failures. (666b096 Jardel Weyrich) + o Use event_err() only if the failure is truly unrecoverable. (3f8d22a Jardel Weyrich) + o Handle resize failures in the select backend better. (83e805a) + o Correctly free selectop fields when select_resize fails in select_init (0c0ec0b) + o Make --enable-gcc-warnings a no-op if not using gcc (3267703) + o Fix a type error in our (unused) arc4random_stir() (f736198) + o Correctly detect and stop non-chunked http requests when the body is too long (63a715e) + o Have event_base_gettimeofday_cached() always return wall-clock time (a459ef7) + o Workaround for http crash bug 3078187 (5dc5662 Tomash Brechko) + o Fix incorrect assertions and possible use-after-free in evrpc_free() (4b8f02f Christophe Fillot) + o Reset outgoing http connection when read data in idle state. (272823f Tomash Brechko) + o Fix subtle recursion in evhttp_connection_cb_cleanup(). (218cf19 Tomash Brechko) + o Fix the case when failed evhttp_make_request() leaved request in the queue. (0d6622e Tomash Brechko) + o Fix a crash bug in evdns server circular list code (00e91b3) + o Handle calloc failure in evdns. (Found by Dave Hart) (364291e) + o Fix a memory leak on win32 socket->event map. (b4f89f0) + o Add a forgotten NULL check to evhttp_parse_headers (12311ff Sebastian Hahn) + o Fix possible NULL-deref in evdns_cancel_request (5208544 Sebastian Hahn) + +PORTABILITY: + o Fall back to sscanf if we have no other way to implement strtoll (453317b) + o Build correctly on platforms without sockaddr_storage (9184563) + o Try to build correctly on platforms with no IPv6 support (713c254) + o Build on systems without AI_PASSIVE (cb92113) + o Fix http unit test on non-windows platforms without getaddrinfo (6092f12) + o Do not check for gethostbyname_r versions if we have getaddrinfo (c1260b0) + o Include arpa/inet.h as needed on HPUX (10c834c Harlan Stenn) + o Include util-internal.h as needed to build on platforms with no sockaddr_storage (bbf5515 Harlan Stenn) + o Check for getservbyname even if not on win32. (af08a94 Harlan Stenn) + o Add -D_OSF_SOURCE to fix hpux builds (0b33479 Harlan Stenn) + o Check for allocation failures in apply_socktype_protocol_hack (637d17a) + o Fix the check for multicast or broadcast addresses in evutil_check_interfaces (1a21d7b) + o Avoid a free(NULL) if out-of-memory in evdns_getaddrinfo. Found by Dave Hart (3417f68) + +DEFENSIVE PROGRAMMING: + o Add compile-time check for AF_UNSPEC==PF_UNSPEC (3c8f4e7) + +BUGS IN TESTS: + o Fix test.sh output on solaris (b4f89b6 Dave Hart) + o Make test-eof fail with a timeout if we never get an eof. (05a2c22 Harlan Stenn) + o Use %s with printf in test.sh (039b9bd) + o Add an assert to appease clang's static analyzer (b0ff7eb Sebastian Hahn) + o Add a forgotten return value check in the unit tests (3819b62 Sebastian Hahn) + o Actually send NULL request in http_bad_request_test (b693c32 Sebastian Hahn) + o add some (void) casts for unused variables (65707d7 Sebastian Hahn) + o Refactor test_getaddrinfo_async_cancel_stress() (48c44a6 Sebastian Hahn) + o Be nice and "handle" error return values in sample code (4bac793 Sebastian Hahn) + o Check return value of evbuffer_add_cb in tests (93a1abb Sebastian Hahn) + o Remote some dead code from dns-example.c (744c745 Sebastian Hahn) + o Zero a struct sockaddr_in before using it (646f9fe Sebastian Hahn) + +BUILD FIXES: + o Fix warnings about AC_LANG_PROGRAM usage (f663112 Sebastian Hahn) + o Skip check for zlib if we have no zlib.h (a317c06 Harlan Stenn) + o Fix autoconf bracket issues; make check for getaddrinfo include netdb.h (833e5e9 Harlan Stenn) + o Correct an AM_CFLAGS to an AM_CPPFLAGS in test/Makefile.am (9c469db Dave Hart) + o Fix make distcheck & installation of libevent 1 headers (b5a1f9f Dave Hart) + o Fix compilation under LLVM/clang with --enable-gcc-warnings (ad9ff58 Sebastian Hahn) + +FEATURES: + o Make URI parser able to tolerate nonconformant URIs. (95060b5) + +DOCUMENTATION: + o Clarify event_set_mem_functions doc (926f816) + o Correct evhttp_del_accept_socket documentation on whether socket is closed (f665924) + o fix spelling mistake in whatsnew-2.0.txt (deb2f73) + o Fix sample/http-server ipv6 fixes (eb692be) + o Comment internal headers used in sample code. (4eb281c) + o Be explicit about how long event loops run in event.h documentation (f95bafb) + o Add comment to configure.in to explain gc-sections test logic (c621359) + o Fix a couple of memory leaks in samples/http-server.c. Found by Dave Hart. (2e9f665) + +BUILD IMPROVEMENTS: + o Use the gcc -ffunction-segments feature to allow gc when linking with static libevent (0965c56 Dave Hart) + o Add configure options to disable installation, regression tests (49e9bb7 Dave Hart) + + + +Changes in version 2.0.10-stable (16 Dec 2010) + [Autogenerated from the Git log, sorted and cleaned by hand.] +BUGFIXES + o Minor fix for IOCP shutdown handling fix (2599b2d Kelly Brock) + o Correctly notify the main thread when activating an event from a subthread (5beeec9) + o Reject overlong http requests early when Expect:100-continue is set (d23839f Constantine Verutin) + o EVUTIL_ASSERT: Use sizeof() to avoid "unused variable" warnings with -DNDEBUG. (b63ab17 Evan Jones) + +CODE CLEANUPS + o bufferevent-internal.h: Use the new event2/util.h header, not evutil.h (ef5e65a Evan Jones) + o Use relative includes instead of system includes consistently. (fbe64f2 Evan Jones) + o Make whitespace more consistent + +TESTING + o tests: Use new event2 headers instead of old compatibility headers. (4f33209 Evan Jones) + +DOCUMENTATION + o Document that the cpu_hint is only used on Windows with IOCP for now (57689c4) + o Add stuff to "whats new in 2.0" based on reading include changes since August. (18adc3f) + + +Changes in 2.0.9-rc (30 Nov 2010): + [Autogenerated from the Git log, sorted and cleaned by hand.] +NEW AND MODIFIED APIs + o Add a function to change a listener's callback. (46ee061) + o Make evbuffer_add_file take ev_off_t, not off_t (ac7e52d) + o Make rate-limits go up to SIZE_MAX/EV_SSIZE_MAX, not just INT32_MAX (2cbb1a1) + o Add a bufferevent_get_base function (aab49b6) + +MAJOR BUGFIXES + o Disable changelist for epoll by default because of Linux dup() bug; add an option and/or an envvar to reenable it for speed. (9531763) + o Fix a 100%-CPU bug where an SSL connection would sometimes never stop trying to write (1213d3d) + o Fix a nasty bug related to use of dup() with epoll on Linux (c281aba) + o Fix bugs in posix thread-id calculation when sizeof(pthread_t) != sizeof(long) (fbaf077) + o Fix some ints to evutil_socket_t; make tests pass on win64. (f817bfa Dimitre Piskyulev) + o Set _EVENT_SIZEOF_VOID_P correctly on win32 and win64 (1ae82cd Dimitre Piskyulev) + o Avoid double-invocation of user callback with EVUTIL_EAI_CANCEL (abf01ed) + o Set SO_UPDATE_ACCEPT_CONTEXT on sockets from AcceptEx so that shutdown() can work (52aa419) + o When closing a filtering bufferevent, clear callbacks on the underlying bufferevent (fc7b1b0) + +NEW AND MODIFIED HTTP APIs + o Add evhttp_parse_query_str to be used with evhttp_uri_parse. (2075fbc) + o Add evhttp_response_code to remove one more reason to include http_struct.h (22e0a9b) + o Define enumerators for all HTTP methods, including PATCH from RFC5789 (75a7341 Felix Nawothnig) + o Functions to actually use evhttp_bound_socket with/as evconnlistener. (006efa7) + o Add evhttp_request_get_command so code can tell GET from POST without peeking at the struct. (49f4bf7) + o Introduce absolute URI parsing helpers. (86dd720 Pavel Plesov) + o Revise evhttp_uri_parse implementation to handle more of RFC3986 (eaa5f1d) + o Add evhttp_connection_get_base() to get the event_base from an http connection (cd00079) + o Let evhttp_parse_query return -1 on failure (b1756d0) + o New evhttp_uri(encode|decode) functions to handle + and NUL characters right (a8148ce) + o Add evhttp_response_code to remove one more reason to include http_struct.h (22e0a9b) + o Tweak interface for allowed methods (f5b391e) + o Add evhttp server alias interface, correct flagging of proxy requests. (aab8c38 Christopher Davis) + +HTTP BUGFIXES + o Add some comments to http.c and make a few functions static. (90b3ed5) + o Fix Content-Length when trying send more than 100GB of data (!) on an evhttp. (525da3e) + o Fix a bug where we would read too much data in HTTP bodies or requests. (58a1cc6) + o Correctly count req->body_size on http usage without Content-Length (8e342e5) + o Avoid missed-request bug when entire http request arrives before data is flushed (74c0e86) + o reset "chunked" flag when sending non-chunked reply (aa5f55f Joachim Bauch) + o evhttp_encode_uri encodes all reserved characters, including !$'()*+,/:=@ (2e63a60) + o Replace exact-version checks for HTTP/1.1 with >= or < checks (647e094) + o evhttp: Return 501 when we get an unrecognized method, not 400. (536311a) + o Don't disable reading from the HTTP connection after sending the request to be notified of connection-close in time (c76640b Felix Nawothnig) + o Never call evhttp_readcb while writing. (0512487) + o Try to fix an assertion failure related to close detection (0faaa39) + o Correctly detect timeouts during http connects (04861d5) + o Preliminary support for Continue expectation in evhttp. (fa9305f Christopher Davis) + +OTHER BUGFIXES + o Correct logic for realigning a chain in evbuffer_add (e4f34e8) + o Fix a minor syntax error that most compilers didn't care about (e56ff65) + o Fix some uses of int for socket in regress (5d389dc) + o Check return value for ioctlsocket on win32 (f5ad31c Trond Norbye) + o Fix som event_warns that should have been event_warnx (19c71e7) + o Fix signal handler types for win64. (b81217f) + o Try to clear up more size_t vs int/long issues. (598d133) + o Make sure IOCP evconnlistener uses virtual events. (7b40a00 Christopher Davis) + o Don't free evdns_request handles until after the callback is invoked (9ed30de) + o Fix some more cancel-related bugs in getaddrinfo_async (c7cfbcf) + o Make evdns_getaddrinfo_cancel threadsafe (d51b2fc) + o Only clear underlying callbacks when the user hasn't reset them. (1ac5b23) + o Fix bug in bufferevent_connect on an openssl bufferevent that already had an fd (4f228a1) + o Resolve an evport bug in the thread/forking test (3a67d0b) + o Make sure the CLOEXEC flag is set on fds we open for base notification (3ab578f) + o Fix IRIX build. sa_family collides with a #define in sys/socket.h on IRIX. (e874982 Kevin Bowling) + o If not WIN32, include in event2/util.h. (1cd45e5 Kevin Bowling) + o Fix some C99-style comments to work with the xlC compiler. (c2e5e22 Kevin Bowling) + o Add some checks since lack of TAILQ_FOREACH doesn't imply lack of FIRST, END, NEXT, or INSERT_BEFORE. Quiet some warnings in XL C. (c4dc335 Kevin Bowling) + o Reworked AIX __ss_family workaround to use AC_STRUCT_MEMBER. (2e2a3d7 Kevin Bowling) + o Take select from when testing in autoconf. AIX build fix. (a3a9f6b Kevin Bowling) + o Fix snprintf related failures on IRIX. (3239073 Kevin Bowling) + o Remove _event_initialized(); make event_initialized() a function(); make it consistent on windows and non-windows (652024b) + o Do not let EVLOOP_ONCE exit the loop until all deferred callbacks have run (2d5e1bd) + o Make EVLOOP_ONCE ignore internal events (0617a81) + o Possible crash fix when freeing an underlying bufferevent of an openssl bufferevent (29f7623) + +HTTP CLEANUPS + o Stop using Libevent-1 headers in regress_http (1f507d7) + o Modernize header usage in bench_http.c (e587069) + o fix signed/unsigned warnings in http.c (74a91e5) + o Update the HTTP regression tests to use Libevent2 apis for non-http stuff (d9ffa89) + o Start porting http tests to not use legacy interfaces (8505a74) + o Convert the rest of the http tests to be non-legacy unit tests. (9bb8239) + o Rename the confusing "base" static variable in regress_http.c (353402a) + o Stop accessing http request struct directly from in the unit tests. (0b137f4) + o Refactor http version parsing into a single function (a38140b) + +TESTING + o Improvements to tinytest_macros.h (ad923a1) + o Add a huge pile of tests for the new URI functions, and make them pass. (a5a76e6) + o Unit tests for evhttp_uri_set* (bc98f5e) + o Increase the skew tolerance to 2 seconds in thread/deferred_cb_skew (f806476 Christopher Davis) + o Reorder backends in test.sh to match preference order in event.c (ece974f) + o Add a stress test for getaddrinfo_cancel (da1bf52) + o Units test for unexpected evhttp methods. (75e3320) + +DOCUMENTATION + o Document behavior of URI parsing more thoroughly. (3a33462) + o Document that two bufferevent functions only work on socket bufferevents (70e1b60) + o add a requested docstring for event_rpcgen.CommandLine.__init__ (f1250eb) + o Fix a mistake in http documentation found by Julien Blache (229714d) + o Add a basic example of how to write a static HTTP server. (4e794d5) + o Document event_get_assignment (88be27d) + o Note that reentrant calls to libevent from logging cbs may fail badly (e431bcd) + o Clarify EVLOOP_* documentation to be more precise. (057a514) + +CLEANUPS + o Simplify the logic for choosing EPOLL_CTL_ADD vs EPOLL_CTL_MOD (2c66983) + o Rename "size" variables in win32select that were really fd counts. (b6a158c) + o Fix even more win64 warnings (7484df6) + o Fix even more win64 warnings: buffer, event_tagging, http, evdns, evrpc (545a611) + o Fix more wn64 warnings. (34b84b9 Christopher Davis) + o Use the label_len local variable in evdns instead of recalculating it over and over (ba01456) + o Fix some irix compilation warnings spotted by Kevin Bowling (7bcace2) + + + +Changes in 2.0.8-rc (14 Oct 2010): + [Autogenerated from the Git log, sorted and cleaned by hand.] +NEW APIS + o Add error callback to evconnlistener (c4be8d8 Simon Perreault) + o Add a LEV_OPT_THREADSAFE option for threadsafe evconnlisteners (127d4f2) + +CHANGED BEHAVIOR + o Correct logic on disabling underlying bufferevents when disabling a filter (ac27eb8) + +BUGFIXES + o Obey enabled status when unsuspending (040a019 Simon Perreault) + o Warn when using the error-prone EV_SIGNAL interface in an error-prone way. Also, fix a couple of race conditions in signal.c (720bd93) + O Make default signal backend fully threadsafe (95a7d41) + o Put internal events at highest priority (90651b3) + o Fix warnings in the main codebase flagged by -Wsigned-compare (9c8db0, 5e4bafb, 5c214a, 6be589a, e06f514) + o Fix compile in kqueue.c (b395392 Sebastian Hahn) + o Do not search outside of the system directory for windows DLLs (d49b5e3) + o Fix a spurious-call bug on epoll.c (0faaee0) + o Send a shutdown(SHUT_WR) before closing an http connection (e0fd870 Christopher Davis) + o Fix warnings on mingw with gcc 4.5 (5b7a370) + o Fix an EINVAL on evbuffer_write_iovec on OpenSolaris. (fdc640b) + o Fix allocation error for IOCP listeners. Probably harmless, since struct event is big (481ef92) + o Make iocp/listener/error work; don't accept again if lev is disabled. (62b429a Christopher Davis) + o Handle rate-limiting for reading on OpenSSL bufferevents correctly. (819b171) + o Fix serious bugs in per-bufferevent rate-limiting code (34d64f8) + o Avoid spurious reads from just-created open openssl bufferevents (223ee40) + o Fix a case where an ssl bufferevent with CLOSE_ON_FREE didn't close its fd (93bb7d8) + o The corrected bufferevent filter semantics let us fix our openssl tests (34331e4) + +TESTING + o Make SSL tests cover enabling/disabling EV_READ. (a5ce9ad) + o Bump to the latest version of tinytest (f0bd83e) + o Unit tests for listener error callbacks (045eef4) + o New unit test for ssl bufferevents starting with connected SSLs. (02f6259) + +DEBUGGABILITY + o Make debugging output for epoll backend more comprehensive (ec2b05e) + o Make event.c debugging messages report fds (e119899) + o Make the --enable-gcc-warnings option include signed comparison warnings (d3b096c) + +DEADCODE REMOVAL + o Remove the now-useless evsig_caught and evsig_process (4858b79) + o Remove event_base.evsigbase; nothing used it. (38d0960) + + + +Changes in 2.0.7-rc (9 Sep 2010): + [Autogenerated from the Git log, sorted and cleaned by hand.] +NEW APIS + o Expose a evdns_base_nameserver_sockaddr_add() function to add a nameserver by sockaddr (1952143) + o Add event_config_set_num_cpus_hint() for tuning win32 IOCP thread pools, etc. (2447fe8 Christopher Davis) + +BUGFIXES + o Fix a nasty dangling-event bug when using rate-limiting groups (0bffe43) + o Clean up syntax on TAILQ_ENTRY() usage to build correctly with recent MSVC (60433a0 Gilad Benjamini) + o Make definition of WIN32_LEAN_AND_MEAN in event.h conditional (3920172 Gilad Benjamini) + o Correctly detect failure to delete bufferevent read-timeout event (da6e7cd) + o Set close-on-exec bit for filedescriptors created by dns subsystem (d0b8843) + o Fix kqueue correctness test on x84_64 (6123d12) + o Detect events with no ev_base; warn instead of crashing (f1074b7) + o Fix an issue with forking and signal socketpairs in select/poll backends (d61b2f3) + o Stop using global arrays to implement the EVUTIL_ctype functions (1fdec20) + o On windows, make lock/thread function tables static (5de2bcb) + o Close th_notify_fds and open a new pair on reinit (495ed66) + o Declare signal handler function as "__cdecl" on Windows (f0056d0) + o Use the _func() replacements for open, fstat, etc in evutil.c on win32 (e50c0fc) + o Only process up to MAX_DEFERRED deferred_cbs at a time (17a14f1 Christopher Davis) + +THREADING BUGFIXES + o Avoid deadlock when activating signals (970e6ad) + o Add a condition variable backend, with implementations for pthreads and win32 (d4977b5) + o Use conditions instead of current_event_lock to fix a deadlock (e0972c2) + o Fix logic error in win32 TRY_LOCK that caused problems with rate-limiting (4c32b9d) + o Avoid needlessly calling evthread_notify_base() when the loop is not running (c7a06bf) + o Minimize calls to base_notify implementation functions, thereby avoiding needless syscalls (4632b78) + +IOCP BUGFIXES + o IOCP-related evbuffer fixes (03afa20 Christopher Davis) + o Stop IOCP when freeing the event_base (d844242 Christopher Davis) + o Some IOCP bufferevent tweaks (76f7e7a Christopher Davis) + +TESTS + o Make the regress_pthread.c tests work on windows with current test APIs (d74ae38) + o Add a unit test for conditions (5fb1095) + o Allow more than one copy of regression tests to run at once (a97320a) + o Fix event_del(0) instance in bench.c (b0f284c Shuo Chen) + o Fix a few memory leaks in the tests (1115366) + o IOCP-related unit test tweaks (499452f Christopher Davis) + o Improve testing of when thread-notification occurs (ce85280) + +BUILD AND DISTRIBUTION + o Add pkgconfig files for libevent_{openssl,pthreads} (ebcb1f0) + o Change include order in Makefile.nmake (4022b28) + o Make include/event2/event-config.h not included in source dist (a4af9be) + o Honor NDEBUG; build without warnings with NDEBUG; make NDEBUG always-off in unit test code (743f866) + o Declare evkeyvalq and event_list even if event_struct.h comes before sys/queue.h (d3ceca8) + o Move evkeyvalq into a separate header for evhttp_parse_query users (ca9048f) + o Prefer autoreconf -ivf to manual autogen.sh (7ea8e89) + +CLEANUP + o Completely remove the (mostly-removed) obsolete thread functions (3808168) + o Rename regress_pthread.c to regress_thread.c (041989f) + o Make defer-internal.h use lock macros, not direct calls to lock fns (5218d2a) + +DOCUMENTATION + o Document that DNS_NO_SEARCH is an obsolete alias for DNS_QUERY_NO_SEARCH (33200e7) + o Update the whatsnew-2.0.txt document (4991669) + + + +Changes in 2.0.6-rc (6 Aug 2010): + [Autogenerated from the Git log, sorted by hand.] +DOCUMENTATION + o Document a change in the semantics of event_get_struct_event_size() (e21f5d1) + o Add a comment to describe our plan for library versioning (9659ece) + o Fix sentence fragment in docs for event_get_struct_event_size() (7b259b6) + +NEW FEATURES AND INTERFACE CHANGES + o Remove the obsolete evthread interfaces (c5bab56) + o Let evhttp_send_error infer the right error reasons (3990669) + o Add a function to retrieve the other side of a bufferevent pair (17a8e2d) + o Add bufferevent_lock()/bufferevent_unlock() (215e629) + o Stop asserting when asked for a (unsupported) TCP dns port. Just return NULL. (7e87a59) + o Replace (unused,always 0) is_tcp argument to evdns_add_server_port*() with flags (e1c1167) + o Constify a couple of arguments to evdns_server_request_add_*_reply (cc2379d) + o Add an interface to expose min_share in ratelimiting groups (6ae53d6) + +BUGFIXES + o Avoid event_del on uninitialized event in event_base_free (6d19510) + o Add some missing includes to fix Linux build again (75701e8) + o Avoid close of uninitialized socket in evbuffer unit test (bda21e7) + o Correctly recognize .255 addresses as link-local when looking for interfaces (8c3452b) + o If no evdns request can be launched, return NULL, not a handle (b14f151) + o Use generic win32 interfaces, not ASCII-only ones, where possible. (899b0a3) + o Fix the default HTTP error template (06bd056 Felix Nawothnig) + o Close the file in evutil_read_file whether there's an error or not. (0798dd1 Pierre Phaneuf) + o Fix possible nullptr dereference in evhttp_send_reply_end() (29b2e23 Felix Nawothnig) + o never let bufferevent_rlim functions return negative (0859870) + o Make sample/hello_world work on windows (d89fdba) + o Fix a deadlock related to event-base notification. Diagnosed by Zhou Li, Avi Bab, and Scott Lamb. (17522d2) + o Possible fix to 100% cpu usage with epoll and openssl (cf249e7 Mike Smellie) + o Don't race when calling event_active/event_add on a running signal event (fc5e0a2) + o Suppress a spurious EPERM warning in epoll.c (e73cbde) + o Fix wrong size calculation of iovec buffers when exact=1 (65abdc2 niks) + o Change bufferevent_openssl::do_write so it doesn't call SSL_write with a 0 length buffer (c991317 Mike Smellie) + o Fixed compilation of sample/le-proxy.c on win32 (13b912e Trond Norbye) + o Fix rate-limit calculation on openssl bufferevents. (009f300) + o Remember to initialize timeout events for bufferevent_async (de1f5d6 Christopher Davis) + +BUILD AND DISTRIBUTION CHANGES + o Test the unlocked-deferred callback case of bufferevents (dfb75ab) + o Remove the now-unusable EVTHREAD_LOCK/UNLOCK constants (fdfc3fc) + o Use -Wlogical-op on gcc 4.5 or higher (d14bb92) + o Add the libtool-generated /m4/* stuff to .gitignore (c21c663) + o Remove some automake-generated files from version control. (9b14911) + o Have autogen.sh pass --force-missing to automake (8a44062) + o Set library version for libevent_pthreads correctly (b2d7440) + o Really only add libevent_core.la to LIBADD on mingw (1425003 Sebastian Hahn) + o Build more cleanly with NetBSDs that dislike toupper(char) (42a8c71) + o Fix unit tests with -DUSE_DEBUG enabled (28f31a4) + o Fix evdns build with -DUNICODE (5fa30d2) + o Move event-config.h to include/event2 (ec347b9) + +TESTING + o Add options to test-ratelim.c to check its results (2b44dcc) + o Make test-ratelim clean up after itself better. (b5bfc44) + o Remove the now-obsolete setup_test() and cleanup_test() functions (e73f1d7) + o Remove all non-error prints from test/regress.c (8bc1e3d) + o Make test.sh exit with nonzero status if tests fail (faf2a04) + o Have the unit tests report errors from test.sh (3689bd2) + o Fix logic in correcting high values from FIONREAD (3467f2f) + o Add test for behavior on remote socket close (44d57ee) + o Unit test for event_get_struct_event_size() (7510aac) + o Make test/test.sh call test-changelist (7c92691) + o Fix badly-behaved subtest of dns/bufferevent_connect_hostname (840a72f Joachim Bauch) + o Add option to test-ratelim to test min_share (42f6b62) + o Fix an assertion bug in test-ratelim (b2c6202) + o Make tests quieter on local dns resolver failure (e996b3d) + o Increase the tolerance in our unit tests for sloppy clocks. (170ffd2) + o Use AF_INET socketpair to test sendfile on Solaris (9b60209) + o Make test-changelist count cpu usage right on win32 (ea1ea3d) + +INTERNALS, PERFORMANCE, AND CODE CLEANUPS + o Mark the event_err() functions as __attribute__((noreturn)) (33bbbed) + o Do not check that event_base is set in EVBASE_ACQUIRE_LOCK (218a3c3) + o Replace (safe) use of strcpy with memcpy to appease OpenBSD (caca2f4) + o Remove some dead assignments (47c5dfb) + o Fix a pedantic gcc 4.4 warning in event2/event.h (276e7ee) + o Drain th_notify_fd[0] more bytes at a time. (a5bc15b) + o Tidy up the code in evthread_make_base_notifiable a little (61e1eee) + o Pass flags to fcntl(F_SETFL) and fcntl(F_SETFD) as int, not long (7c2dea1) + o Remove unused variables in test/test-changelist.c (b00d4c0) + o Fix whitespace. (cb927a5) + o Improve error message for failed epoll to make debugging easier. (9e725f7) + o Turn our socketpair() replacement into its own function (57b30cd) + + + +Changes in 2.0.5-beta (10 May 2010): + [Autogenerated from the Git log, sorted by hand.] +DOCUMENTATION + o Update all our copyright notices to say "2010" (17efc1c) + o Add Christopher Clark and Maxim Yegorushkin to the LICENSE file (38b7b57) + o Clarify Christopher Clark's status as writer of original ht code. (78772c3) + o Try to comment some of the event code more (cdd4c49) + o Add a few more evmap/changelist comments (c247adc) + o Add a comment to explain why evdns_request is now separte from request (ceefbe8) + o Document evutil_secure_rng_init() and evutil_secure_rng_add_bytes() (a5bf43a) + o Stop distributing and installing manpages: they were too inaccurate (7731ec8) + +NEW FEATURES AND INTERFACE CHANGES + o Remove signal_assign() and signal_new() macros. (2fac0f7) + o Make evdns use the regular logging system by default (b2f2be6) + o Allow evbuffer_read() to split across more than 2 iovecs (e470ad3) + o Functions to manipulate existing rate limiting groups. (ee41aca) + o Functions to track the total bytes sent over a rate limit group. (fb366c1) + o Detect and refuse reentrant event_base_loop() calls (b557b17) + o Limit the maximum number of events on each socket to 65535 (819f949) + o Add evbuffer_copyout to copy data from an evbuffer without draining (eb86c8c) + o Expose the request and reply members of rpc_req_generic() (07edf78 Shuo Chen) + o Add void* arguments to request_new and reply_new evrpc hooks (755fbf1 Shuo Chen) + o Seed the RNG using sysctl() as well as /dev/urandom (71fc3eb) + o Make evutil_secure_rng_init() work even with builtin arc4random (f980716) + o Report DNS error when lookup fails during bufferevent_socket_connect_hostname. (0ef4070 Christopher Davis) + o Release locks on bufferevents while executing callbacks (a5208fe Joachim Bauch) o Make debug mode catch mixed ET and non-ET events on an fd (cb67074) + o Catch attempts to enable debug_mode too late (9ecf0d4) + o Refuse null keys in evhttp_parse_query() (953e229 Frank Denis) + +BUGFIXES + o Avoid a spurious close(-1) on Linux (70a44b6) + o Do not close(-1) when freeing an uninitialized socket bufferevent (b34abf3) + o Free evdns_base->req_heads on evdns_base_free (859af67) + o Avoid an (untriggerable so far) crash bug in bufferevent_free() (0cf1431) + o Set mem_offset for every bufferevent type (657d1b6) + o Fix infrequent memory leak in bufferevent_init_common(). (8398641 Jardel Weyrich) + o Make evutil_signal_active() match declaration. (e1e703d Patrick Galbraith) + o Fix minheap code to use replacement malloc functions (a527618) + o Fix a free(NULL) in minheap-internal.h (6f20492) + o Fix critical bug in evbuffer_write when writev is not available (cda56ab) + o Make the no_iovecs case of write_atmost compile (8e227b0) + o Fix a memory leak when appending/prepending to a buffer with unused space. (45068a3) + o Clean up a mistake in pointer manipulation in evbuffer_remove (28bfed4 Christopher Davis) + o Always round up when there's a fractional number of msecs. (8f9e60c Christopher Davis) + o Fix compiler warnings under WIN32 (d469c50 Giuseppe Scrivano) + o Clean up properly when adding a signal handler fails. (b84b598 Gilad Benjamini) o Ensure that evdns_request is a persistent handle. (15bb82d Christopher Davis) + o Free search state when finished searching to avoid an infinite loop. (a625840 Christopher Davis) + o Assert for valid requests as necessary. (67072f3 Christopher Davis) + o do not leak the request object on persistent connections (9d8edf2) + o Make evdns logging threadsafe (b1c7950) + o Fix a couple of bugs in the BSD sysctl arc4seed logic (a47a4b7) + o Remove one last bug in last_with_datap logic. Found with valgrind (d49b92a) + o fix a leak when unpausing evrpc requests (94ee125) + o Fix a memory leak when unmarshalling RPC object arrays (f6ab2a2) + o Fix compilation when openssl support is disabled (40c301b) + o Allow empty reason line in HTTP status (739e688 Pierre Phaneuf) + o Fix a compile warning introduced in 739e688 (bd1ed5f Sebastian Hahn) + o Fix nonstandard TAILQ_FOREACH_REVERSE() definition (71afc52 Frank Denis) + o Try /proc on Linux as entropy fallback; use sysctl as last resort (20fda29) + o Fix symbol conflict between mm_*() macros and libmm (99e50e9) + o Fix some crazy macro mistakes in arc4random.c (90d4225) + o Make evbuffer_add_file() work on windows (dcdae6b) + o Fix unused-variable warning when building with threads disabled (ad811cd) + o Numerous opensolaris compilation fixes (c44de06) + o Fix getaddrinfo with protocol unset on Solaris 9. Found by Dagobert Michelsen (2cf2a28) + o Fix another nasty solaris getaddrinfo() behavior (3557071) + o Define _REENTRANT as needed on Solaris, elsewhere (c1cd32a) + o Fix some autoconf issues on OpenBSD (7c519df) + +BUILD AND DISTRIBUTION CHANGES + o Distribute libevent.pc.in, not libevent.pc (22aff04) + o Avoid errors in evutil.c when building with _UNICODE defined (b677032 Brodie Thiesfield) + o Avoid errors in http.c when building with VC 2003 .NET (13e4f3b Brodie Thiesfield) + o Support the standard 'make check' target in place of 'make verify' (426c8fb) + o Remove redundant stuff from EXTRA_DIST (b660edf) + o Switch to using AM conditionals in place of AC_LIBOBJ (2e898f5) + o Remove an orphaned RELEASE flag in Makefile.am (0794b0d) + o Give a better warning for bad automake versions. (77c917d) + o Use dist_bin_SCRIPTS, not EXTRA_DIST, to distribute scripts (9eb2fd7) + o Never test for select() on windows (3eb044d Trond Norbye) + o Do not inhibit automake dependencies generation (10c4c90 Giuseppe Scrivano) + o Create shared libraries under Windows (3cbca86 Giuseppe Scrivano) + o Add ctags/etags files to .gitignore (0861d17) + o Only specify -no-undefined on mingw (25433b9) + o Only add libevent_core.la to LIBADD on mingw (fdc6297) + +TESTING + o Get bench_http to work on Windows; add a switch to enable IOCP. (4ac38a5 Christopher Davis) + o VC has no getopt(), so do without in bench_http. (1273d2f Christopher Davis) + o Fix an obnoxious typo in the bufferevent_timeout_filter test (0d047c3) + o Fix a write of uninitialized RAM in regression tests (68dc742) + o Fix some memory leaks in the unit tests (274a7bd) + o Make 'main/many_events' test 70 fds, not 64. (33874b0) + o Unit-test every evbuffer_add_file() implementation. (06a4443) + o Add more unit tests for evbuffer_expand (8c83e99) + o Test another case of evbuffer_prepend (1234b95) + o Fix a possible double-free bug in SSL bufferevents with CLOSE_ON_FREE (7501895) o Add dns/search_cancel unit test. (39b870b Christopher Davis) + o Make http_base_test stop leaking an event_base. (96730d3) + o Detect broken unsetenv at unit-test runtime (f37cd4c) + o Implement regress_make_tempfile on win32 to test evbuffer_add_file (b4f12a1) + o add more (currently skipped) add_file tests on win32 (05de45d) + o Fix bench_http build on win32. (384d124) + o Make unit test for add_file able to tell "error" from "done" (88a543f) + o Make test for bufferevent_connect_hostname system-neutral (f89168e) + o Make test.sh support mingw/msys on win32 (0ee6f6c) + o Fix test.sh on freebsd (3d9e05b) + +INTERNALS, PERFORMANCE, AND AND CODE CLEANUPS + o Improve the speed of evbuffer_readln() (cc1600a) + o more whitespace normalization (2c2618d) + o Revise evbuffer to add last_with_data (2a6d2a1) + o Use last_with_data in place of previous_to_last (c8ac57f) + o Remove previous_to_last from evbuffer (6f47bd1) + o Fix last_with_data compilation on windows (1e7b986) + o Add some glass-box tests for the last_with_data code. (17da042) + o Improve robustness for refcounting (f1bc125) + o Remove a needless min_heap_shift_up_() call (7204b91) + o Increase MIN_BUFFER_SIZE to 512 (1024 on 64-bit) (2014ae4) + o Do not use evbuffer_expand() to add the first chain to a buffer (5c0ebb3) + o Make evbuffer_prepend handle empty buffers better (c87272b) + o Replace last_with_data with a slightly smarter version (b7442f8) + o Turn the increasingly complex *_CHAIN() macros into functions (96865c4) + o Rewrite evbuffer_expand and its users (d5ebcf3) + o Add evutil_tv_to_msec for safe conversion of timevals to milliseconds. (850c3ff Christopher Davis) + o Initialize last_with_datap correctly in evbuffer_overlapped (a0983b6) + o Replace EVUTIL_CLOSESOCKET macro with a function (899c1dc Sebastian Sjöberg) + o Move domain search state to evdns_request. (beaa14a Christopher Davis) + o Remove redundant checks for lock!=NULL before calling EVLOCK_LOCK (50ec59f) + o Rename current_base symbol to event_global_current_base_ (c16e684) + o Fix whitespace in evutil.c (935e150) + o Replace users of "int fd" with "evutil_socket_t fd" in portable code (c7cf6f0) + + + +Changes in 2.0.4-alpha (28 Feb 2010): + [Autogenerated from the Git log, sorted by hand.] +DOCUMENTATION + o Add stub header for 2.0.4-alpha changelog. (94d0065) + o Improve the README with more information and links. (0b42726) + o Add more people who wrote patches to the acknowledgments (0af10d5) + o Add a warning about the use of event_initialized. (f32b575) + o Add a LICENSE file so people can find our license easily (7067006) + o Add a new "hello world" sample program (becb9f9) + o Clarify status of example programs (d60a1bd) + o Update time-test.c to use event2 (f4190bf) + o Add the arc4random.c license to the LICENSE file. (e15e1e9) + +NEW FEATURES AND INTERFACE CHANGES + o Improved optional lock debugging. (0cd3bb9) + o Rate-limiting for bufferevents; group and individual limits are supported. (737c9cd) + o Testing code for bufferevent rate-limiting. (f0c0124) + o Make the initial nameserver probe timeout configurable. (1e56a32) + o Revise the locking API: deprecate the old locking callbacks and add trylock. (347952f) + o Do not make bufferevent_setfd implicitly disable EV_READ and EV_WRITE. (8274379) + o Do not ignore bufferevent_enable(EV_READ) before bufferevent_connect(). (4a5b534) + o Introduced evutil_make_socket_closeonexec() to preserve fd flags for F_SETFD. (d0939d2 Jardel Weyrich) + o evdns_getaddrinfo() now supports the /etc/hosts file. (72dd666) + o Look at the proper /etc/hosts file on windows. (66c02c7) + o Allow http connections to use evdns for hostname looksups. (c698b77) + o Changelist code to defer event changes until just before dispatch (27308aa) + o do not use a function to assign the evdns base; instead assign it via evhttp_connection_base_new() which is a new function introduced in 2.0 (5032e52) + o Functions to access more fields of struct event. (0683950) + o Make kqueue use changelists. (45e5ae3) + o Remove kqueue->pend_changes. (3225dfb) + o Minimize epoll_ctl calls by using changelist (c8c6a89) + o Add support for a "debug mode" to try to catch common errors. (cd17c3a) + o Note a missing ratelim function (361da8f) + o Add ev_[u]intptr_t to include/event2/util.h (1fa4c81) + o const-ify a few more functions in event.h (d38a7a1) + o Deprecate EVENT_FD and EVENT_SIGNAL. (f6b2694) + o Remove EVUTIL_CHECK_FMT. (6c21c89) + o Add EV_*_MAX macros to event2/util.h to expose limits for ev_* types. (aba1fff) o Functions to view and manipulate rate-limiting buckets. (85047a6) + o Add the rest of the integer limits, and add a test for them. (60742d5) + o Remove the 'flags' argument from evdns_base_set_option() (1dd7e6d) + o Add an arc4random implementation for use by evdns (d4de062) + o Use off_t for the length parameter of evbuffer_add_file (3fe60fd) + o Construct Windows locks using InitializeCriticalSectionAndSpinCount (32c6f1b) + o Expose view of current rate limit as constrained by group limit (162ce8a) + o Provide consistent, tested semantics for bufferevent timeouts (d328829) + +BUGFIXES AND TESTS + o Tolerate code that returns from a fatal_cb. (91fe23f) + o Parenthesize macro arguments more aggressively (07e9e9b) + o Fix memory-leak of signal handler array with kqueue. (e1ffbb8) + o Stop passing EVTHREAD_READ and EVTHREAD_WRITE to non-rw locks. (76cd2b7) + o Fix two use-after-free bugs in unit tests spoted by lock debugging (d84d838) + o Fix a locking bug in event_base_loop() (da1718b) + o Fix an evdns lock violation. (2df1f82 Zhuang Yuyao) + o Valgrind fix: Clear struct kevent before checking for OSX bug. (56771a3 William Ahern) + o Fix up evthread compilation on windows (bd6f1ba Roman Puls) + o Fix regress_iocp.c usage of old lock allocation macros. (31687b4 unknown) + o Update nmake makefile to build evthread.c (b62d979 unknown) + o Fix a crash when reading badly formatted resolve.conf; from Yasuoka Masahiko (6c7c579 Yasuoka Masahiko) + o Fix a snow leopard compile warning in the unit tests. (7ae9445) + o Fix compile on Snow Leopard with gcc warnings enabled (70cdfe4 Sebastian Hahn) + o Only define _GNU_SOURCE if it is not already defined. (ea6b1df Joachim Bauch) + o Update sample/signal-test.c to use newer APIs and not leak. (f6430ac Evan Jones) + o Fix a segfault when writing a very fragmented evbuffer onto an SSL (a6adeca Joachim Bauch) + o Fix a segfault when freeing SSL bufferevents in an unusual order (a773df5 Joachim Bauch) + o Drop install-sh from our git repo: a mismatched version could break "make dist" (6799527) + o Set all instances of the version number correctly. (5a112d3) + o Fix a few locking issues on windows. (c51bb3c unknown) + o Use evutil_socket_t, not int, when logging socket errors. (292467c) + o Fix up behavior of never-defered callbacks a little (390e056) + o Replace some cases of uint32_t with ev_uint32_t. (a47d88d) + o Fix compilation of devpoll.c by adding missing thread includes. (fee2c77 Dagobert Michelsen) + o Make evutil_make_socket_nonblocking() leave any other flags alone. (4c8b7cd Jardel Weyrich) + o Fix an fd leak in evconnlistener_new_bind(). (24fb502 Jardel Weyrich) + o Fix a bogus free in evutil_new_addrinfo() (0d64051 Jardel Weyrich) + o Adjusted fcntl() retval comparison on evutil_make_socket_nonblocking(). (4df7dbc Jardel Weyrich) + o Fix the code that allowed DNS options to not end with : (ee4953f) + o Fix crash bugs when a bufferevent's eventcb is not set. (2e8eeea) + o Fix test-ratelim compilation on Linux. (885b427) + o Fix compilation of rate-limiting code on win32. (165d30e) + o Eradicated the last free() call. Let mm_free() take care of deallocation. (0546ce1 Jardel Weyrich) + o Fix byte counts when mixing deferred and non-deferred evbuffer callbacks. (29151e6) + o Fixed a memory leak on windows threads implementation. The CRITICAL_SECTION was not being free'd in evthread_win32_lock_free(). (2f33e00 Jardel Weyrich) + o Fixed a fd leak in start_accepting(), plus cosmetic changes (4367a33 Jardel Weyrich) + o Improved error handling in evconnlistener_new_async(). Also keeping the fd open because it is not opened by this function, so the caller is responsible for closing it. Additionally, since evconnlistener_new_bind() creates a socket and passes it to the function above, it required error checking to close the same socket. (fec66f9 Jardel Weyrich) + o Don't use a bind address for nameservers on loopback (8d4aaf9) + o Fix compilation of rate-limit code when threading support is disabled (97a8c79) + o Detect setenv/unsetenv; skip main/base_environ test if we can't fake them. (7296971) + o Check more internal event_add() calls for failure (ff3f6cd) + o Fix windows and msvc build (5c7a7bc) + o Call event_debug_unassign on internal events (a19b4a0) + o Try to fix a warning in hash_debug_entry (137f2c6) + o Fix a dumb typo in ev_intptr_t definitions. (27c9a40) + o do not fail while sending on http connections the client closed. (93d7369) + o make evhttp_send() safe against terminated connections, too (3978180) + o Make Libevent 1.4.12 build on win32 with Unicode enabled. (000a33e Brodie Thiesfield) + o Fix some additional -DUNICODE issues on win32. (a7a9431) + o Add a check to make soure our EVUTIL_AI flags do not conflict with the native ones (c18490e) + o Always use our own gai_strerror() replacement. (6810bdb) + o Make RNG work when we have arc4random() but not arc4random_buf() (4ec8fea) + o validate close cb on server when client connection closes (2f782af) + o Fix two unlocked reads in evbuffer. (7116bf2) + o When working without a current event base, don't try to use IOCP listeners (cb52838) + o Fix getpid() usage on Windows (ff2a134) + o Add a unit test for secure rng. (48a29b6) + o Add some headers to fix freebsd compilation (b72be50) + o When connect() succeeds immediately, don't invoke the callback immediately. (7515de9) + o Suspend read/write on bufferevents during hostname lookup (db08f64) + o Make bufferevent_free() clear all callbacks immediately. (b2fbeb3) + o Fix some race conditions in persistent events and event_reinit (e2642f0) + o Fix a bug in resetting timeouts on persistent events when IO triggers. (38ec0a7) + o Add a test for timeouts on filtering bufferevents. (c02bfe1) + o Add test for periodic timers that get activated for other reasons (8fcb7a1) + o Use new timeval diff comparison function in bufferevent test (f3dfe46) + o Delete stack-alloced event in new unit test before returning. (7ffd387) + o Fix mingw compilation (23170a6) + o Try to define a sane _EVENT_SIZEOF_SIZE_T for msvc compilation (1e14f82) + o Fix arc4random compilation on MSVC. (98edb89) + o deal with connect() failing immediately (7bc48bf) + o Small cleanups on freebsd-connect-refused patch. (57b7248) + +BUILD AND DISTRIBUTION CHANGES + o Remove the contents of WIN32-Prj as unmaintained. (c69d5a5) + o Allow the user to redirect the verbose output of test/test.sh to a file (c382de6) + o Allow test.sh to be run as ./test/test.sh (7dfbe94) + o Never believe that we have pthreads on win32, even if gcc thinks we do. (78ed097) + o Make it compile under gcc --std=c89. (e2ca403) + o Fix a number of warnings from gcc -pedantic (918e9c5) + o Add the msvc-generated .lib files to .gitignore. (e244a2e) + o Add the "compile" script to gitignore. (1ba6bed) + +INTERNALS AND CODE CLEANUPS + o Add a .gitignore file. (ba34071) + o New EVTHREAD_TRY_LOCK function to try to grab a lock. (689fc09) + o Add the abilitity to mark some buffer callbacks as never-deferred. (438f9ed) + o Refactor our 'suspend operation' logic on bufferevents. (0d744aa) + o Simplify the read high-watermark checking. (5846bf6) + o Improve readability of evutil_unparse_protoname() (5a43df8 Jardel Weyrich) + o Expose our cached gettimeofday value with a new interface (47854a8) + o Whitespace fixes in test.sh (0b151a9) + o Enable branch-prediction hints with EVUTIL_UNLIKELY. (eaaf27f) + o Refactor code from evdns into a new internal "read a file" function. (0f7144f) + o Comestic changes in evconnlistener_new(), new_accepting_socket(), accepted_socket_invoke_user_cb() and iocp_listener_enable(). (510ab6b Jardel Weyrich) + o Add unit-test for bad_request bug fixed in 1.4 recently. (6cc79c6 Pavel Plesov) o Add a comment on evthread_enable_lock_debuging. (b9f43b2) + o Fix test.sh on shells without echo -n (94131e9) + o More unit tests for getaddrinfo_async: v4timeout and cancel. (a334b31) + o Make http use evconnlistener. (ec34533) + o move dns utility functions into a separate file so that we can use them for http testing (b822639) + o add a test for evhttp_connection_base_new with a dns_base (26714ca) + o forgot to add void to test function (78a50fe) + o Add a forgotten header (changelist-internal.h) (4b9f307) + o Remove some commented-out code in evutil (26e1b6f) + o Remove a needless include of rpc_compat.h (70a4a3e) + o Use less memory for each entry in a hashtable (a66e947) + o Try to untangle the logic in server_port_flush(). (439aea0) + o Use ev_[u]intptr_t types in place of [u]intptr_t (cef61a2) + o Reduce windows header includes in our own headers. (da6135e) + o clean up terminate_chunked test (e8a9782) + o Increment the submicro version number. (63e868e) + o Update event-config.h version number to match configure.in (aae7db5) + o Clean up formatting: Disallow space-before-tab. (8fdf09c) + o Clean up formatting: use tabs, not 8-spaces, to indent. (e5bbd40) + o Clean up formatting: remove trailing spaces (e5cf987) + o Clean up formatting: function/keyword spacing consistency. (4faeaea) + + + +Changes in 2.0.3-alpha (20 Nov 2009): + o Add a new code to support SSL/TLS on bufferevents, using the OpenSSL library (where available). + o Fix a bug where we didn't allocate enough memory in event_get_supported_methods(). + o Avoid segfault during failed allocation of locked evdns_base. (Found by Rocco Carbone.) + o Export new evutil_ascii_* functions to perform locale-independent character type operations. + o Try to compile better with MSVC: patches from Brodie Thiesfield + o New evconnlistener_get_fd function to expose a listener's associated socket. + o Expose an ev_socklen_t type for consistent use across platforms. + o Make bufferevent_socket_connect() work when the original fd was -1. + o Fix a bug in bufferevent_socket_connect() when the connection succeeds too quickly. + o Export an evutil_sockaddr_cmp() to compare to sockaddr objects for equality. + o Add a bufferevent_get_enabled() to tell what a bufferevent has been configured to do. + o Add an evbuffer_search_eol() function to locate the end of a line nondestructively. + o Add an evbuffer_search_range() function to search a bounded range of a buffer. + o Fix a rare crash bug in evdns. + o Have bufferevent_socket_connect() with no arguments put a bufferevent into connecting mode. + o Support sendfile on Solaris: patch from Caitlin Mercer. + o New functions to explicitly reference a socket used by an evhttp object. Patches from David Reiss. + o When we send a BEV_EVENT_CONNECTED to indicate connected status, we no longer invoke the write callback as well unless we actually wrote data too. + o If the kernel tells us that there are a negative number of bytes to read from a socket, do not believe it. Fixes bug 2841177; found by Alexander Pronchenkov. + o Do not detect whether we have monotonic clock support every time a new event base is created: instead do it only once. Patch taken from Chromium. + o Do not allocate the maximum event queue for the epoll backend at startup. Instead, start out accepting 32 events at a time, and double the queue's size when it seems that the OS is generating events faster than we're requesting them. Saves up to 374K per epoll-based event_base. Resolves bug 2839240. + o Treat an event with a negative fd as valid but untriggerable by Libevent. This is useful for applications that want to manually activate events. + o Fix compilation on Android, which forgot to define fd_mask in its sys/select.h + o Do not drop data from evbuffer when out of memory; reported by Jacek Masiulaniec + o New event_base_got_exit() and event_base_got_break() functions to tell whether an event loop exited because of an event_base_loopexit() or an event_base_loopbreak(). Patch from Ka-Hing Cheung. + o When adding or deleting an event from a non-main thread, only wake up the main thread when its behavior actually needs to change. + o Fix some bugs when using the old evdns interfaces to initialize the evdns module. + o Detect errors during bufferevent_connect(). Patch from Christopher Davis. + o Fix compilation for listener.h for C++ - missing extern "C". Patch from Ferenc Szalai. + o Make the event_base_loop() family of functions respect thread-safety better. This should clear up a few hard-to-debug race conditions. + o Fix a bug when using a specialized memory allocator on win32. + o Have the win32 select() backend label TCP-socket-connected events as EV_WRITE, not EV_READ. This should bring it in line with the other backends, and improve portability. Patch from Christopher Davis. + o Stop using enums as arguments or return values when what we mean is a bitfield of enum values. C++ doesn't believe that you can OR two enum values together and get another enum, and C++ takes its typing seriously. Patch from Christopher Davis. + o Add an API to replace all fatal calls to exit() with a user-provided panic function. + o Replace all assert() calls with a variant that is aware of the user-provided logging and panic functions. + o Add a return value to event_assign so that it can fail rather than asserting when the user gives it bad input. event_set still dies on bad input. + o The event_base_new() and event_base_new_with_config() functions now never call exit() on failure. For backward "compatibility", event_init() still does, but more consistently. + o Remove compat/sys/_time.h. It interfered with system headers on HPUX, and its functionality has been subsumed by event2/util.h and util-internal.h. + o Add a new bufferevent_socket_connect_hostname() to encapsulate the resolve-then-connect operation. + o Build kqueue.c correctly on GNU/kFreeBSD platforms. Patch pulled upstream from Debian. + o Alternative queue-based timeout algorithm for programs that use a large number of timeouts with the same value. + o New event_base_config option to disable the timeval cache entirely. + o Make EV_PERSIST timeouts more accurate: schedule the next event based on the scheduled time of the previous event, not based on the current time. + o Allow http.c to handle cases where getaddrinfo returns an IPv6 address. Patch from Ryan Phillips. + o Fix a problem with excessive memory allocation when using multiple event priorities. + o Default to using arc4random for DNS transaction IDs on systems that have it; from OpenBSD. + o Never check the environment when we're running setuid or setgid; from OpenBSD. + o Options passed to evdns_set_option() no longer need to end with a colon. + o Add an evutil_getaddrinfo() function to clone getaddrinfo on platforms that don't have it. + o Add an evdns_getaddrinfo() function to provide a nonblocking getaddrinfo using evdns, so programs can perform useful hostname lookup. + o Finally expose the IOCP-based bufferevent backend. It passes its unit tests, but probably still has some bugs remaining. Code by Nick Mathewson and Christopher Davis. + o Numerous other bugfixes. + o On FreeBSD and other OSes, connect can return ECONREFUSED immediately; instead of failing the function call, pretend with faileld in the callback. + o Fix a race condition in the pthreads test case; found by Nick Mathewson + o Remove most calls to event_err() in http and deal with memory errors instead + + + +Changes in 2.0.2-alpha (25 Jul 2009): + o Add a new flag to bufferevents to make all callbacks automatically deferred. + o Make evdns functionality locked, and automatically defer dns callbacks. + o Fix a possible free(NULL) when freeing an event_base with no signals. + o Add a flag to disable checking environment varibles when making an event_base + o Disallow setting less than 1 priority. + o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen] + o Use signal.h, not sys/signal.h. [Patch from mmadia] + o Try harder to build with certain older c99 compilers. + o Make sure that an event_config's flags field is always initialized to 0. [Bug report from Victor Goya] + o Avoid data corruption when reading data entirely into the second-to-last chain of an evbuffer. [Bug report from Victor Goya] + o Make sendfile work on FreeBSD + o Do not use vararg macros for accessing evrpc structures; this is not backwards compatible, but we did not promise any backwards compatibility for the rpc code. + o Actually define the event_config_set_flag() function. + o Try harder to compile with Visual C++. + o Move event_set() and its allies to event2/event_compat.h where they belong. + o Remove the event_gotsig code, which has long been deprecated and unused. + o Add an event_get_base() function to return the base assigned to an event. + o New function to automate connecting on a socket-based bufferevent. + o New functions to automate listening for incoming TCP connections. + o Do case-insensitive checks with a locale-independent comparison function. + o Rename the evbuffercb and everrorcb callbacks to bufferevent_data_cb and bufferevent_event_cb respectively. The old names are available in bufferevent_compat.h. + o Rename the EVBUFFER_* codes used by bufferevent event callbacks to BEV_EVENT_*, to avoid namespace collision with evbuffer flags. The old names are available in bufferevent_compat.h. + o Move the EVBUFFER_INPUT and EVBUFFER_OUTPUT macros to bufferevent_compat.h + o Add a bufferevent_getfd() function to mirror bufferevent_setfd() + o Make bufferevent_setfd() return an error code if the operation is not successful. + o Shave 22 bytes off struct event on 32-bit platforms by shrinking and re-ordering fields. The savings on 64-bit platforms is likely higher. + o Cap the maximum number of priorities at 256. + o Change the semantics of evbuffer_cb_set_flags() to be set-flag only; add a new evbuffer_cb_clear_flags() to remove set flags. + o Change the interface of evbuffer_add_reference so that the cleanup callback gets more information + o Revise the new evbuffer_reserve_space/evbuffer_commit_space() interfaces so that you can use them without causing extraneous copies or leaving gaps in the evbuffer. + o Add a new evbuffer_peek() interface to inspect data in an evbuffer without removing it. + o Fix a deadlock when suspending reads in a bufferevent due to a full buffer. (Spotted by Joachim Bauch.) + o Fix a memory error when freeing a thread-enabled event base with registered events. (Spotted by Joachim Bauch.) + o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair. + o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32). + o Replace some read()/write() instances with send()/recv() to work properly on win32. + o Set truncated flag correctly in evdns server replies. + o Raise RpcGenError in event_rpcgen.py; from jmanison and Zack Weinberg + o Fix preamble of rpcgen-generated files to rely on event2 includes; based on work by jmansion; patch from Zack Weinberg. + o Allow specifying the output filename for rpcgen; based on work by jmansion; patch from Zack Weinberg. + o Allow C identifiers as struct names; allow multiple comments in .rpc files; from Zack Weinberg + o Mitigate a race condition when using socket bufferevents in multiple threads. + o Use AC_SEARCH_LIBS, not AC_CHECK_LIB to avoid needless library use. + o Do not allow event_del(ev) to return while that event's callback is executing in another thread. This fixes a nasty race condition. + o event_get_supported_methods() now lists methods that have been disabled with the EVENT_NO* environment options. + o Rename encode_int[64] to evtag_encode_int[64] to avoid polluting the global namespace. The old method names are still available as macros in event2/tag_compat.h. + + + +Changes in 2.0.1-alpha (17 Apr 2009): + o free minheap on event_base_free(); from Christopher Layne + o debug cleanups in signal.c; from Christopher Layne + o provide event_base_new() that does not set the current_base global + o bufferevent_write now uses a const source argument; report from Charles Kerr + o improve documentation on event_base_loopexit; patch from Scott Lamb + o New function, event_{base_}loopbreak. Like event_loopexit, it makes an event loop stop executing and return. Unlike event_loopexit, it keeps subsequent pending events from getting executed. Patch from Scott Lamb + o Check return value of event_add in signal.c + o provide event_reinit() to reintialize an event_base after fork + o New function event_set_mem_functinons. It allows the user to give libevent replacement functions to use for memory management in place of malloc(), free(), etc. This should be generally useful for memory instrumentation, specialized allocators, and so on. + o The kqueue implementation now catches signals that are raised after event_add() is called but before the event_loop() call. This makes it match the other implementations. + o The kqueue implementation now restores original signal handlers correctly when its signal events are removed. + o Check return value of event_add in signal.c + o Add a more powerful evbuffer_readln as a replacement for evbuffer_readline. The new function handles more newline styles, and is more useful with buffers that may contain a nul characters. + o Do not mangle socket handles on 64-bit windows. + o The configure script now takes an --enable-gcc-warnigns option that turns on many optional gcc warnings. (Nick has been building with these for a while, but they might be useful to other developers.) + o move EV_PERSIST handling out of the event backends + o small improvements to evhttp documentation + o always generate Date and Content-Length headers for HTTP/1.1 replies + o set the correct event base for HTTP close events + o When building with GCC, use the "format" attribute to verify type correctness of calls to printf-like functions. + o Rewrite win32.c backend to be O(n lg n) rather than O(n^2). + o Removed obsoleted recalc code + o support for 32-bit tag numbers in rpc structures; this is wire compatible, but changes the API slightly. + o pull setters/getters out of RPC structures into a base class to which we just need to store a pointer; this reduces the memory footprint of these structures. + o prefix {encode,decode}_tag functions with evtag to avoid collisions + o fix a bug with event_rpcgen for integers + o Correctly handle DNS replies with no answers set (Fixes bug 1846282) + o add -Wstrict-aliasing to warnings and more cleanup + o removed linger from http server socket; reported by Ilya Martynov + o event_rpcgen now allows creating integer arrays + o support string arrays in event_rpcgen + o change evrpc hooking to allow pausing of RPCs; this will make it possible for the hook to do some meaning ful work; this is not backwards compatible. + o allow an http request callback to take ownership of a request structure + o allow association of meta data with RPC requests for hook processing + o associate more context for hooks to query such as the connection object + o remove pending timeouts on event_base_free() + o also check EAGAIN for Solaris' event ports; from W.C.A. Wijngaards + o devpoll and evport need reinit; tested by W.C.A Wijngaards + o event_base_get_method; from Springande Ulv + o Send CRLF after each chunk in HTTP output, for compliance with RFC2626. Patch from "propanbutan". Fixes bug 1894184. + o Add a int64_t parsing function, with unit tests, so we can apply Scott Lamb's fix to allow large HTTP values. + o Use a 64-bit field to hold HTTP content-lengths. Patch from Scott Lamb. + o Allow regression code to build even without Python installed + o remove NDEBUG ifdefs from evdns.c + o detect integer types properly on platforms without stdint.h + o udpate documentation of event_loop and event_base_loop; from Tani Hosokawa. + o simplify evbuffer by removing orig_buffer + o do not insert event into list when evsel->add fails + o add support for PUT/DELETE requests; from Josh Rotenberg + o introduce evhttp_accept_socket() to accept from an already created socket + o include Content-Length in reply for HTTP/1.0 requests with keep-alive + o increase listen queue for http sockets to 128; if that is not enough the evhttp_accpet_socket() api can be used with a prepared socket. + o Patch from Tani Hosokawa: make some functions in http.c threadsafe. + o test support for PUT/DELETE requests; from Josh Rotenberg + o rewrite of the evbuffer code to reduce memory copies + o Some older Solaris versions demand that _REENTRANT be defined to get strtok_r(); do so. + o Do not free the kqop file descriptor in other processes, also allow it to be 0; from Andrei Nigmatulin + o Provide OpenSSL style support for multiple threads accessing the same event_base + o make event_rpcgen.py generate code include event-config.h; reported by Sam Banks. + o switch thread support so that locks get allocated as they are needed. + o make event methods static so that they are not exported; from Andrei Nigmatulin + o make RPC replies use application/octet-stream as mime type + o do not delete uninitialized timeout event in evdns + o Correct the documentation on buffer printf functions. + o Don't warn on unimplemented epoll_create(): this isn't a problem, just a reason to fall back to poll or select. + o Correctly handle timeouts larger than 35 minutes on Linux with epoll.c. This is probably a kernel defect, but we'll have to support old kernels anyway even if it gets fixed. + o Make name_from_addr() threadsafe in http.c + o Add new thread-safe interfaces to evdns functions. + o Make all event_tagging interfaces threadsafe. + o Rename internal memory management functions. + o New functions (event_assign, event_new, event_free) for use by apps that want to be safely threadsafe, or want to remain ignorant of the contents of struct event. + o introduce bufferevent_read_buffer; allows reading without memory copy. + o expose bufferevent_setwatermark via header files and fix high watermark on read + o fix a bug in buffrevent read water marks and add a test for them + o fix a bug in which bufferevent_write_buffer would not schedule a write event + o provide bufferevent_input and bufferevent_output without requiring knowledge of the structure + o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents + o convert evhttp_connection to use bufferevents. + o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy. + o Remove the never-exported, never-used evhttp_hostportfile function. + o Support input/output filters for bufferevents; somewhat similar to libio's model. This will allow us to implement SSL, compression, etc, transparently to users of bufferevents such as the http layer. + o allow connections to be removed from an rpc pool + o add new evtimer_assign, signal_assign, evtimer_new, and signal_new functions to manipulate timer and signal events, analagous to the now-recommended event_assign and event_new + o switch internal uses of event_set over to use event_assign. + o introduce evbuffer_contiguous_space() api that tells a user how much data is available in the first buffer chain + o introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing in filters more efficient. + o reduce system calls for getting current time by caching it. + o separate signal events from io events; making the code less complex. + o support for periodic timeouts + o support for virtual HTTP hosts. + o turn event_initialized() into a function, and add function equivalents to EVENT_SIGNAL and EVENT_FD so that people don't need to include event_struct.h + o Build test directory correctly with CPPFLAGS set. + o Provide an API for retrieving the supported event mechanisms. + o event_base_new_with_config() and corresponding config APIs. + o migrate the evhttp header to event2/ but accessors are still missing. + o deprecate timeout_* event functions by moving them to event_compat.h + o Move windows gettimeofday replacement into a new evutil_gettimeofday(). + o Make configure script work on IRIX. + o provide a method for canceling ongoing http requests. + o Make vsnprintf() returns consistent on win32. + o Fix connection keep-alive behavior for HTTP/1.0 + o Fix use of freed memory in event_reinit; pointed out by Peter Postma + o constify struct timeval * where possible + o make event_get_supported_methods obey environment variables + o support for edge-triggered events on epoll and kqueue backends: patch from Valery Kholodkov + o support for selecting event backends by their features, and for querying the features of a backend. + o change failing behavior of event_base_new_with_config: if a config is provided and no backend is selected, return NULL instead of aborting. + o deliver partial data to request callbacks when chunked callback is set even if there is no chunking on the http level; allows cancelation of requests from within the chunked callback; from Scott Lamb. + o allow min_heap_erase to be called on removed members; from liusifan. + o Rename INPUT and OUTPUT to EVRPC_INPUT and EVRPC_OUTPUT. Retain INPUT/OUTPUT aliases on on-win32 platforms for backwards compatibility. + o Do not use SO_REUSEADDR when connecting + o Support 64-bit integers in RPC structs + o Correct handling of trailing headers in chunked replies; from Scott Lamb. + o Support multi-line HTTP headers; based on a patch from Moshe Litvin + o Reject negative Content-Length headers; anonymous bug report + o Detect CLOCK_MONOTONIC at runtime for evdns; anonymous bug report + o Various HTTP correctness fixes from Scott Lamb + o Fix a bug where deleting signals with the kqueue backend would cause subsequent adds to fail + o Support multiple events listening on the same signal; make signals regular events that go on the same event queue; problem report by Alexander Drozdov. + o Fix a problem with epoll() and reinit; problem report by Alexander Drozdov. + o Fix off-by-one errors in devpoll; from Ian Bell + o Make event_add not change any state if it fails; reported by Ian Bell. + o Fix a bug where headers arriving in multiple packets were not parsed; fix from Jiang Hong; test by me. + o Match the query in DNS replies to the query in the request; from Vsevolod Stakhov. + o Add new utility functions to correctly observe and log winsock errors. + o Do not remove Accept-Encoding header + o Clear the timer cache on entering the event loop; reported by Victor Chang + o Only bind the socket on connect when a local address has been provided; reported by Alejo Sanchez + o Allow setting of local port for evhttp connections to support millions of connections from a single system; from Richard Jones. + o Clear the timer cache when leaving the event loop; reported by Robin Haberkorn + o Fix a typo in setting the global event base; reported by lance. + o Set the 0x20 bit on outgoing alphabetic characters in DNS requests randomly, and insist on a match in replies. This helps resist DNS poisoning attacks. + o Make the http connection close detection work properly with bufferevents and fix a potential memory leak associated with it. + o Restructure the event backends so that they do not need to keep track of events themselves, as a side effect multiple events can use the same fd or signal. + o Add generic implementations for parsing and emiting IPv6 addresses on platforms that do not have inet_ntop and/or inet_pton. + o Allow DNS servers that have IPv6 addresses. + o Add an evbuffer_write_atmost() function to write a limited number of bytes to an fd. + o Refactor internal notify-main-thread logic to prefer eventfd to pipe, then pipe to socketpair, and only use socketpairs as a last resort. + o Try harder to pack all evbuffer reads into as few chains as possible, using readv/WSARecv as appropriate. + o New evthread_use_windows_threads() and evthread_use_pthreads() functions to set up the evthread callbacks with reasonable defaults. + o Change the semantics of timeouts in conjunction with EV_PERSIST; timeouts in that case will now repeat until deleted. + o sendfile, mmap and memory reference support for evbuffers. + o New evutil_make_listen_socket_reuseable() to abstract SO_REUSEADDR. + o New bind-to option to allow DNS clients to bind to an arbitrary port for outgoing requests. + o evbuffers can now be "frozen" to prevent operations at one or both ends. + o Bufferevents now notice external attempts to add data to an inbuf or remove it from an outbuf, and stop them. + o Fix parsing of queries where the encoded queries contained \r, \n or + + o Do not allow internal events to starve lower-priority events. + +Changes in 1.4.0: + o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. + o demote most http warnings to debug messages + o Fix Solaris compilation; from Magne Mahre + o Add a "Date" header to HTTP responses, as required by HTTP 1.1. + o Support specifying the local address of an evhttp_connection using set_local_address + o Fix a memory leak in which failed HTTP connections whould not free the request object + o Make adding of array members in event_rpcgen more efficient, but doubling memory allocation + o Fix a memory leak in the DNS server + o Fix compilation when DNS_USE_OPENSSL_FOR_ID is enabled + o Fix buffer size and string generation in evdns_resolve_reverse_ipv6(). + o Respond to nonstandard DNS queries with "NOTIMPL" rather than by ignoring them. + o In DNS responses, the CD flag should be preserved, not the TC flag. + o Fix http.c to compile properly with USE_DEBUG; from Christopher Layne + o Handle NULL timeouts correctly on Solaris; from Trond Norbye + o Recalculate pending events properly when reallocating event array on Solaris; from Trond Norbye + o Add Doxygen documentation to header files; from Mark Heily + o Add a evdns_set_transaction_id_fn() function to override the default + transaction ID generation code. + o Add an evutil module (with header evutil.h) to implement our standard cross-platform hacks, on the theory that somebody else would like to use them too. + o Fix signals implementation on windows. + o Fix http module on windows to close sockets properly. + o Make autogen.sh script run correctly on systems where /bin/sh isn't bash. (Patch from Trond Norbye, rewritten by Hagne Mahre and then Hannah Schroeter.) + o Skip calling gettime() in timeout_process if we are not in fact waiting for any events. (Patch from Trond Norbye) + o Make test subdirectory compile under mingw. + o Fix win32 buffer.c behavior so that it is correct for sockets (which do not like ReadFile and WriteFile). + o Make the test.sh script run unit tests for the evpoll method. + o Make the entire evdns.h header enclosed in "extern C" as appropriate. + o Fix implementation of strsep on platforms that lack it + o Fix implementation of getaddrinfo on platforms that lack it; mainly, this will make Windows http.c work better. Original patch by Lubomir Marinov. + o Fix evport implementation: port_disassociate called on unassociated events resulting in bogus errors; more efficient memory management; from Trond Norbye and Prakash Sangappa + o support for hooks on rpc input and output; can be used to implement rpc independent processing such as compression or authentication. + o use a min heap instead of a red-black tree for timeouts; as a result finding the min is a O(1) operation now; from Maxim Yegorushkin + o associate an event base with an rpc pool + o added two additional libraries: libevent_core and libevent_extra in addition to the regular libevent. libevent_core contains only the event core whereas libevent_extra contains dns, http and rpc support + o Begin using libtool's library versioning support correctly. If we don't mess up, this will more or less guarantee binaries linked against old versions of libevent continue working when we make changes to libevent that do not break backward compatibility. + o Fix evhttp.h compilation when TAILQ_ENTRY is not defined. + o Small code cleanups in epoll_dispatch(). + o Increase the maximum number of addresses read from a packet in evdns to 32. + o Remove support for the rtsig method: it hasn't compiled for a while, and nobody seems to miss it very much. Let us know if there's a good reason to put it back in. + o Rename the "class" field in evdns_server_request to dns_question_class, so that it won't break compilation under C++. Use a macro so that old code won't break. Mark the macro as deprecated. + o Fix DNS unit tests so that having a DNS server with broken IPv6 support is no longer cause for aborting the unit tests. + o Make event_base_free() succeed even if there are pending non-internal events on a base. This may still leak memory and fds, but at least it no longer crashes. + o Post-process the config.h file into a new, installed event-config.h file that we can install, and whose macros will be safe to include in header files. + o Remove the long-deprecated acconfig.h file. + o Do not require #include before #include . + o Add new evutil_timer* functions to wrap (or replace) the regular timeval manipulation functions. + o Fix many build issues when using the Microsoft C compiler. + o Remove a bash-ism in autogen.sh + o When calling event_del on a signal, restore the signal handler's previous value rather than setting it to SIG_DFL. Patch from Christopher Layne. + o Make the logic for active events work better with internal events; patch from Christopher Layne. + o We do not need to specially remove a timeout before calling event_del; patch from Christopher Layne. diff --git a/libevent/Doxyfile b/libevent/Doxyfile new file mode 100644 index 0000000..5d3865e --- /dev/null +++ b/libevent/Doxyfile @@ -0,0 +1,257 @@ +# Doxyfile 1.5.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libevent + +# Place all output under 'doxygen/' + +OUTPUT_DIRECTORY = doxygen/ + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = include/ + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = \ + include/event2/buffer.h \ + include/event2/buffer_compat.h \ + include/event2/bufferevent.h \ + include/event2/bufferevent_compat.h \ + include/event2/bufferevent_ssl.h \ + include/event2/dns.h \ + include/event2/dns_compat.h \ + include/event2/event.h \ + include/event2/event_compat.h \ + include/event2/http.h \ + include/event2/http_compat.h \ + include/event2/listener.h \ + include/event2/rpc.h \ + include/event2/rpc_compat.h \ + include/event2/tag.h \ + include/event2/tag_compat.h \ + include/event2/thread.h \ + include/event2/util.h + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = TAILQ_ENTRY RB_ENTRY _EVENT_DEFINED_TQENTRY _EVENT_IN_DOXYGEN + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES diff --git a/libevent/LICENSE b/libevent/LICENSE new file mode 100644 index 0000000..70d76b3 --- /dev/null +++ b/libevent/LICENSE @@ -0,0 +1,74 @@ +Libevent is available for use under the following license, commonly known +as the 3-clause (or "modified") BSD license: + +============================== +Copyright (c) 2000-2007 Niels Provos +Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + +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. +============================== + +Portions of Libevent are based on works by others, also made available by +them under the three-clause BSD license above. The copyright notices are +available in the corresponding source files; the license is as above. Here's +a list: + +log.c: + Copyright (c) 2000 Dug Song + Copyright (c) 1993 The Regents of the University of California. + +strlcpy.c: + Copyright (c) 1998 Todd C. Miller + +win32select.c: + Copyright (c) 2003 Michael A. Davis + +evport.c: + Copyright (c) 2007 Sun Microsystems + +ht-internal.h: + Copyright (c) 2002 Christopher Clark + +minheap-internal.h: + Copyright (c) 2006 Maxim Yegorushkin + +============================== + +The arc4module is available under the following, sometimes called the +"OpenBSD" license: + + Copyright (c) 1996, David Mazieres + Copyright (c) 2008, Damien Miller + + 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. + diff --git a/libevent/Makefile.am b/libevent/Makefile.am new file mode 100644 index 0000000..8114ad3 --- /dev/null +++ b/libevent/Makefile.am @@ -0,0 +1,249 @@ +# Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + +# 'foreign' means that we're not enforcing GNU package rules strictly. +# '1.7' means that we need automake 1.7 or later (and we do). +AUTOMAKE_OPTIONS = foreign 1.7 + +ACLOCAL_AMFLAGS = -I m4 + +# This is the "Release" of the Libevent ABI. It takes precedence over +# the VERSION_INFO, so that two versions of Libevent with the same +# "Release" are never binary-compatible. +# +# This number incremented once for the 2.0 release candidate, and +# will increment for each series until we revise our interfaces enough +# that we can seriously expect ABI compatibility between series. +# +RELEASE = -release 2.0 + +# This is the version info for the libevent binary API. It has three +# numbers: +# Current -- the number of the binary API that we're implementing +# Revision -- which iteration of the implementation of the binary +# API are we supplying? +# Age -- How many previous binary API versions do we also +# support? +# +# To increment a VERSION_INFO (current:revision:age): +# If the ABI didn't change: +# Return (current:revision+1:age) +# If the ABI changed, but it's backward-compatible: +# Return (current+1:0:age+1) +# If the ABI changed and it isn't backward-compatible: +# Return (current+1:0:0) +# +# Once an RC is out, DO NOT MAKE ANY ABI-BREAKING CHANGES IN THAT SERIES +# UNLESS YOU REALLY REALLY HAVE TO. +VERSION_INFO = 6:6:1 + +# History: RELEASE VERSION_INFO +# 2.0.1-alpha -- 2.0 1:0:0 +# 2.0.2-alpha -- 2:0:0 +# 2.0.3-alpha -- 2:0:0 (should have incremented; didn't.) +# 2.0.4-alpha -- 3:0:0 +# 2.0.5-beta -- 4:0:0 +# 2.0.6-rc -- 2.0 2:0:0 +# 2.0.7-rc -- 2.0 3:0:1 +# 2.0.8-rc -- 2.0 4:0:2 +# 2.0.9-rc -- 2.0 5:0:0 (ABI changed slightly) +# 2.0.10-stable-- 2.0 5:1:0 (No ABI change) +# 2.0.11-stable-- 2.0 6:0:1 (ABI changed, backward-compatible) +# 2.0.12-stable-- 2.0 6:1:1 (No ABI change) +# 2.0.13-stable-- 2.0 6:2:1 (No ABI change) +# 2.0.14-stable-- 2.0 6:3:1 (No ABI change) +# 2.0.15-stable-- 2.0 6:3:1 (Forgot to update :( ) +# 2.0.16-stable-- 2.0 6:4:1 (No ABI change) +# 2.0.17-stable-- 2.0 6:5:1 (No ABI change) +# 2.0.18-stable-- 2.0 6:6:1 (No ABI change) +# +# For Libevent 2.1: +# 2.1.1-alpha -- 2.1 1:0:0 + + +# ABI version history for this package effectively restarts every time +# we change RELEASE. Version 1.4.x had RELEASE of 1.4. +# +# Ideally, we would not be using RELEASE at all; instead we could just +# use the VERSION_INFO field to label our backward-incompatible ABI +# changes, and those would be few and far between. Unfortunately, +# Libevent still exposes far too many volatile structures in its +# headers, so we pretty much have to assume that most development +# series will break ABI compatibility. For now, it's simplest just to +# keep incrementing the RELEASE between series and resetting VERSION_INFO. +# +# Eventually, when we get to the point where the structures in the +# headers are all non-changing (or not there at all!), we can shift to +# a more normal worldview where backward-incompatible ABI changes are +# nice and rare. For the next couple of years, though, 'struct event' +# is user-visible, and so we can pretty much guarantee that release +# series won't be binary-compatible. + +if INSTALL_LIBEVENT +dist_bin_SCRIPTS = event_rpcgen.py +endif + +# These sources are conditionally added by configure.in or conditionally +# included from other files. +PLATFORM_DEPENDENT_SRC = \ + epoll_sub.c \ + arc4random.c + +EXTRA_DIST = \ + LICENSE \ + autogen.sh \ + event_rpcgen.py \ + libevent.pc.in \ + Doxyfile \ + whatsnew-2.0.txt \ + Makefile.nmake test/Makefile.nmake \ + $(PLATFORM_DEPENDENT_SRC) + +LIBEVENT_LIBS_LA = libevent.la libevent_core.la libevent_extra.la +if PTHREADS +LIBEVENT_LIBS_LA += libevent_pthreads.la +endif +if OPENSSL +LIBEVENT_LIBS_LA += libevent_openssl.la +endif + +if INSTALL_LIBEVENT +lib_LTLIBRARIES = $(LIBEVENT_LIBS_LA) +else +noinst_LTLIBRARIES = $(LIBEVENT_LIBS_LA) +endif + +SUBDIRS = . include sample test + +if BUILD_WIN32 + +SYS_LIBS = -lws2_32 -lshell32 -ladvapi32 +SYS_SRC = win32select.c evthread_win32.c buffer_iocp.c event_iocp.c \ + bufferevent_async.c +SYS_INCLUDES = -IWIN32-Code + +else + +SYS_LIBS = +SYS_SRC = +SYS_INCLUDES = + +endif + +if SELECT_BACKEND +SYS_SRC += select.c +endif +if POLL_BACKEND +SYS_SRC += poll.c +endif +if DEVPOLL_BACKEND +SYS_SRC += devpoll.c +endif +if KQUEUE_BACKEND +SYS_SRC += kqueue.c +endif +if EPOLL_BACKEND +SYS_SRC += epoll.c +endif +if EVPORT_BACKEND +SYS_SRC += evport.c +endif +if SIGNAL_SUPPORT +SYS_SRC += signal.c +endif + +BUILT_SOURCES = ./include/event2/event-config.h + +./include/event2/event-config.h: config.h + @MKDIR_P@ ./include/event2 + echo '/* event2/event-config.h' > $@ + echo ' *' >> $@ + echo ' * This file was generated by autoconf when libevent was built, and post-' >> $@ + echo ' * processed by Libevent so that its macros would have a uniform prefix.' >> $@ + echo ' *' >> $@ + echo ' * DO NOT EDIT THIS FILE.' >> $@ + echo ' *' >> $@ + echo ' * Do not rely on macros in this file existing in later versions.'>> $@ + echo ' */' >> $@ + echo '#ifndef _EVENT2_EVENT_CONFIG_H_' >> $@ + echo '#define _EVENT2_EVENT_CONFIG_H_' >> $@ + + sed -e 's/#define /#define _EVENT_/' \ + -e 's/#undef /#undef _EVENT_/' \ + -e 's/#ifndef /#ifndef _EVENT_/' < config.h >> $@ + echo "#endif" >> $@ + +CORE_SRC = event.c evthread.c buffer.c \ + bufferevent.c bufferevent_sock.c bufferevent_filter.c \ + bufferevent_pair.c listener.c bufferevent_ratelim.c \ + evmap.c log.c evutil.c evutil_rand.c strlcpy.c $(SYS_SRC) +EXTRA_SRC = event_tagging.c http.c evdns.c evrpc.c + +if BUILD_WITH_NO_UNDEFINED +NO_UNDEFINED = -no-undefined +MAYBE_CORE = libevent_core.la +else +NO_UNDEFINED = +MAYBE_CORE = +endif + +GENERIC_LDFLAGS = -static + +libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC) +libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) +libevent_la_LDFLAGS = $(GENERIC_LDFLAGS) + +libevent_core_la_SOURCES = $(CORE_SRC) +libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) +libevent_core_la_LDFLAGS = $(GENERIC_LDFLAGS) + +if PTHREADS +libevent_pthreads_la_SOURCES = evthread_pthread.c +libevent_pthreads_la_LIBADD = $(MAYBE_CORE) +libevent_pthreads_la_LDFLAGS = $(GENERIC_LDFLAGS) +endif + +libevent_extra_la_SOURCES = $(EXTRA_SRC) +libevent_extra_la_LIBADD = $(MAYBE_CORE) $(SYS_LIBS) +libevent_extra_la_LDFLAGS = $(GENERIC_LDFLAGS) + +if OPENSSL +libevent_openssl_la_SOURCES = bufferevent_openssl.c +libevent_openssl_la_LIBADD = $(MAYBE_CORE) $(OPENSSL_LIBS) +libevent_openssl_la_LDFLAGS = $(GENERIC_LDFLAGS) +endif + +noinst_HEADERS = util-internal.h mm-internal.h ipv6-internal.h \ + evrpc-internal.h strlcpy-internal.h evbuffer-internal.h \ + bufferevent-internal.h http-internal.h event-internal.h \ + evthread-internal.h ht-internal.h defer-internal.h \ + minheap-internal.h log-internal.h evsignal-internal.h evmap-internal.h \ + changelist-internal.h iocp-internal.h \ + ratelim-internal.h \ + WIN32-Code/event2/event-config.h \ + WIN32-Code/tree.h \ + compat/sys/queue.h + +EVENT1_HDRS = event.h evhttp.h evdns.h evrpc.h evutil.h + +if INSTALL_LIBEVENT +include_HEADERS = $(EVENT1_HDRS) +else +noinst_HEADERS += $(EVENT1_HDRS) +endif + +AM_CPPFLAGS = -I$(srcdir)/compat -I$(srcdir)/include -I./include $(SYS_INCLUDES) + +verify: check + +doxygen: FORCE + doxygen $(srcdir)/Doxyfile +FORCE: + +DISTCLEANFILES = *~ ./include/event2/event-config.h + +install: + diff --git a/libevent/Makefile.in b/libevent/Makefile.in new file mode 100644 index 0000000..f912136 --- /dev/null +++ b/libevent/Makefile.in @@ -0,0 +1,1344 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@PTHREADS_TRUE@am__append_1 = libevent_pthreads.la +@OPENSSL_TRUE@am__append_2 = libevent_openssl.la +@SELECT_BACKEND_TRUE@am__append_3 = select.c +@POLL_BACKEND_TRUE@am__append_4 = poll.c +@DEVPOLL_BACKEND_TRUE@am__append_5 = devpoll.c +@KQUEUE_BACKEND_TRUE@am__append_6 = kqueue.c +@EPOLL_BACKEND_TRUE@am__append_7 = epoll.c +@EVPORT_BACKEND_TRUE@am__append_8 = evport.c +@SIGNAL_SUPPORT_TRUE@am__append_9 = signal.c +@INSTALL_LIBEVENT_FALSE@am__append_10 = $(EVENT1_HDRS) +subdir = . +DIST_COMMON = README $(am__configure_deps) \ + $(am__dist_bin_SCRIPTS_DIST) $(am__include_HEADERS_DIST) \ + $(am__noinst_HEADERS_DIST) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/libevent.pc.in $(srcdir)/libevent_openssl.pc.in \ + $(srcdir)/libevent_pthreads.pc.in $(top_srcdir)/../compile \ + $(top_srcdir)/../config.guess $(top_srcdir)/../config.sub \ + $(top_srcdir)/../depcomp $(top_srcdir)/../install-sh \ + $(top_srcdir)/../ltmain.sh $(top_srcdir)/../missing \ + $(top_srcdir)/configure ChangeLog epoll_sub.c +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = libevent.pc libevent_openssl.pc \ + libevent_pthreads.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libevent_la_DEPENDENCIES = @LTLIBOBJS@ $(am__DEPENDENCIES_1) +am__libevent_la_SOURCES_DIST = event.c evthread.c buffer.c \ + bufferevent.c bufferevent_sock.c bufferevent_filter.c \ + bufferevent_pair.c listener.c bufferevent_ratelim.c evmap.c \ + log.c evutil.c evutil_rand.c strlcpy.c select.c poll.c \ + devpoll.c kqueue.c epoll.c evport.c signal.c win32select.c \ + evthread_win32.c buffer_iocp.c event_iocp.c \ + bufferevent_async.c event_tagging.c http.c evdns.c evrpc.c +@SELECT_BACKEND_TRUE@am__objects_1 = select.lo +@POLL_BACKEND_TRUE@am__objects_2 = poll.lo +@DEVPOLL_BACKEND_TRUE@am__objects_3 = devpoll.lo +@KQUEUE_BACKEND_TRUE@am__objects_4 = kqueue.lo +@EPOLL_BACKEND_TRUE@am__objects_5 = epoll.lo +@EVPORT_BACKEND_TRUE@am__objects_6 = evport.lo +@SIGNAL_SUPPORT_TRUE@am__objects_7 = signal.lo +@BUILD_WIN32_FALSE@am__objects_8 = $(am__objects_1) $(am__objects_2) \ +@BUILD_WIN32_FALSE@ $(am__objects_3) $(am__objects_4) \ +@BUILD_WIN32_FALSE@ $(am__objects_5) $(am__objects_6) \ +@BUILD_WIN32_FALSE@ $(am__objects_7) +@BUILD_WIN32_TRUE@am__objects_8 = win32select.lo evthread_win32.lo \ +@BUILD_WIN32_TRUE@ buffer_iocp.lo event_iocp.lo \ +@BUILD_WIN32_TRUE@ bufferevent_async.lo $(am__objects_1) \ +@BUILD_WIN32_TRUE@ $(am__objects_2) $(am__objects_3) \ +@BUILD_WIN32_TRUE@ $(am__objects_4) $(am__objects_5) \ +@BUILD_WIN32_TRUE@ $(am__objects_6) $(am__objects_7) +am__objects_9 = event.lo evthread.lo buffer.lo bufferevent.lo \ + bufferevent_sock.lo bufferevent_filter.lo bufferevent_pair.lo \ + listener.lo bufferevent_ratelim.lo evmap.lo log.lo evutil.lo \ + evutil_rand.lo strlcpy.lo $(am__objects_8) +am__objects_10 = event_tagging.lo http.lo evdns.lo evrpc.lo +am_libevent_la_OBJECTS = $(am__objects_9) $(am__objects_10) +libevent_la_OBJECTS = $(am_libevent_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libevent_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libevent_la_LDFLAGS) $(LDFLAGS) -o $@ +@INSTALL_LIBEVENT_FALSE@am_libevent_la_rpath = +@INSTALL_LIBEVENT_TRUE@am_libevent_la_rpath = -rpath $(libdir) +libevent_core_la_DEPENDENCIES = @LTLIBOBJS@ $(am__DEPENDENCIES_1) +am__libevent_core_la_SOURCES_DIST = event.c evthread.c buffer.c \ + bufferevent.c bufferevent_sock.c bufferevent_filter.c \ + bufferevent_pair.c listener.c bufferevent_ratelim.c evmap.c \ + log.c evutil.c evutil_rand.c strlcpy.c select.c poll.c \ + devpoll.c kqueue.c epoll.c evport.c signal.c win32select.c \ + evthread_win32.c buffer_iocp.c event_iocp.c \ + bufferevent_async.c +am_libevent_core_la_OBJECTS = $(am__objects_9) +libevent_core_la_OBJECTS = $(am_libevent_core_la_OBJECTS) +libevent_core_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libevent_core_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@INSTALL_LIBEVENT_FALSE@am_libevent_core_la_rpath = +@INSTALL_LIBEVENT_TRUE@am_libevent_core_la_rpath = -rpath $(libdir) +@BUILD_WITH_NO_UNDEFINED_TRUE@am__DEPENDENCIES_2 = libevent_core.la +libevent_extra_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_1) +am_libevent_extra_la_OBJECTS = $(am__objects_10) +libevent_extra_la_OBJECTS = $(am_libevent_extra_la_OBJECTS) +libevent_extra_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libevent_extra_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@INSTALL_LIBEVENT_FALSE@am_libevent_extra_la_rpath = +@INSTALL_LIBEVENT_TRUE@am_libevent_extra_la_rpath = -rpath $(libdir) +@OPENSSL_TRUE@libevent_openssl_la_DEPENDENCIES = \ +@OPENSSL_TRUE@ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +am__libevent_openssl_la_SOURCES_DIST = bufferevent_openssl.c +@OPENSSL_TRUE@am_libevent_openssl_la_OBJECTS = bufferevent_openssl.lo +libevent_openssl_la_OBJECTS = $(am_libevent_openssl_la_OBJECTS) +libevent_openssl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libevent_openssl_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@INSTALL_LIBEVENT_FALSE@@OPENSSL_TRUE@am_libevent_openssl_la_rpath = +@INSTALL_LIBEVENT_TRUE@@OPENSSL_TRUE@am_libevent_openssl_la_rpath = \ +@INSTALL_LIBEVENT_TRUE@@OPENSSL_TRUE@ -rpath $(libdir) +@PTHREADS_TRUE@libevent_pthreads_la_DEPENDENCIES = \ +@PTHREADS_TRUE@ $(am__DEPENDENCIES_2) +am__libevent_pthreads_la_SOURCES_DIST = evthread_pthread.c +@PTHREADS_TRUE@am_libevent_pthreads_la_OBJECTS = evthread_pthread.lo +libevent_pthreads_la_OBJECTS = $(am_libevent_pthreads_la_OBJECTS) +libevent_pthreads_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libevent_pthreads_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@INSTALL_LIBEVENT_FALSE@@PTHREADS_TRUE@am_libevent_pthreads_la_rpath = +@INSTALL_LIBEVENT_TRUE@@PTHREADS_TRUE@am_libevent_pthreads_la_rpath = \ +@INSTALL_LIBEVENT_TRUE@@PTHREADS_TRUE@ -rpath $(libdir) +am__dist_bin_SCRIPTS_DIST = event_rpcgen.py +SCRIPTS = $(dist_bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/../depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libevent_la_SOURCES) $(libevent_core_la_SOURCES) \ + $(libevent_extra_la_SOURCES) $(libevent_openssl_la_SOURCES) \ + $(libevent_pthreads_la_SOURCES) +DIST_SOURCES = $(am__libevent_la_SOURCES_DIST) \ + $(am__libevent_core_la_SOURCES_DIST) \ + $(libevent_extra_la_SOURCES) \ + $(am__libevent_openssl_la_SOURCES_DIST) \ + $(am__libevent_pthreads_la_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__include_HEADERS_DIST = event.h evhttp.h evdns.h evrpc.h evutil.h +am__noinst_HEADERS_DIST = util-internal.h mm-internal.h \ + ipv6-internal.h evrpc-internal.h strlcpy-internal.h \ + evbuffer-internal.h bufferevent-internal.h http-internal.h \ + event-internal.h evthread-internal.h ht-internal.h \ + defer-internal.h minheap-internal.h log-internal.h \ + evsignal-internal.h evmap-internal.h changelist-internal.h \ + iocp-internal.h ratelim-internal.h \ + WIN32-Code/event2/event-config.h WIN32-Code/tree.h \ + compat/sys/queue.h event.h evhttp.h evdns.h evrpc.h evutil.h +HEADERS = $(include_HEADERS) $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + cscope distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EV_LIB_GDI = @EV_LIB_GDI@ +EV_LIB_WS32 = @EV_LIB_WS32@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBEVENT_GC_SECTIONS = @LIBEVENT_GC_SECTIONS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIBADD = @OPENSSL_LIBADD@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acx_pthread_config = @acx_pthread_config@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# 'foreign' means that we're not enforcing GNU package rules strictly. +# '1.7' means that we need automake 1.7 or later (and we do). +AUTOMAKE_OPTIONS = foreign 1.7 +ACLOCAL_AMFLAGS = -I m4 + +# This is the "Release" of the Libevent ABI. It takes precedence over +# the VERSION_INFO, so that two versions of Libevent with the same +# "Release" are never binary-compatible. +# +# This number incremented once for the 2.0 release candidate, and +# will increment for each series until we revise our interfaces enough +# that we can seriously expect ABI compatibility between series. +# +RELEASE = -release 2.0 + +# This is the version info for the libevent binary API. It has three +# numbers: +# Current -- the number of the binary API that we're implementing +# Revision -- which iteration of the implementation of the binary +# API are we supplying? +# Age -- How many previous binary API versions do we also +# support? +# +# To increment a VERSION_INFO (current:revision:age): +# If the ABI didn't change: +# Return (current:revision+1:age) +# If the ABI changed, but it's backward-compatible: +# Return (current+1:0:age+1) +# If the ABI changed and it isn't backward-compatible: +# Return (current+1:0:0) +# +# Once an RC is out, DO NOT MAKE ANY ABI-BREAKING CHANGES IN THAT SERIES +# UNLESS YOU REALLY REALLY HAVE TO. +VERSION_INFO = 6:6:1 + +# History: RELEASE VERSION_INFO +# 2.0.1-alpha -- 2.0 1:0:0 +# 2.0.2-alpha -- 2:0:0 +# 2.0.3-alpha -- 2:0:0 (should have incremented; didn't.) +# 2.0.4-alpha -- 3:0:0 +# 2.0.5-beta -- 4:0:0 +# 2.0.6-rc -- 2.0 2:0:0 +# 2.0.7-rc -- 2.0 3:0:1 +# 2.0.8-rc -- 2.0 4:0:2 +# 2.0.9-rc -- 2.0 5:0:0 (ABI changed slightly) +# 2.0.10-stable-- 2.0 5:1:0 (No ABI change) +# 2.0.11-stable-- 2.0 6:0:1 (ABI changed, backward-compatible) +# 2.0.12-stable-- 2.0 6:1:1 (No ABI change) +# 2.0.13-stable-- 2.0 6:2:1 (No ABI change) +# 2.0.14-stable-- 2.0 6:3:1 (No ABI change) +# 2.0.15-stable-- 2.0 6:3:1 (Forgot to update :( ) +# 2.0.16-stable-- 2.0 6:4:1 (No ABI change) +# 2.0.17-stable-- 2.0 6:5:1 (No ABI change) +# 2.0.18-stable-- 2.0 6:6:1 (No ABI change) +# +# For Libevent 2.1: +# 2.1.1-alpha -- 2.1 1:0:0 + +# ABI version history for this package effectively restarts every time +# we change RELEASE. Version 1.4.x had RELEASE of 1.4. +# +# Ideally, we would not be using RELEASE at all; instead we could just +# use the VERSION_INFO field to label our backward-incompatible ABI +# changes, and those would be few and far between. Unfortunately, +# Libevent still exposes far too many volatile structures in its +# headers, so we pretty much have to assume that most development +# series will break ABI compatibility. For now, it's simplest just to +# keep incrementing the RELEASE between series and resetting VERSION_INFO. +# +# Eventually, when we get to the point where the structures in the +# headers are all non-changing (or not there at all!), we can shift to +# a more normal worldview where backward-incompatible ABI changes are +# nice and rare. For the next couple of years, though, 'struct event' +# is user-visible, and so we can pretty much guarantee that release +# series won't be binary-compatible. +@INSTALL_LIBEVENT_TRUE@dist_bin_SCRIPTS = event_rpcgen.py + +# These sources are conditionally added by configure.in or conditionally +# included from other files. +PLATFORM_DEPENDENT_SRC = \ + epoll_sub.c \ + arc4random.c + +EXTRA_DIST = \ + LICENSE \ + autogen.sh \ + event_rpcgen.py \ + libevent.pc.in \ + Doxyfile \ + whatsnew-2.0.txt \ + Makefile.nmake test/Makefile.nmake \ + $(PLATFORM_DEPENDENT_SRC) + +LIBEVENT_LIBS_LA = libevent.la libevent_core.la libevent_extra.la \ + $(am__append_1) $(am__append_2) +@INSTALL_LIBEVENT_TRUE@lib_LTLIBRARIES = $(LIBEVENT_LIBS_LA) +@INSTALL_LIBEVENT_FALSE@noinst_LTLIBRARIES = $(LIBEVENT_LIBS_LA) +SUBDIRS = . include sample test +@BUILD_WIN32_FALSE@SYS_LIBS = +@BUILD_WIN32_TRUE@SYS_LIBS = -lws2_32 -lshell32 -ladvapi32 +@BUILD_WIN32_FALSE@SYS_SRC = $(am__append_3) $(am__append_4) \ +@BUILD_WIN32_FALSE@ $(am__append_5) $(am__append_6) \ +@BUILD_WIN32_FALSE@ $(am__append_7) $(am__append_8) \ +@BUILD_WIN32_FALSE@ $(am__append_9) +@BUILD_WIN32_TRUE@SYS_SRC = win32select.c evthread_win32.c \ +@BUILD_WIN32_TRUE@ buffer_iocp.c event_iocp.c \ +@BUILD_WIN32_TRUE@ bufferevent_async.c $(am__append_3) \ +@BUILD_WIN32_TRUE@ $(am__append_4) $(am__append_5) \ +@BUILD_WIN32_TRUE@ $(am__append_6) $(am__append_7) \ +@BUILD_WIN32_TRUE@ $(am__append_8) $(am__append_9) +@BUILD_WIN32_FALSE@SYS_INCLUDES = +@BUILD_WIN32_TRUE@SYS_INCLUDES = -IWIN32-Code +BUILT_SOURCES = ./include/event2/event-config.h +CORE_SRC = event.c evthread.c buffer.c \ + bufferevent.c bufferevent_sock.c bufferevent_filter.c \ + bufferevent_pair.c listener.c bufferevent_ratelim.c \ + evmap.c log.c evutil.c evutil_rand.c strlcpy.c $(SYS_SRC) + +EXTRA_SRC = event_tagging.c http.c evdns.c evrpc.c +@BUILD_WITH_NO_UNDEFINED_FALSE@NO_UNDEFINED = +@BUILD_WITH_NO_UNDEFINED_TRUE@NO_UNDEFINED = -no-undefined +@BUILD_WITH_NO_UNDEFINED_FALSE@MAYBE_CORE = +@BUILD_WITH_NO_UNDEFINED_TRUE@MAYBE_CORE = libevent_core.la +GENERIC_LDFLAGS = -static +libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC) +libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) +libevent_la_LDFLAGS = $(GENERIC_LDFLAGS) +libevent_core_la_SOURCES = $(CORE_SRC) +libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) +libevent_core_la_LDFLAGS = $(GENERIC_LDFLAGS) +@PTHREADS_TRUE@libevent_pthreads_la_SOURCES = evthread_pthread.c +@PTHREADS_TRUE@libevent_pthreads_la_LIBADD = $(MAYBE_CORE) +@PTHREADS_TRUE@libevent_pthreads_la_LDFLAGS = $(GENERIC_LDFLAGS) +libevent_extra_la_SOURCES = $(EXTRA_SRC) +libevent_extra_la_LIBADD = $(MAYBE_CORE) $(SYS_LIBS) +libevent_extra_la_LDFLAGS = $(GENERIC_LDFLAGS) +@OPENSSL_TRUE@libevent_openssl_la_SOURCES = bufferevent_openssl.c +@OPENSSL_TRUE@libevent_openssl_la_LIBADD = $(MAYBE_CORE) $(OPENSSL_LIBS) +@OPENSSL_TRUE@libevent_openssl_la_LDFLAGS = $(GENERIC_LDFLAGS) +noinst_HEADERS = util-internal.h mm-internal.h ipv6-internal.h \ + evrpc-internal.h strlcpy-internal.h evbuffer-internal.h \ + bufferevent-internal.h http-internal.h event-internal.h \ + evthread-internal.h ht-internal.h defer-internal.h \ + minheap-internal.h log-internal.h evsignal-internal.h \ + evmap-internal.h changelist-internal.h iocp-internal.h \ + ratelim-internal.h WIN32-Code/event2/event-config.h \ + WIN32-Code/tree.h compat/sys/queue.h $(am__append_10) +EVENT1_HDRS = event.h evhttp.h evdns.h evrpc.h evutil.h +@INSTALL_LIBEVENT_TRUE@include_HEADERS = $(EVENT1_HDRS) +AM_CPPFLAGS = -I$(srcdir)/compat -I$(srcdir)/include -I./include $(SYS_INCLUDES) +DISTCLEANFILES = *~ ./include/event2/event-config.h +all: $(BUILT_SOURCES) config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +libevent.pc: $(top_builddir)/config.status $(srcdir)/libevent.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libevent_openssl.pc: $(top_builddir)/config.status $(srcdir)/libevent_openssl.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libevent_pthreads.pc: $(top_builddir)/config.status $(srcdir)/libevent_pthreads.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libevent.la: $(libevent_la_OBJECTS) $(libevent_la_DEPENDENCIES) $(EXTRA_libevent_la_DEPENDENCIES) + $(AM_V_CCLD)$(libevent_la_LINK) $(am_libevent_la_rpath) $(libevent_la_OBJECTS) $(libevent_la_LIBADD) $(LIBS) +libevent_core.la: $(libevent_core_la_OBJECTS) $(libevent_core_la_DEPENDENCIES) $(EXTRA_libevent_core_la_DEPENDENCIES) + $(AM_V_CCLD)$(libevent_core_la_LINK) $(am_libevent_core_la_rpath) $(libevent_core_la_OBJECTS) $(libevent_core_la_LIBADD) $(LIBS) +libevent_extra.la: $(libevent_extra_la_OBJECTS) $(libevent_extra_la_DEPENDENCIES) $(EXTRA_libevent_extra_la_DEPENDENCIES) + $(AM_V_CCLD)$(libevent_extra_la_LINK) $(am_libevent_extra_la_rpath) $(libevent_extra_la_OBJECTS) $(libevent_extra_la_LIBADD) $(LIBS) +libevent_openssl.la: $(libevent_openssl_la_OBJECTS) $(libevent_openssl_la_DEPENDENCIES) $(EXTRA_libevent_openssl_la_DEPENDENCIES) + $(AM_V_CCLD)$(libevent_openssl_la_LINK) $(am_libevent_openssl_la_rpath) $(libevent_openssl_la_OBJECTS) $(libevent_openssl_la_LIBADD) $(LIBS) +libevent_pthreads.la: $(libevent_pthreads_la_OBJECTS) $(libevent_pthreads_la_DEPENDENCIES) $(EXTRA_libevent_pthreads_la_DEPENDENCIES) + $(AM_V_CCLD)$(libevent_pthreads_la_LINK) $(am_libevent_pthreads_la_rpath) $(libevent_pthreads_la_OBJECTS) $(libevent_pthreads_la_LIBADD) $(LIBS) +install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-dist_binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/epoll_sub.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer_iocp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufferevent.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufferevent_async.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufferevent_filter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufferevent_openssl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufferevent_pair.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufferevent_ratelim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bufferevent_sock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devpoll.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epoll.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evdns.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event_iocp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event_tagging.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evport.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evrpc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evthread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evthread_pthread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evthread_win32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evutil.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evutil_rand.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kqueue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/select.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlcpy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32select.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) + +clean-cscope: + -rm -f cscope.files + +cscope.files: clean-cscope cscopelist-recursive cscopelist + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(HEADERS) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(DEPDIR) ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-includeHEADERS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-dist_binSCRIPTS install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf $(DEPDIR) ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_binSCRIPTS uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check \ + cscopelist-recursive ctags-recursive install install-am \ + install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-cscope \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES cscope cscopelist cscopelist-recursive \ + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ + dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_binSCRIPTS install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-dist_binSCRIPTS uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + + +./include/event2/event-config.h: config.h + @MKDIR_P@ ./include/event2 + echo '/* event2/event-config.h' > $@ + echo ' *' >> $@ + echo ' * This file was generated by autoconf when libevent was built, and post-' >> $@ + echo ' * processed by Libevent so that its macros would have a uniform prefix.' >> $@ + echo ' *' >> $@ + echo ' * DO NOT EDIT THIS FILE.' >> $@ + echo ' *' >> $@ + echo ' * Do not rely on macros in this file existing in later versions.'>> $@ + echo ' */' >> $@ + echo '#ifndef _EVENT2_EVENT_CONFIG_H_' >> $@ + echo '#define _EVENT2_EVENT_CONFIG_H_' >> $@ + + sed -e 's/#define /#define _EVENT_/' \ + -e 's/#undef /#undef _EVENT_/' \ + -e 's/#ifndef /#ifndef _EVENT_/' < config.h >> $@ + echo "#endif" >> $@ + +verify: check + +doxygen: FORCE + doxygen $(srcdir)/Doxyfile +FORCE: + +install: + +# 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/libevent/Makefile.nmake b/libevent/Makefile.nmake new file mode 100644 index 0000000..4cd04c1 --- /dev/null +++ b/libevent/Makefile.nmake @@ -0,0 +1,47 @@ +# WATCH OUT! This makefile is a work in progress. It is probably missing +# tons of important things. DO NOT RELY ON IT TO BUILD A GOOD LIBEVENT. + +# Needed for correctness +CFLAGS=/IWIN32-Code /Iinclude /Icompat /DWIN32 /DHAVE_CONFIG_H /I. + +# For optimization and warnings +CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo + +# XXXX have a debug mode + +LIBFLAGS=/nologo + +CORE_OBJS=event.obj buffer.obj bufferevent.obj bufferevent_sock.obj \ + bufferevent_pair.obj listener.obj evmap.obj log.obj evutil.obj \ + strlcpy.obj signal.obj bufferevent_filter.obj evthread.obj \ + bufferevent_ratelim.obj evutil_rand.obj +WIN_OBJS=win32select.obj evthread_win32.obj buffer_iocp.obj \ + event_iocp.obj bufferevent_async.obj +EXTRA_OBJS=event_tagging.obj http.obj evdns.obj evrpc.obj + +ALL_OBJS=$(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS) +STATIC_LIBS=libevent_core.lib libevent_extras.lib libevent.lib + + +all: static_libs tests + +static_libs: $(STATIC_LIBS) + +libevent_core.lib: $(CORE_OBJS) $(WIN_OBJS) + lib $(LIBFLAGS) $(CORE_OBJS) $(WIN_OBJS) /out:libevent_core.lib + +libevent_extras.lib: $(EXTRA_OBJS) + lib $(LIBFLAGS) $(EXTRA_OBJS) /out:libevent_extras.lib + +libevent.lib: $(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS) + lib $(LIBFLAGS) $(CORE_OBJS) $(EXTRA_OBJS) $(WIN_OBJS) /out:libevent.lib + +clean: + del $(ALL_OBJS) + del $(STATIC_LIBS) + cd test + $(MAKE) /F Makefile.nmake clean + +tests: + cd test + $(MAKE) /F Makefile.nmake diff --git a/libevent/README b/libevent/README new file mode 100644 index 0000000..9d695bb --- /dev/null +++ b/libevent/README @@ -0,0 +1,188 @@ +0. BUILDING AND INSTALLATION (Briefly) + +$ ./configure +$ make +$ make verify # (optional) +$ sudo make install + +1. BUILDING AND INSTALLATION (In Depth) + +To build libevent, type + +$ ./configure && make + + (If you got libevent from the git repository, you will + first need to run the included "autogen.sh" script in order to + generate the configure script.) + +You can run the regression tests by running + +$ make verify + +Install as root via + +# make install + +Before, reporting any problems, please run the regression tests. + +To enable the low-level tracing build the library as: + + CFLAGS=-DUSE_DEBUG ./configure [...] + +Standard configure flags should work. In particular, see: + + --disable-shared Only build static libraries + --prefix Install all files relative to this directory. + + +The configure script also supports the following flags: + + --enable-gcc-warnings Enable extra compiler checking with GCC. + --disable-malloc-replacement + Don't let applications replace our memory + management functions + --disable-openssl Disable support for OpenSSL encryption. + --disable-thread-support Don't support multithreaded environments. + +2. USEFUL LINKS: + +For the latest released version of Libevent, see the official website at +http://monkey.org/~provos/libevent/ . + +There's a pretty good work-in-progress manual up at + http://www.wangafu.net/~nickm/libevent-book/ . + +For the latest development versions of Libevent, access our Git repository +via + "git clone git://levent.git.sourceforge.net/gitroot/levent/libevent" + +You can browse the git repository online at +http://levent.git.sourceforge.net/git/gitweb-index.cgi . + +To report bugs, request features, or submit patches to Libevent, +use the Sourceforge trackers at +https://sourceforge.net/tracker/?group_id=50884 . + +There's also a libevent-users mailing list for talking about Libevent +use and development: http://archives.seul.org/libevent/users/ + +3. ACKNOWLEDGMENTS + +The following people have helped with suggestions, ideas, code or +fixing bugs: + + Arno Bakker + Alejo + Weston Andros Adamson + William Ahern + Ivan Andropov + Sergey Avseyev + Avi Bab + Gilad Benjamini + Stas Bekman + Joachim Bauch + Denis Bilenko + Julien Blache + Kevin Bowling + Tomash Brechko + Kelly Brock + Ralph Castain + Adrian Chadd + Lawnstein Chan + Shuo Chen + Ka-Hing Cheung + Andrew Danforth + Ed Day + Christopher Davis + Mike Davis + Mihai Draghicioiu + Mark Ellzey + Shie Erlich + Leonid Evdokimov + Christophe Fillot + Mike Frysinger + Remi Gacogne + Alexander von Gernler + Artur Grabowski + Dave Hart + Greg Hazel + Michael Herf + Sebastian Hahn + Mark Heily + Greg Hewgill + Aaron Hopkins + Tani Hosokawa + Jamie Iles + Claudio Jeker + Evan Jones + George Kadianakis + Phua Keat + Kevin Ko + Brian Koehmstedt + Marko Kreen + Valery Kyholodov + Ross Lagerwall + Scott Lamb + Christopher Layne + Adam Langley + Philip Lewis + Zhou Li + David Libenzi + Yan Lin + Moshe Litvin + Mitchell Livingston + Hagne Mahre + Lubomir Marinov + Abilio Marques + Nick Mathewson + James Mansion + Nicholas Marriott + Andrey Matveev + Caitlin Mercer + Dagobert Michelsen + Mansour Moufid + Felix Nawothnig + Trond Norbye + Linus Nordberg + Richard Nyberg + Jon Oberheide + Phil Oleson + Dave Pacheco + Tassilo von Parseval + Catalin Patulea + Simon Perreault + Pierre Phaneuf + Ryan Phillips + Dimitre Piskyulev + Pavel Plesov + Jon Poland + Nate R + Robert Ransom + Bert JW Regeer + Peter Rosin + Maseeb Abdul Qadir + Wang Qin + Hanna Schroeter + Ralf Schmitt + Mike Smellie + Kevin Springborn + Harlan Stenn + Steve Snyder + Dug Song + Dongsheng Song + Hannes Sowa + Ferenc Szalai + Brodie Thiesfield + Jason Toffaletti + Gisle Vanem + Bas Verhoeven + Constantine Verutin + Colin Watt + Zack Weinberg + Jardel Weyrich + Alex + Taral + propanbutan + mmadia + +If we have forgotten your name, please contact us. diff --git a/libevent/WIN32-Code/event2/event-config.h b/libevent/WIN32-Code/event2/event-config.h new file mode 100644 index 0000000..67aaf60 --- /dev/null +++ b/libevent/WIN32-Code/event2/event-config.h @@ -0,0 +1,363 @@ +/* event2/event-config.h + * + * This file was generated by autoconf when libevent was built, and post- + * processed by Libevent so that its macros would have a uniform prefix. + * + * DO NOT EDIT THIS FILE. + * + * Do not rely on macros in this file existing in later versions. + */ +#ifndef _EVENT_CONFIG_H_ +#define _EVENT_CONFIG_H_ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if libevent should not allow replacing the mm functions */ +/* #undef _EVENT_DISABLE_MM_REPLACEMENT */ + +/* Define if libevent should not be compiled with thread support */ +/* #undef _EVENT_DISABLE_THREAD_SUPPORT */ + +/* Define if clock_gettime is available in libc */ +/* #undef _EVENT_DNS_USE_CPU_CLOCK_FOR_ID */ + +/* Define is no secure id variant is available */ +/* #define _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID 1 */ +#define _EVENT_DNS_USE_FTIME_FOR_ID 1 + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the `clock_gettime' function. */ +/* #undef _EVENT_HAVE_CLOCK_GETTIME */ + +/* Define if /dev/poll is available */ +/* #undef _EVENT_HAVE_DEVPOLL */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_DLFCN_H */ + +/* Define if your system supports the epoll system calls */ +/* #undef _EVENT_HAVE_EPOLL */ + +/* Define to 1 if you have the `epoll_ctl' function. */ +/* #undef _EVENT_HAVE_EPOLL_CTL */ + +/* Define to 1 if you have the `eventfd' function. */ +/* #undef _EVENT_HAVE_EVENTFD */ + +/* Define if your system supports event ports */ +/* #undef _EVENT_HAVE_EVENT_PORTS */ + +/* Define to 1 if you have the `fcntl' function. */ +/* #undef _EVENT_HAVE_FCNTL */ + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define _EVENT_HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getnameinfo' function. */ +#define _EVENT_HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getprotobynumber' function. */ +#define _EVENT_HAVE_GETPROTOBYNUMBER 1 + +/* Define to 1 if you have the `getservbyname' function. */ +#define _EVENT_HAVE_GETSERVBYNAME 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #define _EVENT_HAVE_GETTIMEOFDAY 1 */ + +/* Define to 1 if you have the `inet_aton' function. */ +/* #undef _EVENT_HAVE_INET_ATON */ + +/* Define to 1 if you have the `inet_ntop' function. */ +/* #undef _EVENT_HAVE_INET_NTOP */ + +/* Define to 1 if you have the `inet_pton' function. */ +/* #undef _EVENT_HAVE_INET_PTON */ + +/* Define to 1 if you have the header file. */ +/* #define _EVENT_HAVE_INTTYPES_H 1 */ + +/* Define to 1 if you have the `kqueue' function. */ +/* #undef _EVENT_HAVE_KQUEUE */ + +/* Define if the system has zlib */ +/* #undef _EVENT_HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mmap' function. */ +/* #undef _EVENT_HAVE_MMAP */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_NETINET_IN6_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_NETINET_IN_H */ + +/* Define to 1 if you have the `pipe' function. */ +/* #undef _EVENT_HAVE_PIPE */ + +/* Define to 1 if you have the `poll' function. */ +/* #undef _EVENT_HAVE_POLL */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_POLL_H */ + +/* Define to 1 if you have the `port_create' function. */ +/* #undef _EVENT_HAVE_PORT_CREATE */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_PORT_H */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef _EVENT_HAVE_PTHREAD */ + +/* Define if we have pthreads on this system */ +/* #undef _EVENT_HAVE_PTHREADS */ + +/* Define to 1 if the system has the type `sa_family_t'. */ +/* #undef _EVENT_HAVE_SA_FAMILY_T */ + +/* Define to 1 if you have the `select' function. */ +/* #undef _EVENT_HAVE_SELECT */ + +/* Define to 1 if you have the `sendfile' function. */ +/* #undef _EVENT_HAVE_SENDFILE */ + +/* Define if F_SETFD is defined in */ +/* #undef _EVENT_HAVE_SETFD */ + +/* Define to 1 if you have the `sigaction' function. */ +/* #undef _EVENT_HAVE_SIGACTION */ + +/* Define to 1 if you have the `signal' function. */ +#define _EVENT_HAVE_SIGNAL 1 + +/* Define to 1 if you have the `splice' function. */ +/* #undef _EVENT_HAVE_SPLICE */ + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +/* #define _EVENT_HAVE_STDINT_H 1 */ + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef _EVENT_HAVE_STRLCPY */ + +/* Define to 1 if you have the `strsep' function. */ +/* #undef _EVENT_HAVE_STRSEP */ + +/* Define to 1 if you have the `strtok_r' function. */ +/* #undef _EVENT_HAVE_STRTOK_R */ + +/* Define to 1 if you have the `strtoll' function. */ +/* #define _EVENT_HAVE_STRTOLL 1 */ + +#define _EVENT_HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if the system has the type `struct in6_addr'. */ +#define _EVENT_HAVE_STRUCT_IN6_ADDR 1 + +/* Define to 1 if `s6_addr16' is member of `struct in6_addr'. */ +#define _EVENT_HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1 + +/* Define to 1 if `s6_addr32' is member of `struct in6_addr'. */ +#define _EVENT_HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1 + +/* Define to 1 if the system has the type `struct sockaddr_in6'. */ +#define _EVENT_HAVE_STRUCT_SOCKADDR_IN6 1 + +/* Define to 1 if `sin6_len' is member of `struct sockaddr_in6'. */ +/* #undef _EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */ + +/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */ +/* #undef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define _EVENT_HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_EPOLL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_EVENTFD_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_EVENT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_MMAN_H */ + +/* Define to 1 if you have the header file. */ +/* #define _EVENT_HAVE_SYS_PARAM_H 1 */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_QUEUE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_SENDFILE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #define _EVENT_HAVE_SYS_TIME_H 1 */ + +/* Define to 1 if you have the header file. */ +#define _EVENT_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _EVENT_HAVE_SYS_UIO_H */ + +/* Define if TAILQ_FOREACH is defined in */ +/* #undef _EVENT_HAVE_TAILQFOREACH */ + +/* Define if timeradd is defined in */ +/* #undef _EVENT_HAVE_TIMERADD */ + +/* Define if timerclear is defined in */ +#define _EVENT_HAVE_TIMERCLEAR 1 + +/* Define if timercmp is defined in */ +#define _EVENT_HAVE_TIMERCMP 1 + +/* Define if timerisset is defined in */ +#define _EVENT_HAVE_TIMERISSET 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +/* #define _EVENT_HAVE_UINT16_T 1 */ + +/* Define to 1 if the system has the type `uint32_t'. */ +/* #define _EVENT_HAVE_UINT32_T 1 */ + +/* Define to 1 if the system has the type `uint64_t'. */ +/* #define _EVENT_HAVE_UINT64_T 1 */ + +/* Define to 1 if the system has the type `uint8_t'. */ +/* #define _EVENT_HAVE_UINT8_T 1 */ + +/* Define to 1 if you have the header file. */ +/* #define _EVENT_HAVE_UNISTD_H 1 */ + +/* Define to 1 if you have the `vasprintf' function. */ +/* #undef _EVENT_HAVE_VASPRINTF */ + +/* Define if kqueue works correctly with pipes */ +/* #undef _EVENT_HAVE_WORKING_KQUEUE */ + +/* Numeric representation of the version */ +#define _EVENT_NUMERIC_VERSION 0x02001200 + +/* Name of package */ +#define _EVENT_PACKAGE "libevent" + +/* Define to the address where bug reports for this package should be sent. */ +#define _EVENT_PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define _EVENT_PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define _EVENT_PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define _EVENT_PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define _EVENT_PACKAGE_VERSION "" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef _EVENT_PTHREAD_CREATE_JOINABLE */ + +/* The size of a `int', as computed by sizeof. */ +#define _EVENT_SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define _EVENT_SIZEOF_LONG 4 + +/* The size of a `long long', as computed by sizeof. */ +#define _EVENT_SIZEOF_LONG_LONG 8 + +/* The size of a `short', as computed by sizeof. */ +#define _EVENT_SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#ifdef _WIN64 +#define _EVENT_SIZEOF_SIZE_T 8 +#else +#define _EVENT_SIZEOF_SIZE_T 4 +#endif + +/* The size of `void *', as computed by sizeof. */ +#ifdef _WIN64 +#define _EVENT_SIZEOF_VOID_P 8 +#else +#define _EVENT_SIZEOF_VOID_P 4 +#endif + +/* Define to 1 if you have the ANSI C header files. */ +#define _EVENT_STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define _EVENT_TIME_WITH_SYS_TIME 1 + +/* Version number of package */ +#define _EVENT_VERSION "2.0.18-stable" + +/* Define to appropriate substitue if compiler doesnt have __func__ */ +#define _EVENT___func__ __FUNCTION__ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef _EVENT_const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef _EVENT___cplusplus +#define _EVENT_inline __inline +#endif + +/* Define to `int' if does not define. */ +/* #undef _EVENT_pid_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef _EVENT_size_t */ + +/* Define to unsigned int if you dont have it */ +#define _EVENT_socklen_t unsigned int + +/* Define to `int' if does not define. */ +#define _EVENT_ssize_t SSIZE_T + +#endif diff --git a/libevent/WIN32-Code/tree.h b/libevent/WIN32-Code/tree.h new file mode 100644 index 0000000..585618d --- /dev/null +++ b/libevent/WIN32-Code/tree.h @@ -0,0 +1,1354 @@ +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-back tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ +void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +struct type *name##_RB_REMOVE(struct name *, struct type *); \ +struct type *name##_RB_INSERT(struct name *, struct type *); \ +struct type *name##_RB_FIND(struct name *, struct type *); \ +struct type *name##_RB_NEXT(struct type *); \ +struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ +void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#endif /* _SYS_TREE_H_ */ +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-back tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ +void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +struct type *name##_RB_REMOVE(struct name *, struct type *); \ +struct type *name##_RB_INSERT(struct name *, struct type *); \ +struct type *name##_RB_FIND(struct name *, struct type *); \ +struct type *name##_RB_NEXT(struct type *); \ +struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ +void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#endif /* _SYS_TREE_H_ */ diff --git a/libevent/aclocal.m4 b/libevent/aclocal.m4 new file mode 100644 index 0000000..6c37698 --- /dev/null +++ b/libevent/aclocal.m4 @@ -0,0 +1,1051 @@ +# generated automatically by aclocal 1.12.5 -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.12' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.12.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.12.5])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], +[$0: two- and three-arguments forms are deprecated. For more info, see: +http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +dnl Support for Objective C++ was only introduced in Autoconf 2.65, +dnl but we still cater to Autoconf 2.62. +m4_ifdef([AC_PROG_OBJCXX], +[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_CC_C_O +# -------------- +# Like AC_PROG_CC_C_O, but changed for automake. +AC_DEFUN([AM_PROG_CC_C_O], +[AC_REQUIRE([AC_PROG_CC_C_O])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of '-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/acx_pthread.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) diff --git a/libevent/arc4random.c b/libevent/arc4random.c new file mode 100644 index 0000000..cabc46f --- /dev/null +++ b/libevent/arc4random.c @@ -0,0 +1,539 @@ +/* Portable arc4random.c based on arc4random.c from OpenBSD. + * Portable version by Chris Davis, adapted for Libevent by Nick Mathewson + * Copyright (c) 2010 Chris Davis, Niels Provos, and Nick Mathewson + * Copyright (c) 2010-2012 Niels Provos and Nick Mathewson + * + * Note that in Libevent, this file isn't compiled directly. Instead, + * it's included from evutil_rand.c + */ + +/* + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * + * 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. + */ + +/* + * Arc4 random number generator for OpenBSD. + * + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * Here the stream cipher has been modified always to include the time + * when initializing the state. That makes it impossible to + * regenerate the same random sequence twice, so this can't be used + * for encryption, but will generate good random numbers. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +#ifndef ARC4RANDOM_EXPORT +#define ARC4RANDOM_EXPORT +#endif + +#ifndef ARC4RANDOM_UINT32 +#define ARC4RANDOM_UINT32 uint32_t +#endif + +#ifndef ARC4RANDOM_NO_INCLUDES +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#include +#ifdef _EVENT_HAVE_SYS_SYSCTL_H +#include +#endif +#endif +#include +#include +#include +#endif + +/* Add platform entropy 32 bytes (256 bits) at a time. */ +#define ADD_ENTROPY 32 + +/* Re-seed from the platform RNG after generating this many bytes. */ +#define BYTES_BEFORE_RESEED 1600000 + +struct arc4_stream { + unsigned char i; + unsigned char j; + unsigned char s[256]; +}; + +#ifdef WIN32 +#define getpid _getpid +#define pid_t int +#endif + +static int rs_initialized; +static struct arc4_stream rs; +static pid_t arc4_stir_pid; +static int arc4_count; +static int arc4_seeded_ok; + +static inline unsigned char arc4_getbyte(void); + +static inline void +arc4_init(void) +{ + int n; + + for (n = 0; n < 256; n++) + rs.s[n] = n; + rs.i = 0; + rs.j = 0; +} + +static inline void +arc4_addrandom(const unsigned char *dat, int datlen) +{ + int n; + unsigned char si; + + rs.i--; + for (n = 0; n < 256; n++) { + rs.i = (rs.i + 1); + si = rs.s[rs.i]; + rs.j = (rs.j + si + dat[n % datlen]); + rs.s[rs.i] = rs.s[rs.j]; + rs.s[rs.j] = si; + } + rs.j = rs.i; +} + +#ifndef WIN32 +static ssize_t +read_all(int fd, unsigned char *buf, size_t count) +{ + size_t numread = 0; + ssize_t result; + + while (numread < count) { + result = read(fd, buf+numread, count-numread); + if (result<0) + return -1; + else if (result == 0) + break; + numread += result; + } + + return (ssize_t)numread; +} +#endif + +#ifdef WIN32 +#define TRY_SEED_WIN32 +static int +arc4_seed_win32(void) +{ + /* This is adapted from Tor's crypto_seed_rng() */ + static int provider_set = 0; + static HCRYPTPROV provider; + unsigned char buf[ADD_ENTROPY]; + + if (!provider_set) { + if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + if (GetLastError() != (DWORD)NTE_BAD_KEYSET) + return -1; + } + provider_set = 1; + } + if (!CryptGenRandom(provider, sizeof(buf), buf)) + return -1; + arc4_addrandom(buf, sizeof(buf)); + memset(buf, 0, sizeof(buf)); + arc4_seeded_ok = 1; + return 0; +} +#endif + +#if defined(_EVENT_HAVE_SYS_SYSCTL_H) && defined(_EVENT_HAVE_SYSCTL) +#if _EVENT_HAVE_DECL_CTL_KERN && _EVENT_HAVE_DECL_KERN_RANDOM && _EVENT_HAVE_DECL_RANDOM_UUID +#define TRY_SEED_SYSCTL_LINUX +static int +arc4_seed_sysctl_linux(void) +{ + /* Based on code by William Ahern, this function tries to use the + * RANDOM_UUID sysctl to get entropy from the kernel. This can work + * even if /dev/urandom is inaccessible for some reason (e.g., we're + * running in a chroot). */ + int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; + unsigned char buf[ADD_ENTROPY]; + size_t len, n; + unsigned i; + int any_set; + + memset(buf, 0, sizeof(buf)); + + for (len = 0; len < sizeof(buf); len += n) { + n = sizeof(buf) - len; + + if (0 != sysctl(mib, 3, &buf[len], &n, NULL, 0)) + return -1; + } + /* make sure that the buffer actually got set. */ + for (i=0,any_set=0; i sizeof(buf)) + n = len - sizeof(buf); + if (sysctl(mib, 2, &buf[len], &n, NULL, 0) == -1) + return -1; + } + } + /* make sure that the buffer actually got set. */ + for (i=any_set=0; i 0xffffffffUL) + min = 0x100000000UL % upper_bound; +#else + /* Calculate (2**32 % upper_bound) avoiding 64-bit math */ + if (upper_bound > 0x80000000) + min = 1 + ~upper_bound; /* 2**32 - upper_bound */ + else { + /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */ + min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound; + } +#endif + + /* + * This could theoretically loop forever but each retry has + * p > 0.5 (worst case, usually far better) of selecting a + * number inside the range we need, so it should rarely need + * to re-roll. + */ + for (;;) { + r = arc4random(); + if (r >= min) + break; + } + + return r % upper_bound; +} +#endif diff --git a/libevent/autogen.sh b/libevent/autogen.sh new file mode 100755 index 0000000..57eeb94 --- /dev/null +++ b/libevent/autogen.sh @@ -0,0 +1,15 @@ +#!/bin/sh +if [ -x "`which autoreconf 2>/dev/null`" ] ; then + exec autoreconf -ivf +fi + +LIBTOOLIZE=libtoolize +SYSNAME=`uname` +if [ "x$SYSNAME" = "xDarwin" ] ; then + LIBTOOLIZE=glibtoolize +fi +aclocal -I m4 && \ + autoheader && \ + $LIBTOOLIZE && \ + autoconf && \ + automake --add-missing --force-missing --copy diff --git a/libevent/buffer.c b/libevent/buffer.c new file mode 100644 index 0000000..ff64aed --- /dev/null +++ b/libevent/buffer.c @@ -0,0 +1,3062 @@ +/* + * Copyright (c) 2002-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#include "event2/event-config.h" + +#ifdef WIN32 +#include +#include +#include +#endif + +#ifdef _EVENT_HAVE_VASPRINTF +/* If we have vasprintf, we need to define this before we include stdio.h. */ +#define _GNU_SOURCE +#endif + +#include + +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef _EVENT_HAVE_SYS_UIO_H +#include +#endif + +#ifdef _EVENT_HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef _EVENT_HAVE_SYS_MMAN_H +#include +#endif + +#ifdef _EVENT_HAVE_SYS_SENDFILE_H +#include +#endif + +#include +#include +#include +#include +#ifdef _EVENT_HAVE_STDARG_H +#include +#endif +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#include + +#include "event2/event.h" +#include "event2/buffer.h" +#include "event2/buffer_compat.h" +#include "event2/bufferevent.h" +#include "event2/bufferevent_compat.h" +#include "event2/bufferevent_struct.h" +#include "event2/thread.h" +#include "event2/event-config.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "util-internal.h" +#include "evthread-internal.h" +#include "evbuffer-internal.h" +#include "bufferevent-internal.h" + +/* some systems do not have MAP_FAILED */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +/* send file support */ +#if defined(_EVENT_HAVE_SYS_SENDFILE_H) && defined(_EVENT_HAVE_SENDFILE) && defined(__linux__) +#define USE_SENDFILE 1 +#define SENDFILE_IS_LINUX 1 +#elif defined(_EVENT_HAVE_SENDFILE) && defined(__FreeBSD__) +#define USE_SENDFILE 1 +#define SENDFILE_IS_FREEBSD 1 +#elif defined(_EVENT_HAVE_SENDFILE) && defined(__APPLE__) +#define USE_SENDFILE 1 +#define SENDFILE_IS_MACOSX 1 +#elif defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__) +#define USE_SENDFILE 1 +#define SENDFILE_IS_SOLARIS 1 +#endif + +#ifdef USE_SENDFILE +static int use_sendfile = 1; +#endif +#ifdef _EVENT_HAVE_MMAP +static int use_mmap = 1; +#endif + + +/* Mask of user-selectable callback flags. */ +#define EVBUFFER_CB_USER_FLAGS 0xffff +/* Mask of all internal-use-only flags. */ +#define EVBUFFER_CB_INTERNAL_FLAGS 0xffff0000 + +/* Flag set if the callback is using the cb_obsolete function pointer */ +#define EVBUFFER_CB_OBSOLETE 0x00040000 + +/* evbuffer_chain support */ +#define CHAIN_SPACE_PTR(ch) ((ch)->buffer + (ch)->misalign + (ch)->off) +#define CHAIN_SPACE_LEN(ch) ((ch)->flags & EVBUFFER_IMMUTABLE ? \ + 0 : (ch)->buffer_len - ((ch)->misalign + (ch)->off)) + +#define CHAIN_PINNED(ch) (((ch)->flags & EVBUFFER_MEM_PINNED_ANY) != 0) +#define CHAIN_PINNED_R(ch) (((ch)->flags & EVBUFFER_MEM_PINNED_R) != 0) + +static void evbuffer_chain_align(struct evbuffer_chain *chain); +static int evbuffer_chain_should_realign(struct evbuffer_chain *chain, + size_t datalen); +static void evbuffer_deferred_callback(struct deferred_cb *cb, void *arg); +static int evbuffer_ptr_memcmp(const struct evbuffer *buf, + const struct evbuffer_ptr *pos, const char *mem, size_t len); +static struct evbuffer_chain *evbuffer_expand_singlechain(struct evbuffer *buf, + size_t datlen); + +#ifdef WIN32 +static int evbuffer_readfile(struct evbuffer *buf, evutil_socket_t fd, + ev_ssize_t howmuch); +#else +#define evbuffer_readfile evbuffer_read +#endif + +static struct evbuffer_chain * +evbuffer_chain_new(size_t size) +{ + struct evbuffer_chain *chain; + size_t to_alloc; + + size += EVBUFFER_CHAIN_SIZE; + + /* get the next largest memory that can hold the buffer */ + to_alloc = MIN_BUFFER_SIZE; + while (to_alloc < size) + to_alloc <<= 1; + + /* we get everything in one chunk */ + if ((chain = mm_malloc(to_alloc)) == NULL) + return (NULL); + + memset(chain, 0, EVBUFFER_CHAIN_SIZE); + + chain->buffer_len = to_alloc - EVBUFFER_CHAIN_SIZE; + + /* this way we can manipulate the buffer to different addresses, + * which is required for mmap for example. + */ + chain->buffer = EVBUFFER_CHAIN_EXTRA(u_char, chain); + + return (chain); +} + +static inline void +evbuffer_chain_free(struct evbuffer_chain *chain) +{ + if (CHAIN_PINNED(chain)) { + chain->flags |= EVBUFFER_DANGLING; + return; + } + if (chain->flags & (EVBUFFER_MMAP|EVBUFFER_SENDFILE| + EVBUFFER_REFERENCE)) { + if (chain->flags & EVBUFFER_REFERENCE) { + struct evbuffer_chain_reference *info = + EVBUFFER_CHAIN_EXTRA( + struct evbuffer_chain_reference, + chain); + if (info->cleanupfn) + (*info->cleanupfn)(chain->buffer, + chain->buffer_len, + info->extra); + } +#ifdef _EVENT_HAVE_MMAP + if (chain->flags & EVBUFFER_MMAP) { + struct evbuffer_chain_fd *info = + EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_fd, + chain); + if (munmap(chain->buffer, chain->buffer_len) == -1) + event_warn("%s: munmap failed", __func__); + if (close(info->fd) == -1) + event_warn("%s: close(%d) failed", + __func__, info->fd); + } +#endif +#ifdef USE_SENDFILE + if (chain->flags & EVBUFFER_SENDFILE) { + struct evbuffer_chain_fd *info = + EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_fd, + chain); + if (close(info->fd) == -1) + event_warn("%s: close(%d) failed", + __func__, info->fd); + } +#endif + } + + mm_free(chain); +} + +static void +evbuffer_free_all_chains(struct evbuffer_chain *chain) +{ + struct evbuffer_chain *next; + for (; chain; chain = next) { + next = chain->next; + evbuffer_chain_free(chain); + } +} + +#ifndef NDEBUG +static int +evbuffer_chains_all_empty(struct evbuffer_chain *chain) +{ + for (; chain; chain = chain->next) { + if (chain->off) + return 0; + } + return 1; +} +#else +/* The definition is needed for EVUTIL_ASSERT, which uses sizeof to avoid +"unused variable" warnings. */ +static inline int evbuffer_chains_all_empty(struct evbuffer_chain *chain) { + return 1; +} +#endif + +/* Free all trailing chains in 'buf' that are neither pinned nor empty, prior + * to replacing them all with a new chain. Return a pointer to the place + * where the new chain will go. + * + * Internal; requires lock. The caller must fix up buf->last and buf->first + * as needed; they might have been freed. + */ +static struct evbuffer_chain ** +evbuffer_free_trailing_empty_chains(struct evbuffer *buf) +{ + struct evbuffer_chain **ch = buf->last_with_datap; + /* Find the first victim chain. It might be *last_with_datap */ + while ((*ch) && ((*ch)->off != 0 || CHAIN_PINNED(*ch))) + ch = &(*ch)->next; + if (*ch) { + EVUTIL_ASSERT(evbuffer_chains_all_empty(*ch)); + evbuffer_free_all_chains(*ch); + *ch = NULL; + } + return ch; +} + +/* Add a single chain 'chain' to the end of 'buf', freeing trailing empty + * chains as necessary. Requires lock. Does not schedule callbacks. + */ +static void +evbuffer_chain_insert(struct evbuffer *buf, + struct evbuffer_chain *chain) +{ + ASSERT_EVBUFFER_LOCKED(buf); + if (*buf->last_with_datap == NULL) { + /* There are no chains data on the buffer at all. */ + EVUTIL_ASSERT(buf->last_with_datap == &buf->first); + EVUTIL_ASSERT(buf->first == NULL); + buf->first = buf->last = chain; + } else { + struct evbuffer_chain **ch = buf->last_with_datap; + /* Find the first victim chain. It might be *last_with_datap */ + while ((*ch) && ((*ch)->off != 0 || CHAIN_PINNED(*ch))) + ch = &(*ch)->next; + if (*ch == NULL) { + /* There is no victim; just append this new chain. */ + buf->last->next = chain; + if (chain->off) + buf->last_with_datap = &buf->last->next; + } else { + /* Replace all victim chains with this chain. */ + EVUTIL_ASSERT(evbuffer_chains_all_empty(*ch)); + evbuffer_free_all_chains(*ch); + *ch = chain; + } + buf->last = chain; + } + buf->total_len += chain->off; +} + +static inline struct evbuffer_chain * +evbuffer_chain_insert_new(struct evbuffer *buf, size_t datlen) +{ + struct evbuffer_chain *chain; + if ((chain = evbuffer_chain_new(datlen)) == NULL) + return NULL; + evbuffer_chain_insert(buf, chain); + return chain; +} + +void +_evbuffer_chain_pin(struct evbuffer_chain *chain, unsigned flag) +{ + EVUTIL_ASSERT((chain->flags & flag) == 0); + chain->flags |= flag; +} + +void +_evbuffer_chain_unpin(struct evbuffer_chain *chain, unsigned flag) +{ + EVUTIL_ASSERT((chain->flags & flag) != 0); + chain->flags &= ~flag; + if (chain->flags & EVBUFFER_DANGLING) + evbuffer_chain_free(chain); +} + +struct evbuffer * +evbuffer_new(void) +{ + struct evbuffer *buffer; + + buffer = mm_calloc(1, sizeof(struct evbuffer)); + if (buffer == NULL) + return (NULL); + + TAILQ_INIT(&buffer->callbacks); + buffer->refcnt = 1; + buffer->last_with_datap = &buffer->first; + + return (buffer); +} + +int +evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags) +{ + EVBUFFER_LOCK(buf); + buf->flags |= (ev_uint32_t)flags; + EVBUFFER_UNLOCK(buf); + return 0; +} + +int +evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags) +{ + EVBUFFER_LOCK(buf); + buf->flags &= ~(ev_uint32_t)flags; + EVBUFFER_UNLOCK(buf); + return 0; +} + +void +_evbuffer_incref(struct evbuffer *buf) +{ + EVBUFFER_LOCK(buf); + ++buf->refcnt; + EVBUFFER_UNLOCK(buf); +} + +void +_evbuffer_incref_and_lock(struct evbuffer *buf) +{ + EVBUFFER_LOCK(buf); + ++buf->refcnt; +} + +int +evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base) +{ + EVBUFFER_LOCK(buffer); + buffer->cb_queue = event_base_get_deferred_cb_queue(base); + buffer->deferred_cbs = 1; + event_deferred_cb_init(&buffer->deferred, + evbuffer_deferred_callback, buffer); + EVBUFFER_UNLOCK(buffer); + return 0; +} + +int +evbuffer_enable_locking(struct evbuffer *buf, void *lock) +{ +#ifdef _EVENT_DISABLE_THREAD_SUPPORT + return -1; +#else + if (buf->lock) + return -1; + + if (!lock) { + EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE); + if (!lock) + return -1; + buf->lock = lock; + buf->own_lock = 1; + } else { + buf->lock = lock; + buf->own_lock = 0; + } + + return 0; +#endif +} + +void +evbuffer_set_parent(struct evbuffer *buf, struct bufferevent *bev) +{ + EVBUFFER_LOCK(buf); + buf->parent = bev; + EVBUFFER_UNLOCK(buf); +} + +static void +evbuffer_run_callbacks(struct evbuffer *buffer, int running_deferred) +{ + struct evbuffer_cb_entry *cbent, *next; + struct evbuffer_cb_info info; + size_t new_size; + ev_uint32_t mask, masked_val; + int clear = 1; + + if (running_deferred) { + mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; + masked_val = EVBUFFER_CB_ENABLED; + } else if (buffer->deferred_cbs) { + mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; + masked_val = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; + /* Don't zero-out n_add/n_del, since the deferred callbacks + will want to see them. */ + clear = 0; + } else { + mask = EVBUFFER_CB_ENABLED; + masked_val = EVBUFFER_CB_ENABLED; + } + + ASSERT_EVBUFFER_LOCKED(buffer); + + if (TAILQ_EMPTY(&buffer->callbacks)) { + buffer->n_add_for_cb = buffer->n_del_for_cb = 0; + return; + } + if (buffer->n_add_for_cb == 0 && buffer->n_del_for_cb == 0) + return; + + new_size = buffer->total_len; + info.orig_size = new_size + buffer->n_del_for_cb - buffer->n_add_for_cb; + info.n_added = buffer->n_add_for_cb; + info.n_deleted = buffer->n_del_for_cb; + if (clear) { + buffer->n_add_for_cb = 0; + buffer->n_del_for_cb = 0; + } + for (cbent = TAILQ_FIRST(&buffer->callbacks); + cbent != TAILQ_END(&buffer->callbacks); + cbent = next) { + /* Get the 'next' pointer now in case this callback decides + * to remove itself or something. */ + next = TAILQ_NEXT(cbent, next); + + if ((cbent->flags & mask) != masked_val) + continue; + + if ((cbent->flags & EVBUFFER_CB_OBSOLETE)) + cbent->cb.cb_obsolete(buffer, + info.orig_size, new_size, cbent->cbarg); + else + cbent->cb.cb_func(buffer, &info, cbent->cbarg); + } +} + +void +evbuffer_invoke_callbacks(struct evbuffer *buffer) +{ + if (TAILQ_EMPTY(&buffer->callbacks)) { + buffer->n_add_for_cb = buffer->n_del_for_cb = 0; + return; + } + + if (buffer->deferred_cbs) { + if (buffer->deferred.queued) + return; + _evbuffer_incref_and_lock(buffer); + if (buffer->parent) + bufferevent_incref(buffer->parent); + EVBUFFER_UNLOCK(buffer); + event_deferred_cb_schedule(buffer->cb_queue, &buffer->deferred); + } + + evbuffer_run_callbacks(buffer, 0); +} + +static void +evbuffer_deferred_callback(struct deferred_cb *cb, void *arg) +{ + struct bufferevent *parent = NULL; + struct evbuffer *buffer = arg; + + /* XXXX It would be better to run these callbacks without holding the + * lock */ + EVBUFFER_LOCK(buffer); + parent = buffer->parent; + evbuffer_run_callbacks(buffer, 1); + _evbuffer_decref_and_unlock(buffer); + if (parent) + bufferevent_decref(parent); +} + +static void +evbuffer_remove_all_callbacks(struct evbuffer *buffer) +{ + struct evbuffer_cb_entry *cbent; + + while ((cbent = TAILQ_FIRST(&buffer->callbacks))) { + TAILQ_REMOVE(&buffer->callbacks, cbent, next); + mm_free(cbent); + } +} + +void +_evbuffer_decref_and_unlock(struct evbuffer *buffer) +{ + struct evbuffer_chain *chain, *next; + ASSERT_EVBUFFER_LOCKED(buffer); + + EVUTIL_ASSERT(buffer->refcnt > 0); + + if (--buffer->refcnt > 0) { + EVBUFFER_UNLOCK(buffer); + return; + } + + for (chain = buffer->first; chain != NULL; chain = next) { + next = chain->next; + evbuffer_chain_free(chain); + } + evbuffer_remove_all_callbacks(buffer); + if (buffer->deferred_cbs) + event_deferred_cb_cancel(buffer->cb_queue, &buffer->deferred); + + EVBUFFER_UNLOCK(buffer); + if (buffer->own_lock) + EVTHREAD_FREE_LOCK(buffer->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + mm_free(buffer); +} + +void +evbuffer_free(struct evbuffer *buffer) +{ + EVBUFFER_LOCK(buffer); + _evbuffer_decref_and_unlock(buffer); +} + +void +evbuffer_lock(struct evbuffer *buf) +{ + EVBUFFER_LOCK(buf); +} + +void +evbuffer_unlock(struct evbuffer *buf) +{ + EVBUFFER_UNLOCK(buf); +} + +size_t +evbuffer_get_length(const struct evbuffer *buffer) +{ + size_t result; + + EVBUFFER_LOCK(buffer); + + result = (buffer->total_len); + + EVBUFFER_UNLOCK(buffer); + + return result; +} + +size_t +evbuffer_get_contiguous_space(const struct evbuffer *buf) +{ + struct evbuffer_chain *chain; + size_t result; + + EVBUFFER_LOCK(buf); + chain = buf->first; + result = (chain != NULL ? chain->off : 0); + EVBUFFER_UNLOCK(buf); + + return result; +} + +int +evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size, + struct evbuffer_iovec *vec, int n_vecs) +{ + struct evbuffer_chain *chain, **chainp; + int n = -1; + + EVBUFFER_LOCK(buf); + if (buf->freeze_end) + goto done; + if (n_vecs < 1) + goto done; + if (n_vecs == 1) { + if ((chain = evbuffer_expand_singlechain(buf, size)) == NULL) + goto done; + + vec[0].iov_base = CHAIN_SPACE_PTR(chain); + vec[0].iov_len = (size_t) CHAIN_SPACE_LEN(chain); + EVUTIL_ASSERT(size<0 || (size_t)vec[0].iov_len >= (size_t)size); + n = 1; + } else { + if (_evbuffer_expand_fast(buf, size, n_vecs)<0) + goto done; + n = _evbuffer_read_setup_vecs(buf, size, vec, n_vecs, + &chainp, 0); + } + +done: + EVBUFFER_UNLOCK(buf); + return n; + +} + +static int +advance_last_with_data(struct evbuffer *buf) +{ + int n = 0; + ASSERT_EVBUFFER_LOCKED(buf); + + if (!*buf->last_with_datap) + return 0; + + while ((*buf->last_with_datap)->next && (*buf->last_with_datap)->next->off) { + buf->last_with_datap = &(*buf->last_with_datap)->next; + ++n; + } + return n; +} + +int +evbuffer_commit_space(struct evbuffer *buf, + struct evbuffer_iovec *vec, int n_vecs) +{ + struct evbuffer_chain *chain, **firstchainp, **chainp; + int result = -1; + size_t added = 0; + int i; + + EVBUFFER_LOCK(buf); + + if (buf->freeze_end) + goto done; + if (n_vecs == 0) { + result = 0; + goto done; + } else if (n_vecs == 1 && + (buf->last && vec[0].iov_base == (void*)CHAIN_SPACE_PTR(buf->last))) { + /* The user only got or used one chain; it might not + * be the first one with space in it. */ + if ((size_t)vec[0].iov_len > (size_t)CHAIN_SPACE_LEN(buf->last)) + goto done; + buf->last->off += vec[0].iov_len; + added = vec[0].iov_len; + if (added) + advance_last_with_data(buf); + goto okay; + } + + /* Advance 'firstchain' to the first chain with space in it. */ + firstchainp = buf->last_with_datap; + if (!*firstchainp) + goto done; + if (CHAIN_SPACE_LEN(*firstchainp) == 0) { + firstchainp = &(*firstchainp)->next; + } + + chain = *firstchainp; + /* pass 1: make sure that the pointers and lengths of vecs[] are in + * bounds before we try to commit anything. */ + for (i=0; i CHAIN_SPACE_LEN(chain)) + goto done; + chain = chain->next; + } + /* pass 2: actually adjust all the chains. */ + chainp = firstchainp; + for (i=0; ioff += vec[i].iov_len; + added += vec[i].iov_len; + if (vec[i].iov_len) { + buf->last_with_datap = chainp; + } + chainp = &(*chainp)->next; + } + +okay: + buf->total_len += added; + buf->n_add_for_cb += added; + result = 0; + evbuffer_invoke_callbacks(buf); + +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +static inline int +HAS_PINNED_R(struct evbuffer *buf) +{ + return (buf->last && CHAIN_PINNED_R(buf->last)); +} + +static inline void +ZERO_CHAIN(struct evbuffer *dst) +{ + ASSERT_EVBUFFER_LOCKED(dst); + dst->first = NULL; + dst->last = NULL; + dst->last_with_datap = &(dst)->first; + dst->total_len = 0; +} + +/* Prepares the contents of src to be moved to another buffer by removing + * read-pinned chains. The first pinned chain is saved in first, and the + * last in last. If src has no read-pinned chains, first and last are set + * to NULL. */ +static int +PRESERVE_PINNED(struct evbuffer *src, struct evbuffer_chain **first, + struct evbuffer_chain **last) +{ + struct evbuffer_chain *chain, **pinned; + + ASSERT_EVBUFFER_LOCKED(src); + + if (!HAS_PINNED_R(src)) { + *first = *last = NULL; + return 0; + } + + pinned = src->last_with_datap; + if (!CHAIN_PINNED_R(*pinned)) + pinned = &(*pinned)->next; + EVUTIL_ASSERT(CHAIN_PINNED_R(*pinned)); + chain = *first = *pinned; + *last = src->last; + + /* If there's data in the first pinned chain, we need to allocate + * a new chain and copy the data over. */ + if (chain->off) { + struct evbuffer_chain *tmp; + + EVUTIL_ASSERT(pinned == src->last_with_datap); + tmp = evbuffer_chain_new(chain->off); + if (!tmp) + return -1; + memcpy(tmp->buffer, chain->buffer + chain->misalign, + chain->off); + tmp->off = chain->off; + *src->last_with_datap = tmp; + src->last = tmp; + chain->misalign += chain->off; + chain->off = 0; + } else { + src->last = *src->last_with_datap; + *pinned = NULL; + } + + return 0; +} + +static inline void +RESTORE_PINNED(struct evbuffer *src, struct evbuffer_chain *pinned, + struct evbuffer_chain *last) +{ + ASSERT_EVBUFFER_LOCKED(src); + + if (!pinned) { + ZERO_CHAIN(src); + return; + } + + src->first = pinned; + src->last = last; + src->last_with_datap = &src->first; + src->total_len = 0; +} + +static inline void +COPY_CHAIN(struct evbuffer *dst, struct evbuffer *src) +{ + ASSERT_EVBUFFER_LOCKED(dst); + ASSERT_EVBUFFER_LOCKED(src); + dst->first = src->first; + if (src->last_with_datap == &src->first) + dst->last_with_datap = &dst->first; + else + dst->last_with_datap = src->last_with_datap; + dst->last = src->last; + dst->total_len = src->total_len; +} + +static void +APPEND_CHAIN(struct evbuffer *dst, struct evbuffer *src) +{ + ASSERT_EVBUFFER_LOCKED(dst); + ASSERT_EVBUFFER_LOCKED(src); + dst->last->next = src->first; + if (src->last_with_datap == &src->first) + dst->last_with_datap = &dst->last->next; + else + dst->last_with_datap = src->last_with_datap; + dst->last = src->last; + dst->total_len += src->total_len; +} + +static void +PREPEND_CHAIN(struct evbuffer *dst, struct evbuffer *src) +{ + ASSERT_EVBUFFER_LOCKED(dst); + ASSERT_EVBUFFER_LOCKED(src); + src->last->next = dst->first; + dst->first = src->first; + dst->total_len += src->total_len; + if (*dst->last_with_datap == NULL) { + if (src->last_with_datap == &(src)->first) + dst->last_with_datap = &dst->first; + else + dst->last_with_datap = src->last_with_datap; + } else if (dst->last_with_datap == &dst->first) { + dst->last_with_datap = &src->last->next; + } +} + +int +evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf) +{ + struct evbuffer_chain *pinned, *last; + size_t in_total_len, out_total_len; + int result = 0; + + EVBUFFER_LOCK2(inbuf, outbuf); + in_total_len = inbuf->total_len; + out_total_len = outbuf->total_len; + + if (in_total_len == 0 || outbuf == inbuf) + goto done; + + if (outbuf->freeze_end || inbuf->freeze_start) { + result = -1; + goto done; + } + + if (PRESERVE_PINNED(inbuf, &pinned, &last) < 0) { + result = -1; + goto done; + } + + if (out_total_len == 0) { + /* There might be an empty chain at the start of outbuf; free + * it. */ + evbuffer_free_all_chains(outbuf->first); + COPY_CHAIN(outbuf, inbuf); + } else { + APPEND_CHAIN(outbuf, inbuf); + } + + RESTORE_PINNED(inbuf, pinned, last); + + inbuf->n_del_for_cb += in_total_len; + outbuf->n_add_for_cb += in_total_len; + + evbuffer_invoke_callbacks(inbuf); + evbuffer_invoke_callbacks(outbuf); + +done: + EVBUFFER_UNLOCK2(inbuf, outbuf); + return result; +} + +int +evbuffer_prepend_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf) +{ + struct evbuffer_chain *pinned, *last; + size_t in_total_len, out_total_len; + int result = 0; + + EVBUFFER_LOCK2(inbuf, outbuf); + + in_total_len = inbuf->total_len; + out_total_len = outbuf->total_len; + + if (!in_total_len || inbuf == outbuf) + goto done; + + if (outbuf->freeze_start || inbuf->freeze_start) { + result = -1; + goto done; + } + + if (PRESERVE_PINNED(inbuf, &pinned, &last) < 0) { + result = -1; + goto done; + } + + if (out_total_len == 0) { + /* There might be an empty chain at the start of outbuf; free + * it. */ + evbuffer_free_all_chains(outbuf->first); + COPY_CHAIN(outbuf, inbuf); + } else { + PREPEND_CHAIN(outbuf, inbuf); + } + + RESTORE_PINNED(inbuf, pinned, last); + + inbuf->n_del_for_cb += in_total_len; + outbuf->n_add_for_cb += in_total_len; + + evbuffer_invoke_callbacks(inbuf); + evbuffer_invoke_callbacks(outbuf); +done: + EVBUFFER_UNLOCK2(inbuf, outbuf); + return result; +} + +int +evbuffer_drain(struct evbuffer *buf, size_t len) +{ + struct evbuffer_chain *chain, *next; + size_t remaining, old_len; + int result = 0; + + EVBUFFER_LOCK(buf); + old_len = buf->total_len; + + if (old_len == 0) + goto done; + + if (buf->freeze_start) { + result = -1; + goto done; + } + + if (len >= old_len && !HAS_PINNED_R(buf)) { + len = old_len; + for (chain = buf->first; chain != NULL; chain = next) { + next = chain->next; + evbuffer_chain_free(chain); + } + + ZERO_CHAIN(buf); + } else { + if (len >= old_len) + len = old_len; + + buf->total_len -= len; + remaining = len; + for (chain = buf->first; + remaining >= chain->off; + chain = next) { + next = chain->next; + remaining -= chain->off; + + if (chain == *buf->last_with_datap) { + buf->last_with_datap = &buf->first; + } + if (&chain->next == buf->last_with_datap) + buf->last_with_datap = &buf->first; + + if (CHAIN_PINNED_R(chain)) { + EVUTIL_ASSERT(remaining == 0); + chain->misalign += chain->off; + chain->off = 0; + break; + } else + evbuffer_chain_free(chain); + } + + buf->first = chain; + if (chain) { + chain->misalign += remaining; + chain->off -= remaining; + } + } + + buf->n_del_for_cb += len; + /* Tell someone about changes in this buffer */ + evbuffer_invoke_callbacks(buf); + +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +/* Reads data from an event buffer and drains the bytes read */ +int +evbuffer_remove(struct evbuffer *buf, void *data_out, size_t datlen) +{ + ev_ssize_t n; + EVBUFFER_LOCK(buf); + n = evbuffer_copyout(buf, data_out, datlen); + if (n > 0) { + if (evbuffer_drain(buf, n)<0) + n = -1; + } + EVBUFFER_UNLOCK(buf); + return (int)n; +} + +ev_ssize_t +evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen) +{ + /*XXX fails badly on sendfile case. */ + struct evbuffer_chain *chain; + char *data = data_out; + size_t nread; + ev_ssize_t result = 0; + + EVBUFFER_LOCK(buf); + + chain = buf->first; + + if (datlen >= buf->total_len) + datlen = buf->total_len; + + if (datlen == 0) + goto done; + + if (buf->freeze_start) { + result = -1; + goto done; + } + + nread = datlen; + + while (datlen && datlen >= chain->off) { + memcpy(data, chain->buffer + chain->misalign, chain->off); + data += chain->off; + datlen -= chain->off; + + chain = chain->next; + EVUTIL_ASSERT(chain || datlen==0); + } + + if (datlen) { + EVUTIL_ASSERT(chain); + memcpy(data, chain->buffer + chain->misalign, datlen); + } + + result = nread; +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +/* reads data from the src buffer to the dst buffer, avoids memcpy as + * possible. */ +/* XXXX should return ev_ssize_t */ +int +evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst, + size_t datlen) +{ + /*XXX We should have an option to force this to be zero-copy.*/ + + /*XXX can fail badly on sendfile case. */ + struct evbuffer_chain *chain, *previous; + size_t nread = 0; + int result; + + EVBUFFER_LOCK2(src, dst); + + chain = previous = src->first; + + if (datlen == 0 || dst == src) { + result = 0; + goto done; + } + + if (dst->freeze_end || src->freeze_start) { + result = -1; + goto done; + } + + /* short-cut if there is no more data buffered */ + if (datlen >= src->total_len) { + datlen = src->total_len; + evbuffer_add_buffer(dst, src); + result = (int)datlen; /*XXXX should return ev_ssize_t*/ + goto done; + } + + /* removes chains if possible */ + while (chain->off <= datlen) { + /* We can't remove the last with data from src unless we + * remove all chains, in which case we would have done the if + * block above */ + EVUTIL_ASSERT(chain != *src->last_with_datap); + nread += chain->off; + datlen -= chain->off; + previous = chain; + if (src->last_with_datap == &chain->next) + src->last_with_datap = &src->first; + chain = chain->next; + } + + if (nread) { + /* we can remove the chain */ + struct evbuffer_chain **chp; + chp = evbuffer_free_trailing_empty_chains(dst); + + if (dst->first == NULL) { + dst->first = src->first; + } else { + *chp = src->first; + } + dst->last = previous; + previous->next = NULL; + src->first = chain; + advance_last_with_data(dst); + + dst->total_len += nread; + dst->n_add_for_cb += nread; + } + + /* we know that there is more data in the src buffer than + * we want to read, so we manually drain the chain */ + evbuffer_add(dst, chain->buffer + chain->misalign, datlen); + chain->misalign += datlen; + chain->off -= datlen; + nread += datlen; + + /* You might think we would want to increment dst->n_add_for_cb + * here too. But evbuffer_add above already took care of that. + */ + src->total_len -= nread; + src->n_del_for_cb += nread; + + if (nread) { + evbuffer_invoke_callbacks(dst); + evbuffer_invoke_callbacks(src); + } + result = (int)nread;/*XXXX should change return type */ + +done: + EVBUFFER_UNLOCK2(src, dst); + return result; +} + +unsigned char * +evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size) +{ + struct evbuffer_chain *chain, *next, *tmp, *last_with_data; + unsigned char *buffer, *result = NULL; + ev_ssize_t remaining; + int removed_last_with_data = 0; + int removed_last_with_datap = 0; + + EVBUFFER_LOCK(buf); + + chain = buf->first; + + if (size < 0) + size = buf->total_len; + /* if size > buf->total_len, we cannot guarantee to the user that she + * is going to have a long enough buffer afterwards; so we return + * NULL */ + if (size == 0 || (size_t)size > buf->total_len) + goto done; + + /* No need to pull up anything; the first size bytes are + * already here. */ + if (chain->off >= (size_t)size) { + result = chain->buffer + chain->misalign; + goto done; + } + + /* Make sure that none of the chains we need to copy from is pinned. */ + remaining = size - chain->off; + EVUTIL_ASSERT(remaining >= 0); + for (tmp=chain->next; tmp; tmp=tmp->next) { + if (CHAIN_PINNED(tmp)) + goto done; + if (tmp->off >= (size_t)remaining) + break; + remaining -= tmp->off; + } + + if (CHAIN_PINNED(chain)) { + size_t old_off = chain->off; + if (CHAIN_SPACE_LEN(chain) < size - chain->off) { + /* not enough room at end of chunk. */ + goto done; + } + buffer = CHAIN_SPACE_PTR(chain); + tmp = chain; + tmp->off = size; + size -= old_off; + chain = chain->next; + } else if (chain->buffer_len - chain->misalign >= (size_t)size) { + /* already have enough space in the first chain */ + size_t old_off = chain->off; + buffer = chain->buffer + chain->misalign + chain->off; + tmp = chain; + tmp->off = size; + size -= old_off; + chain = chain->next; + } else { + if ((tmp = evbuffer_chain_new(size)) == NULL) { + event_warn("%s: out of memory", __func__); + goto done; + } + buffer = tmp->buffer; + tmp->off = size; + buf->first = tmp; + } + + /* TODO(niels): deal with buffers that point to NULL like sendfile */ + + /* Copy and free every chunk that will be entirely pulled into tmp */ + last_with_data = *buf->last_with_datap; + for (; chain != NULL && (size_t)size >= chain->off; chain = next) { + next = chain->next; + + memcpy(buffer, chain->buffer + chain->misalign, chain->off); + size -= chain->off; + buffer += chain->off; + if (chain == last_with_data) + removed_last_with_data = 1; + if (&chain->next == buf->last_with_datap) + removed_last_with_datap = 1; + + evbuffer_chain_free(chain); + } + + if (chain != NULL) { + memcpy(buffer, chain->buffer + chain->misalign, size); + chain->misalign += size; + chain->off -= size; + } else { + buf->last = tmp; + } + + tmp->next = chain; + + if (removed_last_with_data) { + buf->last_with_datap = &buf->first; + } else if (removed_last_with_datap) { + if (buf->first->next && buf->first->next->off) + buf->last_with_datap = &buf->first->next; + else + buf->last_with_datap = &buf->first; + } + + result = (tmp->buffer + tmp->misalign); + +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +/* + * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. + * The returned buffer needs to be freed by the called. + */ +char * +evbuffer_readline(struct evbuffer *buffer) +{ + return evbuffer_readln(buffer, NULL, EVBUFFER_EOL_ANY); +} + +static inline ev_ssize_t +evbuffer_strchr(struct evbuffer_ptr *it, const char chr) +{ + struct evbuffer_chain *chain = it->_internal.chain; + size_t i = it->_internal.pos_in_chain; + while (chain != NULL) { + char *buffer = (char *)chain->buffer + chain->misalign; + char *cp = memchr(buffer+i, chr, chain->off-i); + if (cp) { + it->_internal.chain = chain; + it->_internal.pos_in_chain = cp - buffer; + it->pos += (cp - buffer - i); + return it->pos; + } + it->pos += chain->off - i; + i = 0; + chain = chain->next; + } + + return (-1); +} + +static inline char * +find_eol_char(char *s, size_t len) +{ +#define CHUNK_SZ 128 + /* Lots of benchmarking found this approach to be faster in practice + * than doing two memchrs over the whole buffer, doin a memchr on each + * char of the buffer, or trying to emulate memchr by hand. */ + char *s_end, *cr, *lf; + s_end = s+len; + while (s < s_end) { + size_t chunk = (s + CHUNK_SZ < s_end) ? CHUNK_SZ : (s_end - s); + cr = memchr(s, '\r', chunk); + lf = memchr(s, '\n', chunk); + if (cr) { + if (lf && lf < cr) + return lf; + return cr; + } else if (lf) { + return lf; + } + s += CHUNK_SZ; + } + + return NULL; +#undef CHUNK_SZ +} + +static ev_ssize_t +evbuffer_find_eol_char(struct evbuffer_ptr *it) +{ + struct evbuffer_chain *chain = it->_internal.chain; + size_t i = it->_internal.pos_in_chain; + while (chain != NULL) { + char *buffer = (char *)chain->buffer + chain->misalign; + char *cp = find_eol_char(buffer+i, chain->off-i); + if (cp) { + it->_internal.chain = chain; + it->_internal.pos_in_chain = cp - buffer; + it->pos += (cp - buffer) - i; + return it->pos; + } + it->pos += chain->off - i; + i = 0; + chain = chain->next; + } + + return (-1); +} + +static inline int +evbuffer_strspn( + struct evbuffer_ptr *ptr, const char *chrset) +{ + int count = 0; + struct evbuffer_chain *chain = ptr->_internal.chain; + size_t i = ptr->_internal.pos_in_chain; + + if (!chain) + return -1; + + while (1) { + char *buffer = (char *)chain->buffer + chain->misalign; + for (; i < chain->off; ++i) { + const char *p = chrset; + while (*p) { + if (buffer[i] == *p++) + goto next; + } + ptr->_internal.chain = chain; + ptr->_internal.pos_in_chain = i; + ptr->pos += count; + return count; + next: + ++count; + } + i = 0; + + if (! chain->next) { + ptr->_internal.chain = chain; + ptr->_internal.pos_in_chain = i; + ptr->pos += count; + return count; + } + + chain = chain->next; + } +} + + +static inline char +evbuffer_getchr(struct evbuffer_ptr *it) +{ + struct evbuffer_chain *chain = it->_internal.chain; + size_t off = it->_internal.pos_in_chain; + + return chain->buffer[chain->misalign + off]; +} + +struct evbuffer_ptr +evbuffer_search_eol(struct evbuffer *buffer, + struct evbuffer_ptr *start, size_t *eol_len_out, + enum evbuffer_eol_style eol_style) +{ + struct evbuffer_ptr it, it2; + size_t extra_drain = 0; + int ok = 0; + + EVBUFFER_LOCK(buffer); + + if (start) { + memcpy(&it, start, sizeof(it)); + } else { + it.pos = 0; + it._internal.chain = buffer->first; + it._internal.pos_in_chain = 0; + } + + /* the eol_style determines our first stop character and how many + * characters we are going to drain afterwards. */ + switch (eol_style) { + case EVBUFFER_EOL_ANY: + if (evbuffer_find_eol_char(&it) < 0) + goto done; + memcpy(&it2, &it, sizeof(it)); + extra_drain = evbuffer_strspn(&it2, "\r\n"); + break; + case EVBUFFER_EOL_CRLF_STRICT: { + it = evbuffer_search(buffer, "\r\n", 2, &it); + if (it.pos < 0) + goto done; + extra_drain = 2; + break; + } + case EVBUFFER_EOL_CRLF: + while (1) { + if (evbuffer_find_eol_char(&it) < 0) + goto done; + if (evbuffer_getchr(&it) == '\n') { + extra_drain = 1; + break; + } else if (!evbuffer_ptr_memcmp( + buffer, &it, "\r\n", 2)) { + extra_drain = 2; + break; + } else { + if (evbuffer_ptr_set(buffer, &it, 1, + EVBUFFER_PTR_ADD)<0) + goto done; + } + } + break; + case EVBUFFER_EOL_LF: + if (evbuffer_strchr(&it, '\n') < 0) + goto done; + extra_drain = 1; + break; + default: + goto done; + } + + ok = 1; +done: + EVBUFFER_UNLOCK(buffer); + + if (!ok) { + it.pos = -1; + } + if (eol_len_out) + *eol_len_out = extra_drain; + + return it; +} + +char * +evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, + enum evbuffer_eol_style eol_style) +{ + struct evbuffer_ptr it; + char *line; + size_t n_to_copy=0, extra_drain=0; + char *result = NULL; + + EVBUFFER_LOCK(buffer); + + if (buffer->freeze_start) { + goto done; + } + + it = evbuffer_search_eol(buffer, NULL, &extra_drain, eol_style); + if (it.pos < 0) + goto done; + n_to_copy = it.pos; + + if ((line = mm_malloc(n_to_copy+1)) == NULL) { + event_warn("%s: out of memory", __func__); + goto done; + } + + evbuffer_remove(buffer, line, n_to_copy); + line[n_to_copy] = '\0'; + + evbuffer_drain(buffer, extra_drain); + result = line; +done: + EVBUFFER_UNLOCK(buffer); + + if (n_read_out) + *n_read_out = result ? n_to_copy : 0; + + return result; +} + +#define EVBUFFER_CHAIN_MAX_AUTO_SIZE 4096 + +/* Adds data to an event buffer */ + +int +evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen) +{ + struct evbuffer_chain *chain, *tmp; + const unsigned char *data = data_in; + size_t remain, to_alloc; + int result = -1; + + EVBUFFER_LOCK(buf); + + if (buf->freeze_end) { + goto done; + } + + chain = buf->last; + + /* If there are no chains allocated for this buffer, allocate one + * big enough to hold all the data. */ + if (chain == NULL) { + chain = evbuffer_chain_new(datlen); + if (!chain) + goto done; + evbuffer_chain_insert(buf, chain); + } + + if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) { + remain = (size_t)(chain->buffer_len - chain->misalign - chain->off); + if (remain >= datlen) { + /* there's enough space to hold all the data in the + * current last chain */ + memcpy(chain->buffer + chain->misalign + chain->off, + data, datlen); + chain->off += datlen; + buf->total_len += datlen; + buf->n_add_for_cb += datlen; + goto out; + } else if (!CHAIN_PINNED(chain) && + evbuffer_chain_should_realign(chain, datlen)) { + /* we can fit the data into the misalignment */ + evbuffer_chain_align(chain); + + memcpy(chain->buffer + chain->off, data, datlen); + chain->off += datlen; + buf->total_len += datlen; + buf->n_add_for_cb += datlen; + goto out; + } + } else { + /* we cannot write any data to the last chain */ + remain = 0; + } + + /* we need to add another chain */ + to_alloc = chain->buffer_len; + if (to_alloc <= EVBUFFER_CHAIN_MAX_AUTO_SIZE/2) + to_alloc <<= 1; + if (datlen > to_alloc) + to_alloc = datlen; + tmp = evbuffer_chain_new(to_alloc); + if (tmp == NULL) + goto done; + + if (remain) { + memcpy(chain->buffer + chain->misalign + chain->off, + data, remain); + chain->off += remain; + buf->total_len += remain; + buf->n_add_for_cb += remain; + } + + data += remain; + datlen -= remain; + + memcpy(tmp->buffer, data, datlen); + tmp->off = datlen; + evbuffer_chain_insert(buf, tmp); + buf->n_add_for_cb += datlen; + +out: + evbuffer_invoke_callbacks(buf); + result = 0; +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +int +evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen) +{ + struct evbuffer_chain *chain, *tmp; + int result = -1; + + EVBUFFER_LOCK(buf); + + if (buf->freeze_start) { + goto done; + } + + chain = buf->first; + + if (chain == NULL) { + chain = evbuffer_chain_new(datlen); + if (!chain) + goto done; + evbuffer_chain_insert(buf, chain); + } + + /* we cannot touch immutable buffers */ + if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) { + /* If this chain is empty, we can treat it as + * 'empty at the beginning' rather than 'empty at the end' */ + if (chain->off == 0) + chain->misalign = chain->buffer_len; + + if ((size_t)chain->misalign >= datlen) { + /* we have enough space to fit everything */ + memcpy(chain->buffer + chain->misalign - datlen, + data, datlen); + chain->off += datlen; + chain->misalign -= datlen; + buf->total_len += datlen; + buf->n_add_for_cb += datlen; + goto out; + } else if (chain->misalign) { + /* we can only fit some of the data. */ + memcpy(chain->buffer, + (char*)data + datlen - chain->misalign, + (size_t)chain->misalign); + chain->off += (size_t)chain->misalign; + buf->total_len += (size_t)chain->misalign; + buf->n_add_for_cb += (size_t)chain->misalign; + datlen -= (size_t)chain->misalign; + chain->misalign = 0; + } + } + + /* we need to add another chain */ + if ((tmp = evbuffer_chain_new(datlen)) == NULL) + goto done; + buf->first = tmp; + if (buf->last_with_datap == &buf->first) + buf->last_with_datap = &tmp->next; + + tmp->next = chain; + + tmp->off = datlen; + tmp->misalign = tmp->buffer_len - datlen; + + memcpy(tmp->buffer + tmp->misalign, data, datlen); + buf->total_len += datlen; + buf->n_add_for_cb += (size_t)chain->misalign; + +out: + evbuffer_invoke_callbacks(buf); + result = 0; +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +/** Helper: realigns the memory in chain->buffer so that misalign is 0. */ +static void +evbuffer_chain_align(struct evbuffer_chain *chain) +{ + EVUTIL_ASSERT(!(chain->flags & EVBUFFER_IMMUTABLE)); + EVUTIL_ASSERT(!(chain->flags & EVBUFFER_MEM_PINNED_ANY)); + memmove(chain->buffer, chain->buffer + chain->misalign, chain->off); + chain->misalign = 0; +} + +#define MAX_TO_COPY_IN_EXPAND 4096 +#define MAX_TO_REALIGN_IN_EXPAND 2048 + +/** Helper: return true iff we should realign chain to fit datalen bytes of + data in it. */ +static int +evbuffer_chain_should_realign(struct evbuffer_chain *chain, + size_t datlen) +{ + return chain->buffer_len - chain->off >= datlen && + (chain->off < chain->buffer_len / 2) && + (chain->off <= MAX_TO_REALIGN_IN_EXPAND); +} + +/* Expands the available space in the event buffer to at least datlen, all in + * a single chunk. Return that chunk. */ +static struct evbuffer_chain * +evbuffer_expand_singlechain(struct evbuffer *buf, size_t datlen) +{ + struct evbuffer_chain *chain, **chainp; + struct evbuffer_chain *result = NULL; + ASSERT_EVBUFFER_LOCKED(buf); + + chainp = buf->last_with_datap; + + /* XXX If *chainp is no longer writeable, but has enough space in its + * misalign, this might be a bad idea: we could still use *chainp, not + * (*chainp)->next. */ + if (*chainp && CHAIN_SPACE_LEN(*chainp) == 0) + chainp = &(*chainp)->next; + + /* 'chain' now points to the first chain with writable space (if any) + * We will either use it, realign it, replace it, or resize it. */ + chain = *chainp; + + if (chain == NULL || + (chain->flags & (EVBUFFER_IMMUTABLE|EVBUFFER_MEM_PINNED_ANY))) { + /* We can't use the last_with_data chain at all. Just add a + * new one that's big enough. */ + goto insert_new; + } + + /* If we can fit all the data, then we don't have to do anything */ + if (CHAIN_SPACE_LEN(chain) >= datlen) { + result = chain; + goto ok; + } + + /* If the chain is completely empty, just replace it by adding a new + * empty chain. */ + if (chain->off == 0) { + goto insert_new; + } + + /* If the misalignment plus the remaining space fulfills our data + * needs, we could just force an alignment to happen. Afterwards, we + * have enough space. But only do this if we're saving a lot of space + * and not moving too much data. Otherwise the space savings are + * probably offset by the time lost in copying. + */ + if (evbuffer_chain_should_realign(chain, datlen)) { + evbuffer_chain_align(chain); + result = chain; + goto ok; + } + + /* At this point, we can either resize the last chunk with space in + * it, use the next chunk after it, or If we add a new chunk, we waste + * CHAIN_SPACE_LEN(chain) bytes in the former last chunk. If we + * resize, we have to copy chain->off bytes. + */ + + /* Would expanding this chunk be affordable and worthwhile? */ + if (CHAIN_SPACE_LEN(chain) < chain->buffer_len / 8 || + chain->off > MAX_TO_COPY_IN_EXPAND) { + /* It's not worth resizing this chain. Can the next one be + * used? */ + if (chain->next && CHAIN_SPACE_LEN(chain->next) >= datlen) { + /* Yes, we can just use the next chain (which should + * be empty. */ + result = chain->next; + goto ok; + } else { + /* No; append a new chain (which will free all + * terminal empty chains.) */ + goto insert_new; + } + } else { + /* Okay, we're going to try to resize this chain: Not doing so + * would waste at least 1/8 of its current allocation, and we + * can do so without having to copy more than + * MAX_TO_COPY_IN_EXPAND bytes. */ + /* figure out how much space we need */ + size_t length = chain->off + datlen; + struct evbuffer_chain *tmp = evbuffer_chain_new(length); + if (tmp == NULL) + goto err; + + /* copy the data over that we had so far */ + tmp->off = chain->off; + memcpy(tmp->buffer, chain->buffer + chain->misalign, + chain->off); + /* fix up the list */ + EVUTIL_ASSERT(*chainp == chain); + result = *chainp = tmp; + + if (buf->last == chain) + buf->last = tmp; + + tmp->next = chain->next; + evbuffer_chain_free(chain); + goto ok; + } + +insert_new: + result = evbuffer_chain_insert_new(buf, datlen); + if (!result) + goto err; +ok: + EVUTIL_ASSERT(result); + EVUTIL_ASSERT(CHAIN_SPACE_LEN(result) >= datlen); +err: + return result; +} + +/* Make sure that datlen bytes are available for writing in the last n + * chains. Never copies or moves data. */ +int +_evbuffer_expand_fast(struct evbuffer *buf, size_t datlen, int n) +{ + struct evbuffer_chain *chain = buf->last, *tmp, *next; + size_t avail; + int used; + + ASSERT_EVBUFFER_LOCKED(buf); + EVUTIL_ASSERT(n >= 2); + + if (chain == NULL || (chain->flags & EVBUFFER_IMMUTABLE)) { + /* There is no last chunk, or we can't touch the last chunk. + * Just add a new chunk. */ + chain = evbuffer_chain_new(datlen); + if (chain == NULL) + return (-1); + + evbuffer_chain_insert(buf, chain); + return (0); + } + + used = 0; /* number of chains we're using space in. */ + avail = 0; /* how much space they have. */ + /* How many bytes can we stick at the end of buffer as it is? Iterate + * over the chains at the end of the buffer, tring to see how much + * space we have in the first n. */ + for (chain = *buf->last_with_datap; chain; chain = chain->next) { + if (chain->off) { + size_t space = (size_t) CHAIN_SPACE_LEN(chain); + EVUTIL_ASSERT(chain == *buf->last_with_datap); + if (space) { + avail += space; + ++used; + } + } else { + /* No data in chain; realign it. */ + chain->misalign = 0; + avail += chain->buffer_len; + ++used; + } + if (avail >= datlen) { + /* There is already enough space. Just return */ + return (0); + } + if (used == n) + break; + } + + /* There wasn't enough space in the first n chains with space in + * them. Either add a new chain with enough space, or replace all + * empty chains with one that has enough space, depending on n. */ + if (used < n) { + /* The loop ran off the end of the chains before it hit n + * chains; we can add another. */ + EVUTIL_ASSERT(chain == NULL); + + tmp = evbuffer_chain_new(datlen - avail); + if (tmp == NULL) + return (-1); + + buf->last->next = tmp; + buf->last = tmp; + /* (we would only set last_with_data if we added the first + * chain. But if the buffer had no chains, we would have + * just allocated a new chain earlier) */ + return (0); + } else { + /* Nuke _all_ the empty chains. */ + int rmv_all = 0; /* True iff we removed last_with_data. */ + chain = *buf->last_with_datap; + if (!chain->off) { + EVUTIL_ASSERT(chain == buf->first); + rmv_all = 1; + avail = 0; + } else { + avail = (size_t) CHAIN_SPACE_LEN(chain); + chain = chain->next; + } + + + for (; chain; chain = next) { + next = chain->next; + EVUTIL_ASSERT(chain->off == 0); + evbuffer_chain_free(chain); + } + tmp = evbuffer_chain_new(datlen - avail); + if (tmp == NULL) { + if (rmv_all) { + ZERO_CHAIN(buf); + } else { + buf->last = *buf->last_with_datap; + (*buf->last_with_datap)->next = NULL; + } + return (-1); + } + + if (rmv_all) { + buf->first = buf->last = tmp; + buf->last_with_datap = &buf->first; + } else { + (*buf->last_with_datap)->next = tmp; + buf->last = tmp; + } + return (0); + } +} + +int +evbuffer_expand(struct evbuffer *buf, size_t datlen) +{ + struct evbuffer_chain *chain; + + EVBUFFER_LOCK(buf); + chain = evbuffer_expand_singlechain(buf, datlen); + EVBUFFER_UNLOCK(buf); + return chain ? 0 : -1; +} + +/* + * Reads data from a file descriptor into a buffer. + */ + +#if defined(_EVENT_HAVE_SYS_UIO_H) || defined(WIN32) +#define USE_IOVEC_IMPL +#endif + +#ifdef USE_IOVEC_IMPL + +#ifdef _EVENT_HAVE_SYS_UIO_H +/* number of iovec we use for writev, fragmentation is going to determine + * how much we end up writing */ + +#define DEFAULT_WRITE_IOVEC 128 + +#if defined(UIO_MAXIOV) && UIO_MAXIOV < DEFAULT_WRITE_IOVEC +#define NUM_WRITE_IOVEC UIO_MAXIOV +#elif defined(IOV_MAX) && IOV_MAX < DEFAULT_WRITE_IOVEC +#define NUM_WRITE_IOVEC IOV_MAX +#else +#define NUM_WRITE_IOVEC DEFAULT_WRITE_IOVEC +#endif + +#define IOV_TYPE struct iovec +#define IOV_PTR_FIELD iov_base +#define IOV_LEN_FIELD iov_len +#define IOV_LEN_TYPE size_t +#else +#define NUM_WRITE_IOVEC 16 +#define IOV_TYPE WSABUF +#define IOV_PTR_FIELD buf +#define IOV_LEN_FIELD len +#define IOV_LEN_TYPE unsigned long +#endif +#endif +#define NUM_READ_IOVEC 4 + +#define EVBUFFER_MAX_READ 4096 + +/** Helper function to figure out which space to use for reading data into + an evbuffer. Internal use only. + + @param buf The buffer to read into + @param howmuch How much we want to read. + @param vecs An array of two or more iovecs or WSABUFs. + @param n_vecs_avail The length of vecs + @param chainp A pointer to a variable to hold the first chain we're + reading into. + @param exact Boolean: if true, we do not provide more than 'howmuch' + space in the vectors, even if more space is available. + @return The number of buffers we're using. + */ +int +_evbuffer_read_setup_vecs(struct evbuffer *buf, ev_ssize_t howmuch, + struct evbuffer_iovec *vecs, int n_vecs_avail, + struct evbuffer_chain ***chainp, int exact) +{ + struct evbuffer_chain *chain; + struct evbuffer_chain **firstchainp; + size_t so_far; + int i; + ASSERT_EVBUFFER_LOCKED(buf); + + if (howmuch < 0) + return -1; + + so_far = 0; + /* Let firstchain be the first chain with any space on it */ + firstchainp = buf->last_with_datap; + if (CHAIN_SPACE_LEN(*firstchainp) == 0) { + firstchainp = &(*firstchainp)->next; + } + + chain = *firstchainp; + for (i = 0; i < n_vecs_avail && so_far < (size_t)howmuch; ++i) { + size_t avail = (size_t) CHAIN_SPACE_LEN(chain); + if (avail > (howmuch - so_far) && exact) + avail = howmuch - so_far; + vecs[i].iov_base = CHAIN_SPACE_PTR(chain); + vecs[i].iov_len = avail; + so_far += avail; + chain = chain->next; + } + + *chainp = firstchainp; + return i; +} + +static int +get_n_bytes_readable_on_socket(evutil_socket_t fd) +{ +#if defined(FIONREAD) && defined(WIN32) + unsigned long lng = EVBUFFER_MAX_READ; + if (ioctlsocket(fd, FIONREAD, &lng) < 0) + return -1; + return (int)lng; +#elif defined(FIONREAD) + int n = EVBUFFER_MAX_READ; + if (ioctl(fd, FIONREAD, &n) < 0) + return -1; + return n; +#else + return EVBUFFER_MAX_READ; +#endif +} + +/* TODO(niels): should this function return ev_ssize_t and take ev_ssize_t + * as howmuch? */ +int +evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) +{ + struct evbuffer_chain **chainp; + int n; + int result; + +#ifdef USE_IOVEC_IMPL + int nvecs, i, remaining; +#else + struct evbuffer_chain *chain; + unsigned char *p; +#endif + + EVBUFFER_LOCK(buf); + + if (buf->freeze_end) { + result = -1; + goto done; + } + + n = get_n_bytes_readable_on_socket(fd); + if (n <= 0 || n > EVBUFFER_MAX_READ) + n = EVBUFFER_MAX_READ; + if (howmuch < 0 || howmuch > n) + howmuch = n; + +#ifdef USE_IOVEC_IMPL + /* Since we can use iovecs, we're willing to use the last + * NUM_READ_IOVEC chains. */ + if (_evbuffer_expand_fast(buf, howmuch, NUM_READ_IOVEC) == -1) { + result = -1; + goto done; + } else { + IOV_TYPE vecs[NUM_READ_IOVEC]; +#ifdef _EVBUFFER_IOVEC_IS_NATIVE + nvecs = _evbuffer_read_setup_vecs(buf, howmuch, vecs, + NUM_READ_IOVEC, &chainp, 1); +#else + /* We aren't using the native struct iovec. Therefore, + we are on win32. */ + struct evbuffer_iovec ev_vecs[NUM_READ_IOVEC]; + nvecs = _evbuffer_read_setup_vecs(buf, howmuch, ev_vecs, 2, + &chainp, 1); + + for (i=0; i < nvecs; ++i) + WSABUF_FROM_EVBUFFER_IOV(&vecs[i], &ev_vecs[i]); +#endif + +#ifdef WIN32 + { + DWORD bytesRead; + DWORD flags=0; + if (WSARecv(fd, vecs, nvecs, &bytesRead, &flags, NULL, NULL)) { + /* The read failed. It might be a close, + * or it might be an error. */ + if (WSAGetLastError() == WSAECONNABORTED) + n = 0; + else + n = -1; + } else + n = bytesRead; + } +#else + n = readv(fd, vecs, nvecs); +#endif + } + +#else /*!USE_IOVEC_IMPL*/ + /* If we don't have FIONREAD, we might waste some space here */ + /* XXX we _will_ waste some space here if there is any space left + * over on buf->last. */ + if ((chain = evbuffer_expand_singlechain(buf, howmuch)) == NULL) { + result = -1; + goto done; + } + + /* We can append new data at this point */ + p = chain->buffer + chain->misalign + chain->off; + +#ifndef WIN32 + n = read(fd, p, howmuch); +#else + n = recv(fd, p, howmuch, 0); +#endif +#endif /* USE_IOVEC_IMPL */ + + if (n == -1) { + result = -1; + goto done; + } + if (n == 0) { + result = 0; + goto done; + } + +#ifdef USE_IOVEC_IMPL + remaining = n; + for (i=0; i < nvecs; ++i) { + ev_ssize_t space = (ev_ssize_t) CHAIN_SPACE_LEN(*chainp); + if (space < remaining) { + (*chainp)->off += space; + remaining -= (int)space; + } else { + (*chainp)->off += remaining; + buf->last_with_datap = chainp; + break; + } + chainp = &(*chainp)->next; + } +#else + chain->off += n; + advance_last_with_data(buf); +#endif + buf->total_len += n; + buf->n_add_for_cb += n; + + /* Tell someone about changes in this buffer */ + evbuffer_invoke_callbacks(buf); + result = n; +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +#ifdef WIN32 +static int +evbuffer_readfile(struct evbuffer *buf, evutil_socket_t fd, ev_ssize_t howmuch) +{ + int result; + int nchains, n; + struct evbuffer_iovec v[2]; + + EVBUFFER_LOCK(buf); + + if (buf->freeze_end) { + result = -1; + goto done; + } + + if (howmuch < 0) + howmuch = 16384; + + + /* XXX we _will_ waste some space here if there is any space left + * over on buf->last. */ + nchains = evbuffer_reserve_space(buf, howmuch, v, 2); + if (nchains < 1 || nchains > 2) { + result = -1; + goto done; + } + n = read((int)fd, v[0].iov_base, (unsigned int)v[0].iov_len); + if (n <= 0) { + result = n; + goto done; + } + v[0].iov_len = (IOV_LEN_TYPE) n; /* XXXX another problem with big n.*/ + if (nchains > 1) { + n = read((int)fd, v[1].iov_base, (unsigned int)v[1].iov_len); + if (n <= 0) { + result = (unsigned long) v[0].iov_len; + evbuffer_commit_space(buf, v, 1); + goto done; + } + v[1].iov_len = n; + } + evbuffer_commit_space(buf, v, nchains); + + result = n; +done: + EVBUFFER_UNLOCK(buf); + return result; +} +#endif + +#ifdef USE_IOVEC_IMPL +static inline int +evbuffer_write_iovec(struct evbuffer *buffer, evutil_socket_t fd, + ev_ssize_t howmuch) +{ + IOV_TYPE iov[NUM_WRITE_IOVEC]; + struct evbuffer_chain *chain = buffer->first; + int n, i = 0; + + if (howmuch < 0) + return -1; + + ASSERT_EVBUFFER_LOCKED(buffer); + /* XXX make this top out at some maximal data length? if the + * buffer has (say) 1MB in it, split over 128 chains, there's + * no way it all gets written in one go. */ + while (chain != NULL && i < NUM_WRITE_IOVEC && howmuch) { +#ifdef USE_SENDFILE + /* we cannot write the file info via writev */ + if (chain->flags & EVBUFFER_SENDFILE) + break; +#endif + iov[i].IOV_PTR_FIELD = (void *) (chain->buffer + chain->misalign); + if ((size_t)howmuch >= chain->off) { + /* XXXcould be problematic when windows supports mmap*/ + iov[i++].IOV_LEN_FIELD = (IOV_LEN_TYPE)chain->off; + howmuch -= chain->off; + } else { + /* XXXcould be problematic when windows supports mmap*/ + iov[i++].IOV_LEN_FIELD = (IOV_LEN_TYPE)howmuch; + break; + } + chain = chain->next; + } +#ifdef WIN32 + { + DWORD bytesSent; + if (WSASend(fd, iov, i, &bytesSent, 0, NULL, NULL)) + n = -1; + else + n = bytesSent; + } +#else + n = writev(fd, iov, i); +#endif + return (n); +} +#endif + +#ifdef USE_SENDFILE +static inline int +evbuffer_write_sendfile(struct evbuffer *buffer, evutil_socket_t fd, + ev_ssize_t howmuch) +{ + struct evbuffer_chain *chain = buffer->first; + struct evbuffer_chain_fd *info = + EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_fd, chain); +#if defined(SENDFILE_IS_MACOSX) || defined(SENDFILE_IS_FREEBSD) + int res; + off_t len = chain->off; +#elif defined(SENDFILE_IS_LINUX) || defined(SENDFILE_IS_SOLARIS) + ev_ssize_t res; + off_t offset = chain->misalign; +#endif + + ASSERT_EVBUFFER_LOCKED(buffer); + +#if defined(SENDFILE_IS_MACOSX) + res = sendfile(info->fd, fd, chain->misalign, &len, NULL, 0); + if (res == -1 && !EVUTIL_ERR_RW_RETRIABLE(errno)) + return (-1); + + return (len); +#elif defined(SENDFILE_IS_FREEBSD) + res = sendfile(info->fd, fd, chain->misalign, chain->off, NULL, &len, 0); + if (res == -1 && !EVUTIL_ERR_RW_RETRIABLE(errno)) + return (-1); + + return (len); +#elif defined(SENDFILE_IS_LINUX) + /* TODO(niels): implement splice */ + res = sendfile(fd, info->fd, &offset, chain->off); + if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) { + /* if this is EAGAIN or EINTR return 0; otherwise, -1 */ + return (0); + } + return (res); +#elif defined(SENDFILE_IS_SOLARIS) + { + const off_t offset_orig = offset; + res = sendfile(fd, info->fd, &offset, chain->off); + if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) { + if (offset - offset_orig) + return offset - offset_orig; + /* if this is EAGAIN or EINTR and no bytes were + * written, return 0 */ + return (0); + } + return (res); + } +#endif +} +#endif + +int +evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd, + ev_ssize_t howmuch) +{ + int n = -1; + + EVBUFFER_LOCK(buffer); + + if (buffer->freeze_start) { + goto done; + } + + if (howmuch < 0 || (size_t)howmuch > buffer->total_len) + howmuch = buffer->total_len; + + if (howmuch > 0) { +#ifdef USE_SENDFILE + struct evbuffer_chain *chain = buffer->first; + if (chain != NULL && (chain->flags & EVBUFFER_SENDFILE)) + n = evbuffer_write_sendfile(buffer, fd, howmuch); + else { +#endif +#ifdef USE_IOVEC_IMPL + n = evbuffer_write_iovec(buffer, fd, howmuch); +#elif defined(WIN32) + /* XXX(nickm) Don't disable this code until we know if + * the WSARecv code above works. */ + void *p = evbuffer_pullup(buffer, howmuch); + n = send(fd, p, howmuch, 0); +#else + void *p = evbuffer_pullup(buffer, howmuch); + n = write(fd, p, howmuch); +#endif +#ifdef USE_SENDFILE + } +#endif + } + + if (n > 0) + evbuffer_drain(buffer, n); + +done: + EVBUFFER_UNLOCK(buffer); + return (n); +} + +int +evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd) +{ + return evbuffer_write_atmost(buffer, fd, -1); +} + +unsigned char * +evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len) +{ + unsigned char *search; + struct evbuffer_ptr ptr; + + EVBUFFER_LOCK(buffer); + + ptr = evbuffer_search(buffer, (const char *)what, len, NULL); + if (ptr.pos < 0) { + search = NULL; + } else { + search = evbuffer_pullup(buffer, ptr.pos + len); + if (search) + search += ptr.pos; + } + EVBUFFER_UNLOCK(buffer); + return search; +} + +int +evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos, + size_t position, enum evbuffer_ptr_how how) +{ + size_t left = position; + struct evbuffer_chain *chain = NULL; + + EVBUFFER_LOCK(buf); + + switch (how) { + case EVBUFFER_PTR_SET: + chain = buf->first; + pos->pos = position; + position = 0; + break; + case EVBUFFER_PTR_ADD: + /* this avoids iterating over all previous chains if + we just want to advance the position */ + chain = pos->_internal.chain; + pos->pos += position; + position = pos->_internal.pos_in_chain; + break; + } + + while (chain && position + left >= chain->off) { + left -= chain->off - position; + chain = chain->next; + position = 0; + } + if (chain) { + pos->_internal.chain = chain; + pos->_internal.pos_in_chain = position + left; + } else { + pos->_internal.chain = NULL; + pos->pos = -1; + } + + EVBUFFER_UNLOCK(buf); + + return chain != NULL ? 0 : -1; +} + +/** + Compare the bytes in buf at position pos to the len bytes in mem. Return + less than 0, 0, or greater than 0 as memcmp. + */ +static int +evbuffer_ptr_memcmp(const struct evbuffer *buf, const struct evbuffer_ptr *pos, + const char *mem, size_t len) +{ + struct evbuffer_chain *chain; + size_t position; + int r; + + ASSERT_EVBUFFER_LOCKED(buf); + + if (pos->pos + len > buf->total_len) + return -1; + + chain = pos->_internal.chain; + position = pos->_internal.pos_in_chain; + while (len && chain) { + size_t n_comparable; + if (len + position > chain->off) + n_comparable = chain->off - position; + else + n_comparable = len; + r = memcmp(chain->buffer + chain->misalign + position, mem, + n_comparable); + if (r) + return r; + mem += n_comparable; + len -= n_comparable; + position = 0; + chain = chain->next; + } + + return 0; +} + +struct evbuffer_ptr +evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start) +{ + return evbuffer_search_range(buffer, what, len, start, NULL); +} + +struct evbuffer_ptr +evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end) +{ + struct evbuffer_ptr pos; + struct evbuffer_chain *chain, *last_chain = NULL; + const unsigned char *p; + char first; + + EVBUFFER_LOCK(buffer); + + if (start) { + memcpy(&pos, start, sizeof(pos)); + chain = pos._internal.chain; + } else { + pos.pos = 0; + chain = pos._internal.chain = buffer->first; + pos._internal.pos_in_chain = 0; + } + + if (end) + last_chain = end->_internal.chain; + + if (!len || len > EV_SSIZE_MAX) + goto done; + + first = what[0]; + + while (chain) { + const unsigned char *start_at = + chain->buffer + chain->misalign + + pos._internal.pos_in_chain; + p = memchr(start_at, first, + chain->off - pos._internal.pos_in_chain); + if (p) { + pos.pos += p - start_at; + pos._internal.pos_in_chain += p - start_at; + if (!evbuffer_ptr_memcmp(buffer, &pos, what, len)) { + if (end && pos.pos + (ev_ssize_t)len > end->pos) + goto not_found; + else + goto done; + } + ++pos.pos; + ++pos._internal.pos_in_chain; + if (pos._internal.pos_in_chain == chain->off) { + chain = pos._internal.chain = chain->next; + pos._internal.pos_in_chain = 0; + } + } else { + if (chain == last_chain) + goto not_found; + pos.pos += chain->off - pos._internal.pos_in_chain; + chain = pos._internal.chain = chain->next; + pos._internal.pos_in_chain = 0; + } + } + +not_found: + pos.pos = -1; + pos._internal.chain = NULL; +done: + EVBUFFER_UNLOCK(buffer); + return pos; +} + +int +evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len, + struct evbuffer_ptr *start_at, + struct evbuffer_iovec *vec, int n_vec) +{ + struct evbuffer_chain *chain; + int idx = 0; + ev_ssize_t len_so_far = 0; + + EVBUFFER_LOCK(buffer); + + if (start_at) { + chain = start_at->_internal.chain; + len_so_far = chain->off + - start_at->_internal.pos_in_chain; + idx = 1; + if (n_vec > 0) { + vec[0].iov_base = chain->buffer + chain->misalign + + start_at->_internal.pos_in_chain; + vec[0].iov_len = len_so_far; + } + chain = chain->next; + } else { + chain = buffer->first; + } + + if (n_vec == 0 && len < 0) { + /* If no vectors are provided and they asked for "everything", + * pretend they asked for the actual available amount. */ + len = buffer->total_len - len_so_far; + } + + while (chain) { + if (len >= 0 && len_so_far >= len) + break; + if (idxbuffer + chain->misalign; + vec[idx].iov_len = chain->off; + } else if (len<0) { + break; + } + ++idx; + len_so_far += chain->off; + chain = chain->next; + } + + EVBUFFER_UNLOCK(buffer); + + return idx; +} + + +int +evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) +{ + char *buffer; + size_t space; + int sz, result = -1; + va_list aq; + struct evbuffer_chain *chain; + + + EVBUFFER_LOCK(buf); + + if (buf->freeze_end) { + goto done; + } + + /* make sure that at least some space is available */ + if ((chain = evbuffer_expand_singlechain(buf, 64)) == NULL) + goto done; + + for (;;) { +#if 0 + size_t used = chain->misalign + chain->off; + buffer = (char *)chain->buffer + chain->misalign + chain->off; + EVUTIL_ASSERT(chain->buffer_len >= used); + space = chain->buffer_len - used; +#endif + buffer = (char*) CHAIN_SPACE_PTR(chain); + space = (size_t) CHAIN_SPACE_LEN(chain); + +#ifndef va_copy +#define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list)) +#endif + va_copy(aq, ap); + + sz = evutil_vsnprintf(buffer, space, fmt, aq); + + va_end(aq); + + if (sz < 0) + goto done; + if ((size_t)sz < space) { + chain->off += sz; + buf->total_len += sz; + buf->n_add_for_cb += sz; + + advance_last_with_data(buf); + evbuffer_invoke_callbacks(buf); + result = sz; + goto done; + } + if ((chain = evbuffer_expand_singlechain(buf, sz + 1)) == NULL) + goto done; + } + /* NOTREACHED */ + +done: + EVBUFFER_UNLOCK(buf); + return result; +} + +int +evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) +{ + int res = -1; + va_list ap; + + va_start(ap, fmt); + res = evbuffer_add_vprintf(buf, fmt, ap); + va_end(ap); + + return (res); +} + +int +evbuffer_add_reference(struct evbuffer *outbuf, + const void *data, size_t datlen, + evbuffer_ref_cleanup_cb cleanupfn, void *extra) +{ + struct evbuffer_chain *chain; + struct evbuffer_chain_reference *info; + int result = -1; + + chain = evbuffer_chain_new(sizeof(struct evbuffer_chain_reference)); + if (!chain) + return (-1); + chain->flags |= EVBUFFER_REFERENCE | EVBUFFER_IMMUTABLE; + chain->buffer = (u_char *)data; + chain->buffer_len = datlen; + chain->off = datlen; + + info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_reference, chain); + info->cleanupfn = cleanupfn; + info->extra = extra; + + EVBUFFER_LOCK(outbuf); + if (outbuf->freeze_end) { + /* don't call chain_free; we do not want to actually invoke + * the cleanup function */ + mm_free(chain); + goto done; + } + evbuffer_chain_insert(outbuf, chain); + outbuf->n_add_for_cb += datlen; + + evbuffer_invoke_callbacks(outbuf); + + result = 0; +done: + EVBUFFER_UNLOCK(outbuf); + + return result; +} + +/* TODO(niels): maybe we don't want to own the fd, however, in that + * case, we should dup it - dup is cheap. Perhaps, we should use a + * callback instead? + */ +/* TODO(niels): we may want to add to automagically convert to mmap, in + * case evbuffer_remove() or evbuffer_pullup() are being used. + */ +int +evbuffer_add_file(struct evbuffer *outbuf, int fd, + ev_off_t offset, ev_off_t length) +{ +#if defined(USE_SENDFILE) || defined(_EVENT_HAVE_MMAP) + struct evbuffer_chain *chain; + struct evbuffer_chain_fd *info; +#endif +#if defined(USE_SENDFILE) + int sendfile_okay = 1; +#endif + int ok = 1; + +#if defined(USE_SENDFILE) + if (use_sendfile) { + EVBUFFER_LOCK(outbuf); + sendfile_okay = outbuf->flags & EVBUFFER_FLAG_DRAINS_TO_FD; + EVBUFFER_UNLOCK(outbuf); + } + + if (use_sendfile && sendfile_okay) { + chain = evbuffer_chain_new(sizeof(struct evbuffer_chain_fd)); + if (chain == NULL) { + event_warn("%s: out of memory", __func__); + return (-1); + } + + chain->flags |= EVBUFFER_SENDFILE | EVBUFFER_IMMUTABLE; + chain->buffer = NULL; /* no reading possible */ + chain->buffer_len = length + offset; + chain->off = length; + chain->misalign = offset; + + info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_fd, chain); + info->fd = fd; + + EVBUFFER_LOCK(outbuf); + if (outbuf->freeze_end) { + mm_free(chain); + ok = 0; + } else { + outbuf->n_add_for_cb += length; + evbuffer_chain_insert(outbuf, chain); + } + } else +#endif +#if defined(_EVENT_HAVE_MMAP) + if (use_mmap) { + void *mapped = mmap(NULL, length + offset, PROT_READ, +#ifdef MAP_NOCACHE + MAP_NOCACHE | +#endif +#ifdef MAP_FILE + MAP_FILE | +#endif + MAP_PRIVATE, + fd, 0); + /* some mmap implementations require offset to be a multiple of + * the page size. most users of this api, are likely to use 0 + * so mapping everything is not likely to be a problem. + * TODO(niels): determine page size and round offset to that + * page size to avoid mapping too much memory. + */ + if (mapped == MAP_FAILED) { + event_warn("%s: mmap(%d, %d, %zu) failed", + __func__, fd, 0, (size_t)(offset + length)); + return (-1); + } + chain = evbuffer_chain_new(sizeof(struct evbuffer_chain_fd)); + if (chain == NULL) { + event_warn("%s: out of memory", __func__); + munmap(mapped, length); + return (-1); + } + + chain->flags |= EVBUFFER_MMAP | EVBUFFER_IMMUTABLE; + chain->buffer = mapped; + chain->buffer_len = length + offset; + chain->off = length + offset; + + info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_fd, chain); + info->fd = fd; + + EVBUFFER_LOCK(outbuf); + if (outbuf->freeze_end) { + info->fd = -1; + evbuffer_chain_free(chain); + ok = 0; + } else { + outbuf->n_add_for_cb += length; + + evbuffer_chain_insert(outbuf, chain); + + /* we need to subtract whatever we don't need */ + evbuffer_drain(outbuf, offset); + } + } else +#endif + { + /* the default implementation */ + struct evbuffer *tmp = evbuffer_new(); + ev_ssize_t read; + + if (tmp == NULL) + return (-1); + +#ifdef WIN32 +#define lseek _lseeki64 +#endif + if (lseek(fd, offset, SEEK_SET) == -1) { + evbuffer_free(tmp); + return (-1); + } + + /* we add everything to a temporary buffer, so that we + * can abort without side effects if the read fails. + */ + while (length) { + read = evbuffer_readfile(tmp, fd, (ev_ssize_t)length); + if (read == -1) { + evbuffer_free(tmp); + return (-1); + } + + length -= read; + } + + EVBUFFER_LOCK(outbuf); + if (outbuf->freeze_end) { + evbuffer_free(tmp); + ok = 0; + } else { + evbuffer_add_buffer(outbuf, tmp); + evbuffer_free(tmp); + +#ifdef WIN32 +#define close _close +#endif + close(fd); + } + } + + if (ok) + evbuffer_invoke_callbacks(outbuf); + EVBUFFER_UNLOCK(outbuf); + + return ok ? 0 : -1; +} + + +void +evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg) +{ + EVBUFFER_LOCK(buffer); + + if (!TAILQ_EMPTY(&buffer->callbacks)) + evbuffer_remove_all_callbacks(buffer); + + if (cb) { + struct evbuffer_cb_entry *ent = + evbuffer_add_cb(buffer, NULL, cbarg); + ent->cb.cb_obsolete = cb; + ent->flags |= EVBUFFER_CB_OBSOLETE; + } + EVBUFFER_UNLOCK(buffer); +} + +struct evbuffer_cb_entry * +evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg) +{ + struct evbuffer_cb_entry *e; + if (! (e = mm_calloc(1, sizeof(struct evbuffer_cb_entry)))) + return NULL; + EVBUFFER_LOCK(buffer); + e->cb.cb_func = cb; + e->cbarg = cbarg; + e->flags = EVBUFFER_CB_ENABLED; + TAILQ_INSERT_HEAD(&buffer->callbacks, e, next); + EVBUFFER_UNLOCK(buffer); + return e; +} + +int +evbuffer_remove_cb_entry(struct evbuffer *buffer, + struct evbuffer_cb_entry *ent) +{ + EVBUFFER_LOCK(buffer); + TAILQ_REMOVE(&buffer->callbacks, ent, next); + EVBUFFER_UNLOCK(buffer); + mm_free(ent); + return 0; +} + +int +evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg) +{ + struct evbuffer_cb_entry *cbent; + int result = -1; + EVBUFFER_LOCK(buffer); + TAILQ_FOREACH(cbent, &buffer->callbacks, next) { + if (cb == cbent->cb.cb_func && cbarg == cbent->cbarg) { + result = evbuffer_remove_cb_entry(buffer, cbent); + goto done; + } + } +done: + EVBUFFER_UNLOCK(buffer); + return result; +} + +int +evbuffer_cb_set_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags) +{ + /* the user isn't allowed to mess with these. */ + flags &= ~EVBUFFER_CB_INTERNAL_FLAGS; + EVBUFFER_LOCK(buffer); + cb->flags |= flags; + EVBUFFER_UNLOCK(buffer); + return 0; +} + +int +evbuffer_cb_clear_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags) +{ + /* the user isn't allowed to mess with these. */ + flags &= ~EVBUFFER_CB_INTERNAL_FLAGS; + EVBUFFER_LOCK(buffer); + cb->flags &= ~flags; + EVBUFFER_UNLOCK(buffer); + return 0; +} + +int +evbuffer_freeze(struct evbuffer *buffer, int start) +{ + EVBUFFER_LOCK(buffer); + if (start) + buffer->freeze_start = 1; + else + buffer->freeze_end = 1; + EVBUFFER_UNLOCK(buffer); + return 0; +} + +int +evbuffer_unfreeze(struct evbuffer *buffer, int start) +{ + EVBUFFER_LOCK(buffer); + if (start) + buffer->freeze_start = 0; + else + buffer->freeze_end = 0; + EVBUFFER_UNLOCK(buffer); + return 0; +} + +#if 0 +void +evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb) +{ + if (!(cb->flags & EVBUFFER_CB_SUSPENDED)) { + cb->size_before_suspend = evbuffer_get_length(buffer); + cb->flags |= EVBUFFER_CB_SUSPENDED; + } +} + +void +evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb) +{ + if ((cb->flags & EVBUFFER_CB_SUSPENDED)) { + unsigned call = (cb->flags & EVBUFFER_CB_CALL_ON_UNSUSPEND); + size_t sz = cb->size_before_suspend; + cb->flags &= ~(EVBUFFER_CB_SUSPENDED| + EVBUFFER_CB_CALL_ON_UNSUSPEND); + cb->size_before_suspend = 0; + if (call && (cb->flags & EVBUFFER_CB_ENABLED)) { + cb->cb(buffer, sz, evbuffer_get_length(buffer), cb->cbarg); + } + } +} +#endif + +/* These hooks are exposed so that the unit tests can temporarily disable + * sendfile support in order to test mmap, or both to test linear + * access. Don't use it; if we need to add a way to disable sendfile support + * in the future, it will probably be via an alternate version of + * evbuffer_add_file() with a 'flags' argument. + */ +int _evbuffer_testing_use_sendfile(void); +int _evbuffer_testing_use_mmap(void); +int _evbuffer_testing_use_linear_file_access(void); + +int +_evbuffer_testing_use_sendfile(void) +{ + int ok = 0; +#ifdef USE_SENDFILE + use_sendfile = 1; + ok = 1; +#endif +#ifdef _EVENT_HAVE_MMAP + use_mmap = 0; +#endif + return ok; +} +int +_evbuffer_testing_use_mmap(void) +{ + int ok = 0; +#ifdef USE_SENDFILE + use_sendfile = 0; +#endif +#ifdef _EVENT_HAVE_MMAP + use_mmap = 1; + ok = 1; +#endif + return ok; +} +int +_evbuffer_testing_use_linear_file_access(void) +{ +#ifdef USE_SENDFILE + use_sendfile = 0; +#endif +#ifdef _EVENT_HAVE_MMAP + use_mmap = 0; +#endif + return 1; +} diff --git a/libevent/buffer_iocp.c b/libevent/buffer_iocp.c new file mode 100644 index 0000000..5d5303e --- /dev/null +++ b/libevent/buffer_iocp.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +/** + @file buffer_iocp.c + + This module implements overlapped read and write functions for evbuffer + objects on Windows. +*/ + +#include "event2/buffer.h" +#include "event2/buffer_compat.h" +#include "event2/util.h" +#include "event2/thread.h" +#include "event2/event-config.h" +#include "util-internal.h" +#include "evthread-internal.h" +#include "evbuffer-internal.h" +#include "iocp-internal.h" +#include "mm-internal.h" + +#include +#include +#include + +#define MAX_WSABUFS 16 + +/** An evbuffer that can handle overlapped IO. */ +struct evbuffer_overlapped { + struct evbuffer buffer; + /** The socket that we're doing overlapped IO on. */ + evutil_socket_t fd; + + /** pending I/O type */ + unsigned read_in_progress : 1; + unsigned write_in_progress : 1; + + /** The first pinned chain in the buffer. */ + struct evbuffer_chain *first_pinned; + + /** How many chains are pinned; how many of the fields in buffers + * are we using. */ + int n_buffers; + WSABUF buffers[MAX_WSABUFS]; +}; + +/** Given an evbuffer, return the correponding evbuffer structure, or NULL if + * the evbuffer isn't overlapped. */ +static inline struct evbuffer_overlapped * +upcast_evbuffer(struct evbuffer *buf) +{ + if (!buf || !buf->is_overlapped) + return NULL; + return EVUTIL_UPCAST(buf, struct evbuffer_overlapped, buffer); +} + +/** Unpin all the chains noted as pinned in 'eo'. */ +static void +pin_release(struct evbuffer_overlapped *eo, unsigned flag) +{ + int i; + struct evbuffer_chain *next, *chain = eo->first_pinned; + + for (i = 0; i < eo->n_buffers; ++i) { + EVUTIL_ASSERT(chain); + next = chain->next; + _evbuffer_chain_unpin(chain, flag); + chain = next; + } +} + +void +evbuffer_commit_read(struct evbuffer *evbuf, ev_ssize_t nBytes) +{ + struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf); + struct evbuffer_chain **chainp; + size_t remaining, len; + unsigned i; + + EVBUFFER_LOCK(evbuf); + EVUTIL_ASSERT(buf->read_in_progress && !buf->write_in_progress); + EVUTIL_ASSERT(nBytes >= 0); /* XXXX Can this be false? */ + + evbuffer_unfreeze(evbuf, 0); + + chainp = evbuf->last_with_datap; + if (!((*chainp)->flags & EVBUFFER_MEM_PINNED_R)) + chainp = &(*chainp)->next; + remaining = nBytes; + for (i = 0; remaining > 0 && i < (unsigned)buf->n_buffers; ++i) { + EVUTIL_ASSERT(*chainp); + len = buf->buffers[i].len; + if (remaining < len) + len = remaining; + (*chainp)->off += len; + evbuf->last_with_datap = chainp; + remaining -= len; + chainp = &(*chainp)->next; + } + + pin_release(buf, EVBUFFER_MEM_PINNED_R); + + buf->read_in_progress = 0; + + evbuf->total_len += nBytes; + evbuf->n_add_for_cb += nBytes; + + evbuffer_invoke_callbacks(evbuf); + + _evbuffer_decref_and_unlock(evbuf); +} + +void +evbuffer_commit_write(struct evbuffer *evbuf, ev_ssize_t nBytes) +{ + struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf); + + EVBUFFER_LOCK(evbuf); + EVUTIL_ASSERT(buf->write_in_progress && !buf->read_in_progress); + evbuffer_unfreeze(evbuf, 1); + evbuffer_drain(evbuf, nBytes); + pin_release(buf,EVBUFFER_MEM_PINNED_W); + buf->write_in_progress = 0; + _evbuffer_decref_and_unlock(evbuf); +} + +struct evbuffer * +evbuffer_overlapped_new(evutil_socket_t fd) +{ + struct evbuffer_overlapped *evo; + + evo = mm_calloc(1, sizeof(struct evbuffer_overlapped)); + if (!evo) + return NULL; + + TAILQ_INIT(&evo->buffer.callbacks); + evo->buffer.refcnt = 1; + evo->buffer.last_with_datap = &evo->buffer.first; + + evo->buffer.is_overlapped = 1; + evo->fd = fd; + + return &evo->buffer; +} + +int +evbuffer_launch_write(struct evbuffer *buf, ev_ssize_t at_most, + struct event_overlapped *ol) +{ + struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf); + int r = -1; + int i; + struct evbuffer_chain *chain; + DWORD bytesSent; + + if (!buf) { + /* No buffer, or it isn't overlapped */ + return -1; + } + + EVBUFFER_LOCK(buf); + EVUTIL_ASSERT(!buf_o->read_in_progress); + if (buf->freeze_start || buf_o->write_in_progress) + goto done; + if (!buf->total_len) { + /* Nothing to write */ + r = 0; + goto done; + } else if (at_most < 0 || (size_t)at_most > buf->total_len) { + at_most = buf->total_len; + } + evbuffer_freeze(buf, 1); + + buf_o->first_pinned = NULL; + buf_o->n_buffers = 0; + memset(buf_o->buffers, 0, sizeof(buf_o->buffers)); + + chain = buf_o->first_pinned = buf->first; + + for (i=0; i < MAX_WSABUFS && chain; ++i, chain=chain->next) { + WSABUF *b = &buf_o->buffers[i]; + b->buf = (char*)( chain->buffer + chain->misalign ); + _evbuffer_chain_pin(chain, EVBUFFER_MEM_PINNED_W); + + if ((size_t)at_most > chain->off) { + /* XXXX Cast is safe for now, since win32 has no + mmaped chains. But later, we need to have this + add more WSAbufs if chain->off is greater than + ULONG_MAX */ + b->len = (unsigned long)chain->off; + at_most -= chain->off; + } else { + b->len = (unsigned long)at_most; + ++i; + break; + } + } + + buf_o->n_buffers = i; + _evbuffer_incref(buf); + if (WSASend(buf_o->fd, buf_o->buffers, i, &bytesSent, 0, + &ol->overlapped, NULL)) { + int error = WSAGetLastError(); + if (error != WSA_IO_PENDING) { + /* An actual error. */ + pin_release(buf_o, EVBUFFER_MEM_PINNED_W); + evbuffer_unfreeze(buf, 1); + evbuffer_free(buf); /* decref */ + goto done; + } + } + + buf_o->write_in_progress = 1; + r = 0; +done: + EVBUFFER_UNLOCK(buf); + return r; +} + +int +evbuffer_launch_read(struct evbuffer *buf, size_t at_most, + struct event_overlapped *ol) +{ + struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf); + int r = -1, i; + int nvecs; + int npin=0; + struct evbuffer_chain *chain=NULL, **chainp; + DWORD bytesRead; + DWORD flags = 0; + struct evbuffer_iovec vecs[MAX_WSABUFS]; + + if (!buf_o) + return -1; + EVBUFFER_LOCK(buf); + EVUTIL_ASSERT(!buf_o->write_in_progress); + if (buf->freeze_end || buf_o->read_in_progress) + goto done; + + buf_o->first_pinned = NULL; + buf_o->n_buffers = 0; + memset(buf_o->buffers, 0, sizeof(buf_o->buffers)); + + if (_evbuffer_expand_fast(buf, at_most, MAX_WSABUFS) == -1) + goto done; + evbuffer_freeze(buf, 0); + + nvecs = _evbuffer_read_setup_vecs(buf, at_most, + vecs, MAX_WSABUFS, &chainp, 1); + for (i=0;ibuffers[i], + &vecs[i]); + } + + buf_o->n_buffers = nvecs; + buf_o->first_pinned = chain = *chainp; + + npin=0; + for ( ; chain; chain = chain->next) { + _evbuffer_chain_pin(chain, EVBUFFER_MEM_PINNED_R); + ++npin; + } + EVUTIL_ASSERT(npin == nvecs); + + _evbuffer_incref(buf); + if (WSARecv(buf_o->fd, buf_o->buffers, nvecs, &bytesRead, &flags, + &ol->overlapped, NULL)) { + int error = WSAGetLastError(); + if (error != WSA_IO_PENDING) { + /* An actual error. */ + pin_release(buf_o, EVBUFFER_MEM_PINNED_R); + evbuffer_unfreeze(buf, 0); + evbuffer_free(buf); /* decref */ + goto done; + } + } + + buf_o->read_in_progress = 1; + r = 0; +done: + EVBUFFER_UNLOCK(buf); + return r; +} + +evutil_socket_t +_evbuffer_overlapped_get_fd(struct evbuffer *buf) +{ + struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf); + return buf_o ? buf_o->fd : -1; +} + +void +_evbuffer_overlapped_set_fd(struct evbuffer *buf, evutil_socket_t fd) +{ + struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf); + EVBUFFER_LOCK(buf); + /* XXX is this right?, should it cancel current I/O operations? */ + if (buf_o) + buf_o->fd = fd; + EVBUFFER_UNLOCK(buf); +} diff --git a/libevent/bufferevent-internal.h b/libevent/bufferevent-internal.h new file mode 100644 index 0000000..8348ab7 --- /dev/null +++ b/libevent/bufferevent-internal.h @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _BUFFEREVENT_INTERNAL_H_ +#define _BUFFEREVENT_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event2/event-config.h" +#include "event2/util.h" +#include "defer-internal.h" +#include "evthread-internal.h" +#include "event2/thread.h" +#include "ratelim-internal.h" +#include "event2/bufferevent_struct.h" + +/* These flags are reasons that we might be declining to actually enable + reading or writing on a bufferevent. + */ + +/* On a all bufferevents, for reading: used when we have read up to the + watermark value. + + On a filtering bufferevent, for writing: used when the underlying + bufferevent's write buffer has been filled up to its watermark + value. +*/ +#define BEV_SUSPEND_WM 0x01 +/* On a base bufferevent: when we have emptied a bandwidth buckets */ +#define BEV_SUSPEND_BW 0x02 +/* On a base bufferevent: when we have emptied the group's bandwidth bucket. */ +#define BEV_SUSPEND_BW_GROUP 0x04 +/* On a socket bufferevent: can't do any operations while we're waiting for + * name lookup to finish. */ +#define BEV_SUSPEND_LOOKUP 0x08 +/* On a base bufferevent, for reading: used when a filter has choked this + * (underlying) bufferevent because it has stopped reading from it. */ +#define BEV_SUSPEND_FILT_READ 0x10 + +typedef ev_uint16_t bufferevent_suspend_flags; + +struct bufferevent_rate_limit_group { + /** List of all members in the group */ + TAILQ_HEAD(rlim_group_member_list, bufferevent_private) members; + /** Current limits for the group. */ + struct ev_token_bucket rate_limit; + struct ev_token_bucket_cfg rate_limit_cfg; + + /** True iff we don't want to read from any member of the group.until + * the token bucket refills. */ + unsigned read_suspended : 1; + /** True iff we don't want to write from any member of the group.until + * the token bucket refills. */ + unsigned write_suspended : 1; + /** True iff we were unable to suspend one of the bufferevents in the + * group for reading the last time we tried, and we should try + * again. */ + unsigned pending_unsuspend_read : 1; + /** True iff we were unable to suspend one of the bufferevents in the + * group for writing the last time we tried, and we should try + * again. */ + unsigned pending_unsuspend_write : 1; + + /*@{*/ + /** Total number of bytes read or written in this group since last + * reset. */ + ev_uint64_t total_read; + ev_uint64_t total_written; + /*@}*/ + + /** The number of bufferevents in the group. */ + int n_members; + + /** The smallest number of bytes that any member of the group should + * be limited to read or write at a time. */ + ev_ssize_t min_share; + ev_ssize_t configured_min_share; + + /** Timeout event that goes off once a tick, when the bucket is ready + * to refill. */ + struct event master_refill_event; + /** Lock to protect the members of this group. This lock should nest + * within every bufferevent lock: if you are holding this lock, do + * not assume you can lock another bufferevent. */ + void *lock; +}; + +/** Fields for rate-limiting a single bufferevent. */ +struct bufferevent_rate_limit { + /* Linked-list elements for storing this bufferevent_private in a + * group. + * + * Note that this field is supposed to be protected by the group + * lock */ + TAILQ_ENTRY(bufferevent_private) next_in_group; + /** The rate-limiting group for this bufferevent, or NULL if it is + * only rate-limited on its own. */ + struct bufferevent_rate_limit_group *group; + + /* This bufferevent's current limits. */ + struct ev_token_bucket limit; + /* Pointer to the rate-limit configuration for this bufferevent. + * Can be shared. XXX reference-count this? */ + struct ev_token_bucket_cfg *cfg; + + /* Timeout event used when one this bufferevent's buckets are + * empty. */ + struct event refill_bucket_event; +}; + +/** Parts of the bufferevent structure that are shared among all bufferevent + * types, but not exposed in bufferevent_struct.h. */ +struct bufferevent_private { + /** The underlying bufferevent structure. */ + struct bufferevent bev; + + /** Evbuffer callback to enforce watermarks on input. */ + struct evbuffer_cb_entry *read_watermarks_cb; + + /** If set, we should free the lock when we free the bufferevent. */ + unsigned own_lock : 1; + + /** Flag: set if we have deferred callbacks and a read callback is + * pending. */ + unsigned readcb_pending : 1; + /** Flag: set if we have deferred callbacks and a write callback is + * pending. */ + unsigned writecb_pending : 1; + /** Flag: set if we are currently busy connecting. */ + unsigned connecting : 1; + /** Flag: set if a connect failed prematurely; this is a hack for + * getting around the bufferevent abstraction. */ + unsigned connection_refused : 1; + /** Set to the events pending if we have deferred callbacks and + * an events callback is pending. */ + short eventcb_pending; + + /** If set, read is suspended until one or more conditions are over. + * The actual value here is a bitfield of those conditions; see the + * BEV_SUSPEND_* flags above. */ + bufferevent_suspend_flags read_suspended; + + /** If set, writing is suspended until one or more conditions are over. + * The actual value here is a bitfield of those conditions; see the + * BEV_SUSPEND_* flags above. */ + bufferevent_suspend_flags write_suspended; + + /** Set to the current socket errno if we have deferred callbacks and + * an events callback is pending. */ + int errno_pending; + + /** The DNS error code for bufferevent_socket_connect_hostname */ + int dns_error; + + /** Used to implement deferred callbacks */ + struct deferred_cb deferred; + + /** The options this bufferevent was constructed with */ + enum bufferevent_options options; + + /** Current reference count for this bufferevent. */ + int refcnt; + + /** Lock for this bufferevent. Shared by the inbuf and the outbuf. + * If NULL, locking is disabled. */ + void *lock; + + /** Rate-limiting information for this bufferevent */ + struct bufferevent_rate_limit *rate_limiting; +}; + +/** Possible operations for a control callback. */ +enum bufferevent_ctrl_op { + BEV_CTRL_SET_FD, + BEV_CTRL_GET_FD, + BEV_CTRL_GET_UNDERLYING, + BEV_CTRL_CANCEL_ALL +}; + +/** Possible data types for a control callback */ +union bufferevent_ctrl_data { + void *ptr; + evutil_socket_t fd; +}; + +/** + Implementation table for a bufferevent: holds function pointers and other + information to make the various bufferevent types work. +*/ +struct bufferevent_ops { + /** The name of the bufferevent's type. */ + const char *type; + /** At what offset into the implementation type will we find a + bufferevent structure? + + Example: if the type is implemented as + struct bufferevent_x { + int extra_data; + struct bufferevent bev; + } + then mem_offset should be offsetof(struct bufferevent_x, bev) + */ + off_t mem_offset; + + /** Enables one or more of EV_READ|EV_WRITE on a bufferevent. Does + not need to adjust the 'enabled' field. Returns 0 on success, -1 + on failure. + */ + int (*enable)(struct bufferevent *, short); + + /** Disables one or more of EV_READ|EV_WRITE on a bufferevent. Does + not need to adjust the 'enabled' field. Returns 0 on success, -1 + on failure. + */ + int (*disable)(struct bufferevent *, short); + + /** Free any storage and deallocate any extra data or structures used + in this implementation. + */ + void (*destruct)(struct bufferevent *); + + /** Called when the timeouts on the bufferevent have changed.*/ + int (*adj_timeouts)(struct bufferevent *); + + /** Called to flush data. */ + int (*flush)(struct bufferevent *, short, enum bufferevent_flush_mode); + + /** Called to access miscellaneous fields. */ + int (*ctrl)(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); + +}; + +extern const struct bufferevent_ops bufferevent_ops_socket; +extern const struct bufferevent_ops bufferevent_ops_filter; +extern const struct bufferevent_ops bufferevent_ops_pair; + +#define BEV_IS_SOCKET(bevp) ((bevp)->be_ops == &bufferevent_ops_socket) +#define BEV_IS_FILTER(bevp) ((bevp)->be_ops == &bufferevent_ops_filter) +#define BEV_IS_PAIR(bevp) ((bevp)->be_ops == &bufferevent_ops_pair) + +#ifdef WIN32 +extern const struct bufferevent_ops bufferevent_ops_async; +#define BEV_IS_ASYNC(bevp) ((bevp)->be_ops == &bufferevent_ops_async) +#else +#define BEV_IS_ASYNC(bevp) 0 +#endif + +/** Initialize the shared parts of a bufferevent. */ +int bufferevent_init_common(struct bufferevent_private *, struct event_base *, const struct bufferevent_ops *, enum bufferevent_options options); + +/** For internal use: temporarily stop all reads on bufev, until the conditions + * in 'what' are over. */ +void bufferevent_suspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what); +/** For internal use: clear the conditions 'what' on bufev, and re-enable + * reading if there are no conditions left. */ +void bufferevent_unsuspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what); + +/** For internal use: temporarily stop all writes on bufev, until the conditions + * in 'what' are over. */ +void bufferevent_suspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what); +/** For internal use: clear the conditions 'what' on bufev, and re-enable + * writing if there are no conditions left. */ +void bufferevent_unsuspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what); + +#define bufferevent_wm_suspend_read(b) \ + bufferevent_suspend_read((b), BEV_SUSPEND_WM) +#define bufferevent_wm_unsuspend_read(b) \ + bufferevent_unsuspend_read((b), BEV_SUSPEND_WM) + +/* + Disable a bufferevent. Equivalent to bufferevent_disable(), but + first resets 'connecting' flag to force EV_WRITE down for sure. + + XXXX this method will go away in the future; try not to add new users. + See comment in evhttp_connection_reset() for discussion. + + @param bufev the bufferevent to be disabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_disable() + */ +int bufferevent_disable_hard(struct bufferevent *bufev, short event); + +/** Internal: Set up locking on a bufferevent. If lock is set, use it. + * Otherwise, use a new lock. */ +int bufferevent_enable_locking(struct bufferevent *bufev, void *lock); +/** Internal: Increment the reference count on bufev. */ +void bufferevent_incref(struct bufferevent *bufev); +/** Internal: Lock bufev and increase its reference count. + * unlocking it otherwise. */ +void _bufferevent_incref_and_lock(struct bufferevent *bufev); +/** Internal: Decrement the reference count on bufev. Returns 1 if it freed + * the bufferevent.*/ +int bufferevent_decref(struct bufferevent *bufev); +/** Internal: Drop the reference count on bufev, freeing as necessary, and + * unlocking it otherwise. Returns 1 if it freed the bufferevent. */ +int _bufferevent_decref_and_unlock(struct bufferevent *bufev); + +/** Internal: If callbacks are deferred and we have a read callback, schedule + * a readcb. Otherwise just run the readcb. */ +void _bufferevent_run_readcb(struct bufferevent *bufev); +/** Internal: If callbacks are deferred and we have a write callback, schedule + * a writecb. Otherwise just run the writecb. */ +void _bufferevent_run_writecb(struct bufferevent *bufev); +/** Internal: If callbacks are deferred and we have an eventcb, schedule + * it to run with events "what". Otherwise just run the eventcb. */ +void _bufferevent_run_eventcb(struct bufferevent *bufev, short what); + +/** Internal: Add the event 'ev' with timeout tv, unless tv is set to 0, in + * which case add ev with no timeout. */ +int _bufferevent_add_event(struct event *ev, const struct timeval *tv); + +/* ========= + * These next functions implement timeouts for bufferevents that aren't doing + * anything else with ev_read and ev_write, to handle timeouts. + * ========= */ +/** Internal use: Set up the ev_read and ev_write callbacks so that + * the other "generic_timeout" functions will work on it. Call this from + * the constructor function. */ +void _bufferevent_init_generic_timeout_cbs(struct bufferevent *bev); +/** Internal use: Delete the ev_read and ev_write callbacks if they're pending. + * Call this from the destructor function. */ +int _bufferevent_del_generic_timeout_cbs(struct bufferevent *bev); +/** Internal use: Add or delete the generic timeout events as appropriate. + * (If an event is enabled and a timeout is set, we add the event. Otherwise + * we delete it.) Call this from anything that changes the timeout values, + * that enabled EV_READ or EV_WRITE, or that disables EV_READ or EV_WRITE. */ +int _bufferevent_generic_adj_timeouts(struct bufferevent *bev); + +/** Internal use: We have just successfully read data into an inbuf, so + * reset the read timeout (if any). */ +#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \ + do { \ + if (evutil_timerisset(&(bev)->timeout_read)) \ + event_add(&(bev)->ev_read, &(bev)->timeout_read); \ + } while (0) +/** Internal use: We have just successfully written data from an inbuf, so + * reset the read timeout (if any). */ +#define BEV_RESET_GENERIC_WRITE_TIMEOUT(bev) \ + do { \ + if (evutil_timerisset(&(bev)->timeout_write)) \ + event_add(&(bev)->ev_write, &(bev)->timeout_write); \ + } while (0) +#define BEV_DEL_GENERIC_READ_TIMEOUT(bev) \ + event_del(&(bev)->ev_read) +#define BEV_DEL_GENERIC_WRITE_TIMEOUT(bev) \ + event_del(&(bev)->ev_write) + + +/** Internal: Given a bufferevent, return its corresponding + * bufferevent_private. */ +#define BEV_UPCAST(b) EVUTIL_UPCAST((b), struct bufferevent_private, bev) + +#ifdef _EVENT_DISABLE_THREAD_SUPPORT +#define BEV_LOCK(b) _EVUTIL_NIL_STMT +#define BEV_UNLOCK(b) _EVUTIL_NIL_STMT +#else +/** Internal: Grab the lock (if any) on a bufferevent */ +#define BEV_LOCK(b) do { \ + struct bufferevent_private *locking = BEV_UPCAST(b); \ + EVLOCK_LOCK(locking->lock, 0); \ + } while (0) + +/** Internal: Release the lock (if any) on a bufferevent */ +#define BEV_UNLOCK(b) do { \ + struct bufferevent_private *locking = BEV_UPCAST(b); \ + EVLOCK_UNLOCK(locking->lock, 0); \ + } while (0) +#endif + + +/* ==== For rate-limiting. */ + +int _bufferevent_decrement_write_buckets(struct bufferevent_private *bev, + ev_ssize_t bytes); +int _bufferevent_decrement_read_buckets(struct bufferevent_private *bev, + ev_ssize_t bytes); +ev_ssize_t _bufferevent_get_read_max(struct bufferevent_private *bev); +ev_ssize_t _bufferevent_get_write_max(struct bufferevent_private *bev); + +#ifdef __cplusplus +} +#endif + + +#endif /* _BUFFEREVENT_INTERNAL_H_ */ diff --git a/libevent/bufferevent.c b/libevent/bufferevent.c new file mode 100644 index 0000000..45a1437 --- /dev/null +++ b/libevent/bufferevent.c @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2002-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos, Nick Mathewson + * + * 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. + */ + +#include + +#include "event2/event-config.h" + +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#ifdef _EVENT_HAVE_STDARG_H +#include +#endif + +#ifdef WIN32 +#include +#endif +#include + +#include "event2/util.h" +#include "event2/buffer.h" +#include "event2/buffer_compat.h" +#include "event2/bufferevent.h" +#include "event2/bufferevent_struct.h" +#include "event2/bufferevent_compat.h" +#include "event2/event.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "bufferevent-internal.h" +#include "evbuffer-internal.h" +#include "util-internal.h" + +static void _bufferevent_cancel_all(struct bufferevent *bev); + + +void +bufferevent_suspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + BEV_LOCK(bufev); + if (!bufev_private->read_suspended) + bufev->be_ops->disable(bufev, EV_READ); + bufev_private->read_suspended |= what; + BEV_UNLOCK(bufev); +} + +void +bufferevent_unsuspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + BEV_LOCK(bufev); + bufev_private->read_suspended &= ~what; + if (!bufev_private->read_suspended && (bufev->enabled & EV_READ)) + bufev->be_ops->enable(bufev, EV_READ); + BEV_UNLOCK(bufev); +} + +void +bufferevent_suspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + BEV_LOCK(bufev); + if (!bufev_private->write_suspended) + bufev->be_ops->disable(bufev, EV_WRITE); + bufev_private->write_suspended |= what; + BEV_UNLOCK(bufev); +} + +void +bufferevent_unsuspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + BEV_LOCK(bufev); + bufev_private->write_suspended &= ~what; + if (!bufev_private->write_suspended && (bufev->enabled & EV_WRITE)) + bufev->be_ops->enable(bufev, EV_WRITE); + BEV_UNLOCK(bufev); +} + + +/* Callback to implement watermarks on the input buffer. Only enabled + * if the watermark is set. */ +static void +bufferevent_inbuf_wm_cb(struct evbuffer *buf, + const struct evbuffer_cb_info *cbinfo, + void *arg) +{ + struct bufferevent *bufev = arg; + size_t size; + + size = evbuffer_get_length(buf); + + if (size >= bufev->wm_read.high) + bufferevent_wm_suspend_read(bufev); + else + bufferevent_wm_unsuspend_read(bufev); +} + +static void +bufferevent_run_deferred_callbacks_locked(struct deferred_cb *_, void *arg) +{ + struct bufferevent_private *bufev_private = arg; + struct bufferevent *bufev = &bufev_private->bev; + + BEV_LOCK(bufev); + if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) && + bufev->errorcb) { + /* The "connected" happened before any reads or writes, so + send it first. */ + bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED; + bufev->errorcb(bufev, BEV_EVENT_CONNECTED, bufev->cbarg); + } + if (bufev_private->readcb_pending && bufev->readcb) { + bufev_private->readcb_pending = 0; + bufev->readcb(bufev, bufev->cbarg); + } + if (bufev_private->writecb_pending && bufev->writecb) { + bufev_private->writecb_pending = 0; + bufev->writecb(bufev, bufev->cbarg); + } + if (bufev_private->eventcb_pending && bufev->errorcb) { + short what = bufev_private->eventcb_pending; + int err = bufev_private->errno_pending; + bufev_private->eventcb_pending = 0; + bufev_private->errno_pending = 0; + EVUTIL_SET_SOCKET_ERROR(err); + bufev->errorcb(bufev, what, bufev->cbarg); + } + _bufferevent_decref_and_unlock(bufev); +} + +static void +bufferevent_run_deferred_callbacks_unlocked(struct deferred_cb *_, void *arg) +{ + struct bufferevent_private *bufev_private = arg; + struct bufferevent *bufev = &bufev_private->bev; + + BEV_LOCK(bufev); +#define UNLOCKED(stmt) \ + do { BEV_UNLOCK(bufev); stmt; BEV_LOCK(bufev); } while(0) + + if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) && + bufev->errorcb) { + /* The "connected" happened before any reads or writes, so + send it first. */ + bufferevent_event_cb errorcb = bufev->errorcb; + void *cbarg = bufev->cbarg; + bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED; + UNLOCKED(errorcb(bufev, BEV_EVENT_CONNECTED, cbarg)); + } + if (bufev_private->readcb_pending && bufev->readcb) { + bufferevent_data_cb readcb = bufev->readcb; + void *cbarg = bufev->cbarg; + bufev_private->readcb_pending = 0; + UNLOCKED(readcb(bufev, cbarg)); + } + if (bufev_private->writecb_pending && bufev->writecb) { + bufferevent_data_cb writecb = bufev->writecb; + void *cbarg = bufev->cbarg; + bufev_private->writecb_pending = 0; + UNLOCKED(writecb(bufev, cbarg)); + } + if (bufev_private->eventcb_pending && bufev->errorcb) { + bufferevent_event_cb errorcb = bufev->errorcb; + void *cbarg = bufev->cbarg; + short what = bufev_private->eventcb_pending; + int err = bufev_private->errno_pending; + bufev_private->eventcb_pending = 0; + bufev_private->errno_pending = 0; + EVUTIL_SET_SOCKET_ERROR(err); + UNLOCKED(errorcb(bufev,what,cbarg)); + } + _bufferevent_decref_and_unlock(bufev); +#undef UNLOCKED +} + +#define SCHEDULE_DEFERRED(bevp) \ + do { \ + bufferevent_incref(&(bevp)->bev); \ + event_deferred_cb_schedule( \ + event_base_get_deferred_cb_queue((bevp)->bev.ev_base), \ + &(bevp)->deferred); \ + } while (0) + + +void +_bufferevent_run_readcb(struct bufferevent *bufev) +{ + /* Requires that we hold the lock and a reference */ + struct bufferevent_private *p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + if (bufev->readcb == NULL) + return; + if (p->options & BEV_OPT_DEFER_CALLBACKS) { + p->readcb_pending = 1; + if (!p->deferred.queued) + SCHEDULE_DEFERRED(p); + } else { + bufev->readcb(bufev, bufev->cbarg); + } +} + +void +_bufferevent_run_writecb(struct bufferevent *bufev) +{ + /* Requires that we hold the lock and a reference */ + struct bufferevent_private *p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + if (bufev->writecb == NULL) + return; + if (p->options & BEV_OPT_DEFER_CALLBACKS) { + p->writecb_pending = 1; + if (!p->deferred.queued) + SCHEDULE_DEFERRED(p); + } else { + bufev->writecb(bufev, bufev->cbarg); + } +} + +void +_bufferevent_run_eventcb(struct bufferevent *bufev, short what) +{ + /* Requires that we hold the lock and a reference */ + struct bufferevent_private *p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + if (bufev->errorcb == NULL) + return; + if (p->options & BEV_OPT_DEFER_CALLBACKS) { + p->eventcb_pending |= what; + p->errno_pending = EVUTIL_SOCKET_ERROR(); + if (!p->deferred.queued) + SCHEDULE_DEFERRED(p); + } else { + bufev->errorcb(bufev, what, bufev->cbarg); + } +} + +int +bufferevent_init_common(struct bufferevent_private *bufev_private, + struct event_base *base, + const struct bufferevent_ops *ops, + enum bufferevent_options options) +{ + struct bufferevent *bufev = &bufev_private->bev; + + if (!bufev->input) { + if ((bufev->input = evbuffer_new()) == NULL) + return -1; + } + + if (!bufev->output) { + if ((bufev->output = evbuffer_new()) == NULL) { + evbuffer_free(bufev->input); + return -1; + } + } + + bufev_private->refcnt = 1; + bufev->ev_base = base; + + /* Disable timeouts. */ + evutil_timerclear(&bufev->timeout_read); + evutil_timerclear(&bufev->timeout_write); + + bufev->be_ops = ops; + + /* + * Set to EV_WRITE so that using bufferevent_write is going to + * trigger a callback. Reading needs to be explicitly enabled + * because otherwise no data will be available. + */ + bufev->enabled = EV_WRITE; + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + if (options & BEV_OPT_THREADSAFE) { + if (bufferevent_enable_locking(bufev, NULL) < 0) { + /* cleanup */ + evbuffer_free(bufev->input); + evbuffer_free(bufev->output); + bufev->input = NULL; + bufev->output = NULL; + return -1; + } + } +#endif + if ((options & (BEV_OPT_DEFER_CALLBACKS|BEV_OPT_UNLOCK_CALLBACKS)) + == BEV_OPT_UNLOCK_CALLBACKS) { + event_warnx("UNLOCK_CALLBACKS requires DEFER_CALLBACKS"); + return -1; + } + if (options & BEV_OPT_DEFER_CALLBACKS) { + if (options & BEV_OPT_UNLOCK_CALLBACKS) + event_deferred_cb_init(&bufev_private->deferred, + bufferevent_run_deferred_callbacks_unlocked, + bufev_private); + else + event_deferred_cb_init(&bufev_private->deferred, + bufferevent_run_deferred_callbacks_locked, + bufev_private); + } + + bufev_private->options = options; + + evbuffer_set_parent(bufev->input, bufev); + evbuffer_set_parent(bufev->output, bufev); + + return 0; +} + +void +bufferevent_setcb(struct bufferevent *bufev, + bufferevent_data_cb readcb, bufferevent_data_cb writecb, + bufferevent_event_cb eventcb, void *cbarg) +{ + BEV_LOCK(bufev); + + bufev->readcb = readcb; + bufev->writecb = writecb; + bufev->errorcb = eventcb; + + bufev->cbarg = cbarg; + BEV_UNLOCK(bufev); +} + +struct evbuffer * +bufferevent_get_input(struct bufferevent *bufev) +{ + return bufev->input; +} + +struct evbuffer * +bufferevent_get_output(struct bufferevent *bufev) +{ + return bufev->output; +} + +struct event_base * +bufferevent_get_base(struct bufferevent *bufev) +{ + return bufev->ev_base; +} + +int +bufferevent_write(struct bufferevent *bufev, const void *data, size_t size) +{ + if (evbuffer_add(bufev->output, data, size) == -1) + return (-1); + + return 0; +} + +int +bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf) +{ + if (evbuffer_add_buffer(bufev->output, buf) == -1) + return (-1); + + return 0; +} + +size_t +bufferevent_read(struct bufferevent *bufev, void *data, size_t size) +{ + return (evbuffer_remove(bufev->input, data, size)); +} + +int +bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf) +{ + return (evbuffer_add_buffer(buf, bufev->input)); +} + +int +bufferevent_enable(struct bufferevent *bufev, short event) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + short impl_events = event; + int r = 0; + + _bufferevent_incref_and_lock(bufev); + if (bufev_private->read_suspended) + impl_events &= ~EV_READ; + if (bufev_private->write_suspended) + impl_events &= ~EV_WRITE; + + bufev->enabled |= event; + + if (impl_events && bufev->be_ops->enable(bufev, impl_events) < 0) + r = -1; + + _bufferevent_decref_and_unlock(bufev); + return r; +} + +int +bufferevent_set_timeouts(struct bufferevent *bufev, + const struct timeval *tv_read, + const struct timeval *tv_write) +{ + int r = 0; + BEV_LOCK(bufev); + if (tv_read) { + bufev->timeout_read = *tv_read; + } else { + evutil_timerclear(&bufev->timeout_read); + } + if (tv_write) { + bufev->timeout_write = *tv_write; + } else { + evutil_timerclear(&bufev->timeout_write); + } + + if (bufev->be_ops->adj_timeouts) + r = bufev->be_ops->adj_timeouts(bufev); + BEV_UNLOCK(bufev); + + return r; +} + + +/* Obsolete; use bufferevent_set_timeouts */ +void +bufferevent_settimeout(struct bufferevent *bufev, + int timeout_read, int timeout_write) +{ + struct timeval tv_read, tv_write; + struct timeval *ptv_read = NULL, *ptv_write = NULL; + + memset(&tv_read, 0, sizeof(tv_read)); + memset(&tv_write, 0, sizeof(tv_write)); + + if (timeout_read) { + tv_read.tv_sec = timeout_read; + ptv_read = &tv_read; + } + if (timeout_write) { + tv_write.tv_sec = timeout_write; + ptv_write = &tv_write; + } + + bufferevent_set_timeouts(bufev, ptv_read, ptv_write); +} + + +int +bufferevent_disable_hard(struct bufferevent *bufev, short event) +{ + int r = 0; + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + + BEV_LOCK(bufev); + bufev->enabled &= ~event; + + bufev_private->connecting = 0; + if (bufev->be_ops->disable(bufev, event) < 0) + r = -1; + + BEV_UNLOCK(bufev); + return r; +} + +int +bufferevent_disable(struct bufferevent *bufev, short event) +{ + int r = 0; + + BEV_LOCK(bufev); + bufev->enabled &= ~event; + + if (bufev->be_ops->disable(bufev, event) < 0) + r = -1; + + BEV_UNLOCK(bufev); + return r; +} + +/* + * Sets the water marks + */ + +void +bufferevent_setwatermark(struct bufferevent *bufev, short events, + size_t lowmark, size_t highmark) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + + BEV_LOCK(bufev); + if (events & EV_WRITE) { + bufev->wm_write.low = lowmark; + bufev->wm_write.high = highmark; + } + + if (events & EV_READ) { + bufev->wm_read.low = lowmark; + bufev->wm_read.high = highmark; + + if (highmark) { + /* There is now a new high-water mark for read. + enable the callback if needed, and see if we should + suspend/bufferevent_wm_unsuspend. */ + + if (bufev_private->read_watermarks_cb == NULL) { + bufev_private->read_watermarks_cb = + evbuffer_add_cb(bufev->input, + bufferevent_inbuf_wm_cb, + bufev); + } + evbuffer_cb_set_flags(bufev->input, + bufev_private->read_watermarks_cb, + EVBUFFER_CB_ENABLED|EVBUFFER_CB_NODEFER); + + if (evbuffer_get_length(bufev->input) > highmark) + bufferevent_wm_suspend_read(bufev); + else if (evbuffer_get_length(bufev->input) < highmark) + bufferevent_wm_unsuspend_read(bufev); + } else { + /* There is now no high-water mark for read. */ + if (bufev_private->read_watermarks_cb) + evbuffer_cb_clear_flags(bufev->input, + bufev_private->read_watermarks_cb, + EVBUFFER_CB_ENABLED); + bufferevent_wm_unsuspend_read(bufev); + } + } + BEV_UNLOCK(bufev); +} + +int +bufferevent_flush(struct bufferevent *bufev, + short iotype, + enum bufferevent_flush_mode mode) +{ + int r = -1; + BEV_LOCK(bufev); + if (bufev->be_ops->flush) + r = bufev->be_ops->flush(bufev, iotype, mode); + BEV_UNLOCK(bufev); + return r; +} + +void +_bufferevent_incref_and_lock(struct bufferevent *bufev) +{ + struct bufferevent_private *bufev_private = + BEV_UPCAST(bufev); + BEV_LOCK(bufev); + ++bufev_private->refcnt; +} + +#if 0 +static void +_bufferevent_transfer_lock_ownership(struct bufferevent *donor, + struct bufferevent *recipient) +{ + struct bufferevent_private *d = BEV_UPCAST(donor); + struct bufferevent_private *r = BEV_UPCAST(recipient); + if (d->lock != r->lock) + return; + if (r->own_lock) + return; + if (d->own_lock) { + d->own_lock = 0; + r->own_lock = 1; + } +} +#endif + +int +_bufferevent_decref_and_unlock(struct bufferevent *bufev) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + struct bufferevent *underlying; + + EVUTIL_ASSERT(bufev_private->refcnt > 0); + + if (--bufev_private->refcnt) { + BEV_UNLOCK(bufev); + return 0; + } + + underlying = bufferevent_get_underlying(bufev); + + /* Clean up the shared info */ + if (bufev->be_ops->destruct) + bufev->be_ops->destruct(bufev); + + /* XXX what happens if refcnt for these buffers is > 1? + * The buffers can share a lock with this bufferevent object, + * but the lock might be destroyed below. */ + /* evbuffer will free the callbacks */ + evbuffer_free(bufev->input); + evbuffer_free(bufev->output); + + if (bufev_private->rate_limiting) { + if (bufev_private->rate_limiting->group) + bufferevent_remove_from_rate_limit_group_internal(bufev,0); + if (event_initialized(&bufev_private->rate_limiting->refill_bucket_event)) + event_del(&bufev_private->rate_limiting->refill_bucket_event); + event_debug_unassign(&bufev_private->rate_limiting->refill_bucket_event); + mm_free(bufev_private->rate_limiting); + bufev_private->rate_limiting = NULL; + } + + event_debug_unassign(&bufev->ev_read); + event_debug_unassign(&bufev->ev_write); + + BEV_UNLOCK(bufev); + if (bufev_private->own_lock) + EVTHREAD_FREE_LOCK(bufev_private->lock, + EVTHREAD_LOCKTYPE_RECURSIVE); + + /* Free the actual allocated memory. */ + mm_free(((char*)bufev) - bufev->be_ops->mem_offset); + + /* Release the reference to underlying now that we no longer need the + * reference to it. We wait this long mainly in case our lock is + * shared with underlying. + * + * The 'destruct' function will also drop a reference to underlying + * if BEV_OPT_CLOSE_ON_FREE is set. + * + * XXX Should we/can we just refcount evbuffer/bufferevent locks? + * It would probably save us some headaches. + */ + if (underlying) + bufferevent_decref(underlying); + + return 1; +} + +int +bufferevent_decref(struct bufferevent *bufev) +{ + BEV_LOCK(bufev); + return _bufferevent_decref_and_unlock(bufev); +} + +void +bufferevent_free(struct bufferevent *bufev) +{ + BEV_LOCK(bufev); + bufferevent_setcb(bufev, NULL, NULL, NULL, NULL); + _bufferevent_cancel_all(bufev); + _bufferevent_decref_and_unlock(bufev); +} + +void +bufferevent_incref(struct bufferevent *bufev) +{ + struct bufferevent_private *bufev_private = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + + BEV_LOCK(bufev); + ++bufev_private->refcnt; + BEV_UNLOCK(bufev); +} + +int +bufferevent_enable_locking(struct bufferevent *bufev, void *lock) +{ +#ifdef _EVENT_DISABLE_THREAD_SUPPORT + return -1; +#else + struct bufferevent *underlying; + + if (BEV_UPCAST(bufev)->lock) + return -1; + underlying = bufferevent_get_underlying(bufev); + + if (!lock && underlying && BEV_UPCAST(underlying)->lock) { + lock = BEV_UPCAST(underlying)->lock; + BEV_UPCAST(bufev)->lock = lock; + BEV_UPCAST(bufev)->own_lock = 0; + } else if (!lock) { + EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE); + if (!lock) + return -1; + BEV_UPCAST(bufev)->lock = lock; + BEV_UPCAST(bufev)->own_lock = 1; + } else { + BEV_UPCAST(bufev)->lock = lock; + BEV_UPCAST(bufev)->own_lock = 0; + } + evbuffer_enable_locking(bufev->input, lock); + evbuffer_enable_locking(bufev->output, lock); + + if (underlying && !BEV_UPCAST(underlying)->lock) + bufferevent_enable_locking(underlying, lock); + + return 0; +#endif +} + +int +bufferevent_setfd(struct bufferevent *bev, evutil_socket_t fd) +{ + union bufferevent_ctrl_data d; + int res = -1; + d.fd = fd; + BEV_LOCK(bev); + if (bev->be_ops->ctrl) + res = bev->be_ops->ctrl(bev, BEV_CTRL_SET_FD, &d); + BEV_UNLOCK(bev); + return res; +} + +evutil_socket_t +bufferevent_getfd(struct bufferevent *bev) +{ + union bufferevent_ctrl_data d; + int res = -1; + d.fd = -1; + BEV_LOCK(bev); + if (bev->be_ops->ctrl) + res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_FD, &d); + BEV_UNLOCK(bev); + return (res<0) ? -1 : d.fd; +} + +static void +_bufferevent_cancel_all(struct bufferevent *bev) +{ + union bufferevent_ctrl_data d; + memset(&d, 0, sizeof(d)); + BEV_LOCK(bev); + if (bev->be_ops->ctrl) + bev->be_ops->ctrl(bev, BEV_CTRL_CANCEL_ALL, &d); + BEV_UNLOCK(bev); +} + +short +bufferevent_get_enabled(struct bufferevent *bufev) +{ + short r; + BEV_LOCK(bufev); + r = bufev->enabled; + BEV_UNLOCK(bufev); + return r; +} + +struct bufferevent * +bufferevent_get_underlying(struct bufferevent *bev) +{ + union bufferevent_ctrl_data d; + int res = -1; + d.ptr = NULL; + BEV_LOCK(bev); + if (bev->be_ops->ctrl) + res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_UNDERLYING, &d); + BEV_UNLOCK(bev); + return (res<0) ? NULL : d.ptr; +} + +static void +bufferevent_generic_read_timeout_cb(evutil_socket_t fd, short event, void *ctx) +{ + struct bufferevent *bev = ctx; + _bufferevent_incref_and_lock(bev); + bufferevent_disable(bev, EV_READ); + _bufferevent_run_eventcb(bev, BEV_EVENT_TIMEOUT|BEV_EVENT_READING); + _bufferevent_decref_and_unlock(bev); +} +static void +bufferevent_generic_write_timeout_cb(evutil_socket_t fd, short event, void *ctx) +{ + struct bufferevent *bev = ctx; + _bufferevent_incref_and_lock(bev); + bufferevent_disable(bev, EV_WRITE); + _bufferevent_run_eventcb(bev, BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING); + _bufferevent_decref_and_unlock(bev); +} + +void +_bufferevent_init_generic_timeout_cbs(struct bufferevent *bev) +{ + evtimer_assign(&bev->ev_read, bev->ev_base, + bufferevent_generic_read_timeout_cb, bev); + evtimer_assign(&bev->ev_write, bev->ev_base, + bufferevent_generic_write_timeout_cb, bev); +} + +int +_bufferevent_del_generic_timeout_cbs(struct bufferevent *bev) +{ + int r1,r2; + r1 = event_del(&bev->ev_read); + r2 = event_del(&bev->ev_write); + if (r1<0 || r2<0) + return -1; + return 0; +} + +int +_bufferevent_generic_adj_timeouts(struct bufferevent *bev) +{ + const short enabled = bev->enabled; + struct bufferevent_private *bev_p = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + int r1=0, r2=0; + if ((enabled & EV_READ) && !bev_p->read_suspended && + evutil_timerisset(&bev->timeout_read)) + r1 = event_add(&bev->ev_read, &bev->timeout_read); + else + r1 = event_del(&bev->ev_read); + + if ((enabled & EV_WRITE) && !bev_p->write_suspended && + evutil_timerisset(&bev->timeout_write) && + evbuffer_get_length(bev->output)) + r2 = event_add(&bev->ev_write, &bev->timeout_write); + else + r2 = event_del(&bev->ev_write); + if (r1 < 0 || r2 < 0) + return -1; + return 0; +} + +int +_bufferevent_add_event(struct event *ev, const struct timeval *tv) +{ + if (tv->tv_sec == 0 && tv->tv_usec == 0) + return event_add(ev, NULL); + else + return event_add(ev, tv); +} + +/* For use by user programs only; internally, we should be calling + either _bufferevent_incref_and_lock(), or BEV_LOCK. */ +void +bufferevent_lock(struct bufferevent *bev) +{ + _bufferevent_incref_and_lock(bev); +} + +void +bufferevent_unlock(struct bufferevent *bev) +{ + _bufferevent_decref_and_unlock(bev); +} diff --git a/libevent/bufferevent_async.c b/libevent/bufferevent_async.c new file mode 100644 index 0000000..f34ca5f --- /dev/null +++ b/libevent/bufferevent_async.c @@ -0,0 +1,690 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. 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. + */ + +#include "event2/event-config.h" + +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#ifdef _EVENT_HAVE_STDARG_H +#include +#endif +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif + +#ifdef WIN32 +#include +#include +#endif + +#include + +#include "event2/util.h" +#include "event2/bufferevent.h" +#include "event2/buffer.h" +#include "event2/bufferevent_struct.h" +#include "event2/event.h" +#include "event2/util.h" +#include "event-internal.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "bufferevent-internal.h" +#include "util-internal.h" +#include "iocp-internal.h" + +#ifndef SO_UPDATE_CONNECT_CONTEXT +/* Mingw is sometimes missing this */ +#define SO_UPDATE_CONNECT_CONTEXT 0x7010 +#endif + +/* prototypes */ +static int be_async_enable(struct bufferevent *, short); +static int be_async_disable(struct bufferevent *, short); +static void be_async_destruct(struct bufferevent *); +static int be_async_flush(struct bufferevent *, short, enum bufferevent_flush_mode); +static int be_async_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); + +struct bufferevent_async { + struct bufferevent_private bev; + struct event_overlapped connect_overlapped; + struct event_overlapped read_overlapped; + struct event_overlapped write_overlapped; + size_t read_in_progress; + size_t write_in_progress; + unsigned ok : 1; + unsigned read_added : 1; + unsigned write_added : 1; +}; + +const struct bufferevent_ops bufferevent_ops_async = { + "socket_async", + evutil_offsetof(struct bufferevent_async, bev.bev), + be_async_enable, + be_async_disable, + be_async_destruct, + _bufferevent_generic_adj_timeouts, + be_async_flush, + be_async_ctrl, +}; + +static inline struct bufferevent_async * +upcast(struct bufferevent *bev) +{ + struct bufferevent_async *bev_a; + if (bev->be_ops != &bufferevent_ops_async) + return NULL; + bev_a = EVUTIL_UPCAST(bev, struct bufferevent_async, bev.bev); + return bev_a; +} + +static inline struct bufferevent_async * +upcast_connect(struct event_overlapped *eo) +{ + struct bufferevent_async *bev_a; + bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, connect_overlapped); + EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev)); + return bev_a; +} + +static inline struct bufferevent_async * +upcast_read(struct event_overlapped *eo) +{ + struct bufferevent_async *bev_a; + bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, read_overlapped); + EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev)); + return bev_a; +} + +static inline struct bufferevent_async * +upcast_write(struct event_overlapped *eo) +{ + struct bufferevent_async *bev_a; + bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, write_overlapped); + EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev)); + return bev_a; +} + +static void +bev_async_del_write(struct bufferevent_async *beva) +{ + struct bufferevent *bev = &beva->bev.bev; + + if (beva->write_added) { + beva->write_added = 0; + event_base_del_virtual(bev->ev_base); + } +} + +static void +bev_async_del_read(struct bufferevent_async *beva) +{ + struct bufferevent *bev = &beva->bev.bev; + + if (beva->read_added) { + beva->read_added = 0; + event_base_del_virtual(bev->ev_base); + } +} + +static void +bev_async_add_write(struct bufferevent_async *beva) +{ + struct bufferevent *bev = &beva->bev.bev; + + if (!beva->write_added) { + beva->write_added = 1; + event_base_add_virtual(bev->ev_base); + } +} + +static void +bev_async_add_read(struct bufferevent_async *beva) +{ + struct bufferevent *bev = &beva->bev.bev; + + if (!beva->read_added) { + beva->read_added = 1; + event_base_add_virtual(bev->ev_base); + } +} + +static void +bev_async_consider_writing(struct bufferevent_async *beva) +{ + size_t at_most; + int limit; + struct bufferevent *bev = &beva->bev.bev; + + /* Don't write if there's a write in progress, or we do not + * want to write, or when there's nothing left to write. */ + if (beva->write_in_progress || beva->bev.connecting) + return; + if (!beva->ok || !(bev->enabled&EV_WRITE) || + !evbuffer_get_length(bev->output)) { + bev_async_del_write(beva); + return; + } + + at_most = evbuffer_get_length(bev->output); + + /* This is safe so long as bufferevent_get_write_max never returns + * more than INT_MAX. That's true for now. XXXX */ + limit = (int)_bufferevent_get_write_max(&beva->bev); + if (at_most >= (size_t)limit && limit >= 0) + at_most = limit; + + if (beva->bev.write_suspended) { + bev_async_del_write(beva); + return; + } + + /* XXXX doesn't respect low-water mark very well. */ + bufferevent_incref(bev); + if (evbuffer_launch_write(bev->output, at_most, + &beva->write_overlapped)) { + bufferevent_decref(bev); + beva->ok = 0; + _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); + } else { + beva->write_in_progress = at_most; + _bufferevent_decrement_write_buckets(&beva->bev, at_most); + bev_async_add_write(beva); + } +} + +static void +bev_async_consider_reading(struct bufferevent_async *beva) +{ + size_t cur_size; + size_t read_high; + size_t at_most; + int limit; + struct bufferevent *bev = &beva->bev.bev; + + /* Don't read if there is a read in progress, or we do not + * want to read. */ + if (beva->read_in_progress || beva->bev.connecting) + return; + if (!beva->ok || !(bev->enabled&EV_READ)) { + bev_async_del_read(beva); + return; + } + + /* Don't read if we're full */ + cur_size = evbuffer_get_length(bev->input); + read_high = bev->wm_read.high; + if (read_high) { + if (cur_size >= read_high) { + bev_async_del_read(beva); + return; + } + at_most = read_high - cur_size; + } else { + at_most = 16384; /* FIXME totally magic. */ + } + + /* XXXX This over-commits. */ + /* XXXX see also not above on cast on _bufferevent_get_write_max() */ + limit = (int)_bufferevent_get_read_max(&beva->bev); + if (at_most >= (size_t)limit && limit >= 0) + at_most = limit; + + if (beva->bev.read_suspended) { + bev_async_del_read(beva); + return; + } + + bufferevent_incref(bev); + if (evbuffer_launch_read(bev->input, at_most, &beva->read_overlapped)) { + beva->ok = 0; + _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); + bufferevent_decref(bev); + } else { + beva->read_in_progress = at_most; + _bufferevent_decrement_read_buckets(&beva->bev, at_most); + bev_async_add_read(beva); + } + + return; +} + +static void +be_async_outbuf_callback(struct evbuffer *buf, + const struct evbuffer_cb_info *cbinfo, + void *arg) +{ + struct bufferevent *bev = arg; + struct bufferevent_async *bev_async = upcast(bev); + + /* If we added data to the outbuf and were not writing before, + * we may want to write now. */ + + _bufferevent_incref_and_lock(bev); + + if (cbinfo->n_added) + bev_async_consider_writing(bev_async); + + _bufferevent_decref_and_unlock(bev); +} + +static void +be_async_inbuf_callback(struct evbuffer *buf, + const struct evbuffer_cb_info *cbinfo, + void *arg) +{ + struct bufferevent *bev = arg; + struct bufferevent_async *bev_async = upcast(bev); + + /* If we drained data from the inbuf and were not reading before, + * we may want to read now */ + + _bufferevent_incref_and_lock(bev); + + if (cbinfo->n_deleted) + bev_async_consider_reading(bev_async); + + _bufferevent_decref_and_unlock(bev); +} + +static int +be_async_enable(struct bufferevent *buf, short what) +{ + struct bufferevent_async *bev_async = upcast(buf); + + if (!bev_async->ok) + return -1; + + if (bev_async->bev.connecting) { + /* Don't launch anything during connection attempts. */ + return 0; + } + + if (what & EV_READ) + BEV_RESET_GENERIC_READ_TIMEOUT(buf); + if (what & EV_WRITE) + BEV_RESET_GENERIC_WRITE_TIMEOUT(buf); + + /* If we newly enable reading or writing, and we aren't reading or + writing already, consider launching a new read or write. */ + + if (what & EV_READ) + bev_async_consider_reading(bev_async); + if (what & EV_WRITE) + bev_async_consider_writing(bev_async); + return 0; +} + +static int +be_async_disable(struct bufferevent *bev, short what) +{ + struct bufferevent_async *bev_async = upcast(bev); + /* XXXX If we disable reading or writing, we may want to consider + * canceling any in-progress read or write operation, though it might + * not work. */ + + if (what & EV_READ) { + BEV_DEL_GENERIC_READ_TIMEOUT(bev); + bev_async_del_read(bev_async); + } + if (what & EV_WRITE) { + BEV_DEL_GENERIC_WRITE_TIMEOUT(bev); + bev_async_del_write(bev_async); + } + + return 0; +} + +static void +be_async_destruct(struct bufferevent *bev) +{ + struct bufferevent_async *bev_async = upcast(bev); + struct bufferevent_private *bev_p = BEV_UPCAST(bev); + evutil_socket_t fd; + + EVUTIL_ASSERT(!upcast(bev)->write_in_progress && + !upcast(bev)->read_in_progress); + + bev_async_del_read(bev_async); + bev_async_del_write(bev_async); + + fd = _evbuffer_overlapped_get_fd(bev->input); + if (bev_p->options & BEV_OPT_CLOSE_ON_FREE) { + /* XXXX possible double-close */ + evutil_closesocket(fd); + } + /* delete this in case non-blocking connect was used */ + if (event_initialized(&bev->ev_write)) { + event_del(&bev->ev_write); + _bufferevent_del_generic_timeout_cbs(bev); + } +} + +/* GetQueuedCompletionStatus doesn't reliably yield WSA error codes, so + * we use WSAGetOverlappedResult to translate. */ +static void +bev_async_set_wsa_error(struct bufferevent *bev, struct event_overlapped *eo) +{ + DWORD bytes, flags; + evutil_socket_t fd; + + fd = _evbuffer_overlapped_get_fd(bev->input); + WSAGetOverlappedResult(fd, &eo->overlapped, &bytes, FALSE, &flags); +} + +static int +be_async_flush(struct bufferevent *bev, short what, + enum bufferevent_flush_mode mode) +{ + return 0; +} + +static void +connect_complete(struct event_overlapped *eo, ev_uintptr_t key, + ev_ssize_t nbytes, int ok) +{ + struct bufferevent_async *bev_a = upcast_connect(eo); + struct bufferevent *bev = &bev_a->bev.bev; + evutil_socket_t sock; + + BEV_LOCK(bev); + + EVUTIL_ASSERT(bev_a->bev.connecting); + bev_a->bev.connecting = 0; + sock = _evbuffer_overlapped_get_fd(bev_a->bev.bev.input); + /* XXXX Handle error? */ + setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0); + + if (ok) + bufferevent_async_set_connected(bev); + else + bev_async_set_wsa_error(bev, eo); + + _bufferevent_run_eventcb(bev, + ok? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR); + + event_base_del_virtual(bev->ev_base); + + _bufferevent_decref_and_unlock(bev); +} + +static void +read_complete(struct event_overlapped *eo, ev_uintptr_t key, + ev_ssize_t nbytes, int ok) +{ + struct bufferevent_async *bev_a = upcast_read(eo); + struct bufferevent *bev = &bev_a->bev.bev; + short what = BEV_EVENT_READING; + ev_ssize_t amount_unread; + BEV_LOCK(bev); + EVUTIL_ASSERT(bev_a->read_in_progress); + + amount_unread = bev_a->read_in_progress - nbytes; + evbuffer_commit_read(bev->input, nbytes); + bev_a->read_in_progress = 0; + if (amount_unread) + _bufferevent_decrement_read_buckets(&bev_a->bev, -amount_unread); + + if (!ok) + bev_async_set_wsa_error(bev, eo); + + if (bev_a->ok) { + if (ok && nbytes) { + BEV_RESET_GENERIC_READ_TIMEOUT(bev); + if (evbuffer_get_length(bev->input) >= bev->wm_read.low) + _bufferevent_run_readcb(bev); + bev_async_consider_reading(bev_a); + } else if (!ok) { + what |= BEV_EVENT_ERROR; + bev_a->ok = 0; + _bufferevent_run_eventcb(bev, what); + } else if (!nbytes) { + what |= BEV_EVENT_EOF; + bev_a->ok = 0; + _bufferevent_run_eventcb(bev, what); + } + } + + _bufferevent_decref_and_unlock(bev); +} + +static void +write_complete(struct event_overlapped *eo, ev_uintptr_t key, + ev_ssize_t nbytes, int ok) +{ + struct bufferevent_async *bev_a = upcast_write(eo); + struct bufferevent *bev = &bev_a->bev.bev; + short what = BEV_EVENT_WRITING; + ev_ssize_t amount_unwritten; + + BEV_LOCK(bev); + EVUTIL_ASSERT(bev_a->write_in_progress); + + amount_unwritten = bev_a->write_in_progress - nbytes; + evbuffer_commit_write(bev->output, nbytes); + bev_a->write_in_progress = 0; + + if (amount_unwritten) + _bufferevent_decrement_write_buckets(&bev_a->bev, + -amount_unwritten); + + + if (!ok) + bev_async_set_wsa_error(bev, eo); + + if (bev_a->ok) { + if (ok && nbytes) { + BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); + if (evbuffer_get_length(bev->output) <= + bev->wm_write.low) + _bufferevent_run_writecb(bev); + bev_async_consider_writing(bev_a); + } else if (!ok) { + what |= BEV_EVENT_ERROR; + bev_a->ok = 0; + _bufferevent_run_eventcb(bev, what); + } else if (!nbytes) { + what |= BEV_EVENT_EOF; + bev_a->ok = 0; + _bufferevent_run_eventcb(bev, what); + } + } + + _bufferevent_decref_and_unlock(bev); +} + +struct bufferevent * +bufferevent_async_new(struct event_base *base, + evutil_socket_t fd, int options) +{ + struct bufferevent_async *bev_a; + struct bufferevent *bev; + struct event_iocp_port *iocp; + + options |= BEV_OPT_THREADSAFE; + + if (!(iocp = event_base_get_iocp(base))) + return NULL; + + if (fd >= 0 && event_iocp_port_associate(iocp, fd, 1)<0) { + int err = GetLastError(); + /* We may have alrady associated this fd with a port. + * Let's hope it's this port, and that the error code + * for doing this neer changes. */ + if (err != ERROR_INVALID_PARAMETER) + return NULL; + } + + if (!(bev_a = mm_calloc(1, sizeof(struct bufferevent_async)))) + return NULL; + + bev = &bev_a->bev.bev; + if (!(bev->input = evbuffer_overlapped_new(fd))) { + mm_free(bev_a); + return NULL; + } + if (!(bev->output = evbuffer_overlapped_new(fd))) { + evbuffer_free(bev->input); + mm_free(bev_a); + return NULL; + } + + if (bufferevent_init_common(&bev_a->bev, base, &bufferevent_ops_async, + options)<0) + goto err; + + evbuffer_add_cb(bev->input, be_async_inbuf_callback, bev); + evbuffer_add_cb(bev->output, be_async_outbuf_callback, bev); + + event_overlapped_init(&bev_a->connect_overlapped, connect_complete); + event_overlapped_init(&bev_a->read_overlapped, read_complete); + event_overlapped_init(&bev_a->write_overlapped, write_complete); + + bev_a->ok = fd >= 0; + if (bev_a->ok) + _bufferevent_init_generic_timeout_cbs(bev); + + return bev; +err: + bufferevent_free(&bev_a->bev.bev); + return NULL; +} + +void +bufferevent_async_set_connected(struct bufferevent *bev) +{ + struct bufferevent_async *bev_async = upcast(bev); + bev_async->ok = 1; + _bufferevent_init_generic_timeout_cbs(bev); + /* Now's a good time to consider reading/writing */ + be_async_enable(bev, bev->enabled); +} + +int +bufferevent_async_can_connect(struct bufferevent *bev) +{ + const struct win32_extension_fns *ext = + event_get_win32_extension_fns(); + + if (BEV_IS_ASYNC(bev) && + event_base_get_iocp(bev->ev_base) && + ext && ext->ConnectEx) + return 1; + + return 0; +} + +int +bufferevent_async_connect(struct bufferevent *bev, evutil_socket_t fd, + const struct sockaddr *sa, int socklen) +{ + BOOL rc; + struct bufferevent_async *bev_async = upcast(bev); + struct sockaddr_storage ss; + const struct win32_extension_fns *ext = + event_get_win32_extension_fns(); + + EVUTIL_ASSERT(ext && ext->ConnectEx && fd >= 0 && sa != NULL); + + /* ConnectEx() requires that the socket be bound to an address + * with bind() before using, otherwise it will fail. We attempt + * to issue a bind() here, taking into account that the error + * code is set to WSAEINVAL when the socket is already bound. */ + memset(&ss, 0, sizeof(ss)); + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)&ss; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; + sin6->sin6_family = AF_INET6; + sin6->sin6_addr = in6addr_any; + } else { + /* Well, the user will have to bind() */ + return -1; + } + if (bind(fd, (struct sockaddr *)&ss, sizeof(ss)) < 0 && + WSAGetLastError() != WSAEINVAL) + return -1; + + event_base_add_virtual(bev->ev_base); + bufferevent_incref(bev); + rc = ext->ConnectEx(fd, sa, socklen, NULL, 0, NULL, + &bev_async->connect_overlapped.overlapped); + if (rc || WSAGetLastError() == ERROR_IO_PENDING) + return 0; + + event_base_del_virtual(bev->ev_base); + bufferevent_decref(bev); + + return -1; +} + +static int +be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, + union bufferevent_ctrl_data *data) +{ + switch (op) { + case BEV_CTRL_GET_FD: + data->fd = _evbuffer_overlapped_get_fd(bev->input); + return 0; + case BEV_CTRL_SET_FD: { + struct event_iocp_port *iocp; + + if (data->fd == _evbuffer_overlapped_get_fd(bev->input)) + return 0; + if (!(iocp = event_base_get_iocp(bev->ev_base))) + return -1; + if (event_iocp_port_associate(iocp, data->fd, 1) < 0) + return -1; + _evbuffer_overlapped_set_fd(bev->input, data->fd); + _evbuffer_overlapped_set_fd(bev->output, data->fd); + return 0; + } + case BEV_CTRL_CANCEL_ALL: { + struct bufferevent_async *bev_a = upcast(bev); + evutil_socket_t fd = _evbuffer_overlapped_get_fd(bev->input); + if (fd != (evutil_socket_t)INVALID_SOCKET && + (bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) { + closesocket(fd); + } + bev_a->ok = 0; + return 0; + } + case BEV_CTRL_GET_UNDERLYING: + default: + return -1; + } +} + + diff --git a/libevent/bufferevent_filter.c b/libevent/bufferevent_filter.c new file mode 100644 index 0000000..557f8cc --- /dev/null +++ b/libevent/bufferevent_filter.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * Copyright (c) 2002-2006 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + */ + +#include + +#include "event2/event-config.h" + +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#ifdef _EVENT_HAVE_STDARG_H +#include +#endif + +#ifdef WIN32 +#include +#endif + +#include "event2/util.h" +#include "event2/bufferevent.h" +#include "event2/buffer.h" +#include "event2/bufferevent_struct.h" +#include "event2/event.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "bufferevent-internal.h" +#include "util-internal.h" + +/* prototypes */ +static int be_filter_enable(struct bufferevent *, short); +static int be_filter_disable(struct bufferevent *, short); +static void be_filter_destruct(struct bufferevent *); + +static void be_filter_readcb(struct bufferevent *, void *); +static void be_filter_writecb(struct bufferevent *, void *); +static void be_filter_eventcb(struct bufferevent *, short, void *); +static int be_filter_flush(struct bufferevent *bufev, + short iotype, enum bufferevent_flush_mode mode); +static int be_filter_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); + +static void bufferevent_filtered_outbuf_cb(struct evbuffer *buf, + const struct evbuffer_cb_info *info, void *arg); + +struct bufferevent_filtered { + struct bufferevent_private bev; + + /** The bufferevent that we read/write filtered data from/to. */ + struct bufferevent *underlying; + /** A callback on our outbuf to notice when somebody adds data */ + struct evbuffer_cb_entry *outbuf_cb; + /** True iff we have received an EOF callback from the underlying + * bufferevent. */ + unsigned got_eof; + + /** Function to free context when we're done. */ + void (*free_context)(void *); + /** Input filter */ + bufferevent_filter_cb process_in; + /** Output filter */ + bufferevent_filter_cb process_out; + /** User-supplied argument to the filters. */ + void *context; +}; + +const struct bufferevent_ops bufferevent_ops_filter = { + "filter", + evutil_offsetof(struct bufferevent_filtered, bev.bev), + be_filter_enable, + be_filter_disable, + be_filter_destruct, + _bufferevent_generic_adj_timeouts, + be_filter_flush, + be_filter_ctrl, +}; + +/* Given a bufferevent that's really the bev filter of a bufferevent_filtered, + * return that bufferevent_filtered. Returns NULL otherwise.*/ +static inline struct bufferevent_filtered * +upcast(struct bufferevent *bev) +{ + struct bufferevent_filtered *bev_f; + if (bev->be_ops != &bufferevent_ops_filter) + return NULL; + bev_f = (void*)( ((char*)bev) - + evutil_offsetof(struct bufferevent_filtered, bev.bev)); + EVUTIL_ASSERT(bev_f->bev.bev.be_ops == &bufferevent_ops_filter); + return bev_f; +} + +#define downcast(bev_f) (&(bev_f)->bev.bev) + +/** Return 1 iff bevf's underlying bufferevent's output buffer is at or + * over its high watermark such that we should not write to it in a given + * flush mode. */ +static int +be_underlying_writebuf_full(struct bufferevent_filtered *bevf, + enum bufferevent_flush_mode state) +{ + struct bufferevent *u = bevf->underlying; + return state == BEV_NORMAL && + u->wm_write.high && + evbuffer_get_length(u->output) >= u->wm_write.high; +} + +/** Return 1 if our input buffer is at or over its high watermark such that we + * should not write to it in a given flush mode. */ +static int +be_readbuf_full(struct bufferevent_filtered *bevf, + enum bufferevent_flush_mode state) +{ + struct bufferevent *bufev = downcast(bevf); + return state == BEV_NORMAL && + bufev->wm_read.high && + evbuffer_get_length(bufev->input) >= bufev->wm_read.high; +} + + +/* Filter to use when we're created with a NULL filter. */ +static enum bufferevent_filter_result +be_null_filter(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t lim, + enum bufferevent_flush_mode state, void *ctx) +{ + (void)state; + if (evbuffer_remove_buffer(src, dst, lim) == 0) + return BEV_OK; + else + return BEV_ERROR; +} + +struct bufferevent * +bufferevent_filter_new(struct bufferevent *underlying, + bufferevent_filter_cb input_filter, + bufferevent_filter_cb output_filter, + int options, + void (*free_context)(void *), + void *ctx) +{ + struct bufferevent_filtered *bufev_f; + int tmp_options = options & ~BEV_OPT_THREADSAFE; + + if (!underlying) + return NULL; + + if (!input_filter) + input_filter = be_null_filter; + if (!output_filter) + output_filter = be_null_filter; + + bufev_f = mm_calloc(1, sizeof(struct bufferevent_filtered)); + if (!bufev_f) + return NULL; + + if (bufferevent_init_common(&bufev_f->bev, underlying->ev_base, + &bufferevent_ops_filter, tmp_options) < 0) { + mm_free(bufev_f); + return NULL; + } + if (options & BEV_OPT_THREADSAFE) { + bufferevent_enable_locking(downcast(bufev_f), NULL); + } + + bufev_f->underlying = underlying; + + bufev_f->process_in = input_filter; + bufev_f->process_out = output_filter; + bufev_f->free_context = free_context; + bufev_f->context = ctx; + + bufferevent_setcb(bufev_f->underlying, + be_filter_readcb, be_filter_writecb, be_filter_eventcb, bufev_f); + + bufev_f->outbuf_cb = evbuffer_add_cb(downcast(bufev_f)->output, + bufferevent_filtered_outbuf_cb, bufev_f); + + _bufferevent_init_generic_timeout_cbs(downcast(bufev_f)); + bufferevent_incref(underlying); + + bufferevent_enable(underlying, EV_READ|EV_WRITE); + bufferevent_suspend_read(underlying, BEV_SUSPEND_FILT_READ); + + return downcast(bufev_f); +} + +static void +be_filter_destruct(struct bufferevent *bev) +{ + struct bufferevent_filtered *bevf = upcast(bev); + EVUTIL_ASSERT(bevf); + if (bevf->free_context) + bevf->free_context(bevf->context); + + if (bevf->bev.options & BEV_OPT_CLOSE_ON_FREE) { + /* Yes, there is also a decref in bufferevent_decref. + * That decref corresponds to the incref when we set + * underlying for the first time. This decref is an + * extra one to remove the last reference. + */ + if (BEV_UPCAST(bevf->underlying)->refcnt < 2) { + event_warnx("BEV_OPT_CLOSE_ON_FREE set on an " + "bufferevent with too few references"); + } else { + bufferevent_free(bevf->underlying); + } + } else { + if (bevf->underlying) { + if (bevf->underlying->errorcb == be_filter_eventcb) + bufferevent_setcb(bevf->underlying, + NULL, NULL, NULL, NULL); + bufferevent_unsuspend_read(bevf->underlying, + BEV_SUSPEND_FILT_READ); + } + } + + _bufferevent_del_generic_timeout_cbs(bev); +} + +static int +be_filter_enable(struct bufferevent *bev, short event) +{ + struct bufferevent_filtered *bevf = upcast(bev); + if (event & EV_WRITE) + BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); + + if (event & EV_READ) { + BEV_RESET_GENERIC_READ_TIMEOUT(bev); + bufferevent_unsuspend_read(bevf->underlying, + BEV_SUSPEND_FILT_READ); + } + return 0; +} + +static int +be_filter_disable(struct bufferevent *bev, short event) +{ + struct bufferevent_filtered *bevf = upcast(bev); + if (event & EV_WRITE) + BEV_DEL_GENERIC_WRITE_TIMEOUT(bev); + if (event & EV_READ) { + BEV_DEL_GENERIC_READ_TIMEOUT(bev); + bufferevent_suspend_read(bevf->underlying, + BEV_SUSPEND_FILT_READ); + } + return 0; +} + +static enum bufferevent_filter_result +be_filter_process_input(struct bufferevent_filtered *bevf, + enum bufferevent_flush_mode state, + int *processed_out) +{ + enum bufferevent_filter_result res; + struct bufferevent *bev = downcast(bevf); + + if (state == BEV_NORMAL) { + /* If we're in 'normal' mode, don't urge data on the filter + * unless we're reading data and under our high-water mark.*/ + if (!(bev->enabled & EV_READ) || + be_readbuf_full(bevf, state)) + return BEV_OK; + } + + do { + ev_ssize_t limit = -1; + if (state == BEV_NORMAL && bev->wm_read.high) + limit = bev->wm_read.high - + evbuffer_get_length(bev->input); + + res = bevf->process_in(bevf->underlying->input, + bev->input, limit, state, bevf->context); + + if (res == BEV_OK) + *processed_out = 1; + } while (res == BEV_OK && + (bev->enabled & EV_READ) && + evbuffer_get_length(bevf->underlying->input) && + !be_readbuf_full(bevf, state)); + + if (*processed_out) + BEV_RESET_GENERIC_READ_TIMEOUT(bev); + + return res; +} + + +static enum bufferevent_filter_result +be_filter_process_output(struct bufferevent_filtered *bevf, + enum bufferevent_flush_mode state, + int *processed_out) +{ + /* Requires references and lock: might call writecb */ + enum bufferevent_filter_result res = BEV_OK; + struct bufferevent *bufev = downcast(bevf); + int again = 0; + + if (state == BEV_NORMAL) { + /* If we're in 'normal' mode, don't urge data on the + * filter unless we're writing data, and the underlying + * bufferevent is accepting data, and we have data to + * give the filter. If we're in 'flush' or 'finish', + * call the filter no matter what. */ + if (!(bufev->enabled & EV_WRITE) || + be_underlying_writebuf_full(bevf, state) || + !evbuffer_get_length(bufev->output)) + return BEV_OK; + } + + /* disable the callback that calls this function + when the user adds to the output buffer. */ + evbuffer_cb_set_flags(bufev->output, bevf->outbuf_cb, 0); + + do { + int processed = 0; + again = 0; + + do { + ev_ssize_t limit = -1; + if (state == BEV_NORMAL && + bevf->underlying->wm_write.high) + limit = bevf->underlying->wm_write.high - + evbuffer_get_length(bevf->underlying->output); + + res = bevf->process_out(downcast(bevf)->output, + bevf->underlying->output, + limit, + state, + bevf->context); + + if (res == BEV_OK) + processed = *processed_out = 1; + } while (/* Stop if the filter wasn't successful...*/ + res == BEV_OK && + /* Or if we aren't writing any more. */ + (bufev->enabled & EV_WRITE) && + /* Of if we have nothing more to write and we are + * not flushing. */ + evbuffer_get_length(bufev->output) && + /* Or if we have filled the underlying output buffer. */ + !be_underlying_writebuf_full(bevf,state)); + + if (processed && + evbuffer_get_length(bufev->output) <= bufev->wm_write.low) { + /* call the write callback.*/ + _bufferevent_run_writecb(bufev); + + if (res == BEV_OK && + (bufev->enabled & EV_WRITE) && + evbuffer_get_length(bufev->output) && + !be_underlying_writebuf_full(bevf, state)) { + again = 1; + } + } + } while (again); + + /* reenable the outbuf_cb */ + evbuffer_cb_set_flags(bufev->output,bevf->outbuf_cb, + EVBUFFER_CB_ENABLED); + + if (*processed_out) + BEV_RESET_GENERIC_WRITE_TIMEOUT(bufev); + + return res; +} + +/* Called when the size of our outbuf changes. */ +static void +bufferevent_filtered_outbuf_cb(struct evbuffer *buf, + const struct evbuffer_cb_info *cbinfo, void *arg) +{ + struct bufferevent_filtered *bevf = arg; + struct bufferevent *bev = downcast(bevf); + + if (cbinfo->n_added) { + int processed_any = 0; + /* Somebody added more data to the output buffer. Try to + * process it, if we should. */ + _bufferevent_incref_and_lock(bev); + be_filter_process_output(bevf, BEV_NORMAL, &processed_any); + _bufferevent_decref_and_unlock(bev); + } +} + +/* Called when the underlying socket has read. */ +static void +be_filter_readcb(struct bufferevent *underlying, void *_me) +{ + struct bufferevent_filtered *bevf = _me; + enum bufferevent_filter_result res; + enum bufferevent_flush_mode state; + struct bufferevent *bufev = downcast(bevf); + int processed_any = 0; + + _bufferevent_incref_and_lock(bufev); + + if (bevf->got_eof) + state = BEV_FINISHED; + else + state = BEV_NORMAL; + + /* XXXX use return value */ + res = be_filter_process_input(bevf, state, &processed_any); + (void)res; + + /* XXX This should be in process_input, not here. There are + * other places that can call process-input, and they should + * force readcb calls as needed. */ + if (processed_any && + evbuffer_get_length(bufev->input) >= bufev->wm_read.low) + _bufferevent_run_readcb(bufev); + + _bufferevent_decref_and_unlock(bufev); +} + +/* Called when the underlying socket has drained enough that we can write to + it. */ +static void +be_filter_writecb(struct bufferevent *underlying, void *_me) +{ + struct bufferevent_filtered *bevf = _me; + struct bufferevent *bev = downcast(bevf); + int processed_any = 0; + + _bufferevent_incref_and_lock(bev); + be_filter_process_output(bevf, BEV_NORMAL, &processed_any); + _bufferevent_decref_and_unlock(bev); +} + +/* Called when the underlying socket has given us an error */ +static void +be_filter_eventcb(struct bufferevent *underlying, short what, void *_me) +{ + struct bufferevent_filtered *bevf = _me; + struct bufferevent *bev = downcast(bevf); + + _bufferevent_incref_and_lock(bev); + /* All we can really to is tell our own eventcb. */ + _bufferevent_run_eventcb(bev, what); + _bufferevent_decref_and_unlock(bev); +} + +static int +be_filter_flush(struct bufferevent *bufev, + short iotype, enum bufferevent_flush_mode mode) +{ + struct bufferevent_filtered *bevf = upcast(bufev); + int processed_any = 0; + EVUTIL_ASSERT(bevf); + + _bufferevent_incref_and_lock(bufev); + + if (iotype & EV_READ) { + be_filter_process_input(bevf, mode, &processed_any); + } + if (iotype & EV_WRITE) { + be_filter_process_output(bevf, mode, &processed_any); + } + /* XXX check the return value? */ + /* XXX does this want to recursively call lower-level flushes? */ + bufferevent_flush(bevf->underlying, iotype, mode); + + _bufferevent_decref_and_unlock(bufev); + + return processed_any; +} + +static int +be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, + union bufferevent_ctrl_data *data) +{ + struct bufferevent_filtered *bevf; + switch (op) { + case BEV_CTRL_GET_UNDERLYING: + bevf = upcast(bev); + data->ptr = bevf->underlying; + return 0; + case BEV_CTRL_GET_FD: + case BEV_CTRL_SET_FD: + case BEV_CTRL_CANCEL_ALL: + default: + return -1; + } +} diff --git a/libevent/bufferevent_openssl.c b/libevent/bufferevent_openssl.c new file mode 100644 index 0000000..412c08e --- /dev/null +++ b/libevent/bufferevent_openssl.c @@ -0,0 +1,1418 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#include + +#include "event2/event-config.h" + +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#ifdef _EVENT_HAVE_STDARG_H +#include +#endif +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif + +#ifdef WIN32 +#include +#endif + +#include "event2/bufferevent.h" +#include "event2/bufferevent_struct.h" +#include "event2/bufferevent_ssl.h" +#include "event2/buffer.h" +#include "event2/event.h" + +#include "mm-internal.h" +#include "bufferevent-internal.h" +#include "log-internal.h" + +#include +#include +#include + +/* + * Define an OpenSSL bio that targets a bufferevent. + */ + +/* -------------------- + A BIO is an OpenSSL abstraction that handles reading and writing data. The + library will happily speak SSL over anything that implements a BIO + interface. + + Here we define a BIO implementation that directs its output to a + bufferevent. We'll want to use this only when none of OpenSSL's built-in + IO mechanisms work for us. + -------------------- */ + +/* every BIO type needs its own integer type value. */ +#define BIO_TYPE_LIBEVENT 57 +/* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on + * this. */ + +#if 0 +static void +print_err(int val) +{ + int err; + printf("Error was %d\n", val); + + while ((err = ERR_get_error()))x { + const char *msg = (const char*)ERR_reason_error_string(err); + const char *lib = (const char*)ERR_lib_error_string(err); + const char *func = (const char*)ERR_func_error_string(err); + + printf("%s in %s %s\n", msg, lib, func); + } +} +#else +#define print_err(v) ((void)0) +#endif + +/* Called to initialize a new BIO */ +static int +bio_bufferevent_new(BIO *b) +{ + b->init = 0; + b->num = -1; + b->ptr = NULL; /* We'll be putting the bufferevent in this field.*/ + b->flags = 0; + return 1; +} + +/* Called to uninitialize the BIO. */ +static int +bio_bufferevent_free(BIO *b) +{ + if (!b) + return 0; + if (b->shutdown) { + if (b->init && b->ptr) + bufferevent_free(b->ptr); + b->init = 0; + b->flags = 0; + b->ptr = NULL; + } + return 1; +} + +/* Called to extract data from the BIO. */ +static int +bio_bufferevent_read(BIO *b, char *out, int outlen) +{ + int r = 0; + struct evbuffer *input; + + BIO_clear_retry_flags(b); + + if (!out) + return 0; + if (!b->ptr) + return -1; + + input = bufferevent_get_input(b->ptr); + if (evbuffer_get_length(input) == 0) { + /* If there's no data to read, say so. */ + BIO_set_retry_read(b); + return -1; + } else { + r = evbuffer_remove(input, out, outlen); + } + + return r; +} + +/* Called to write data info the BIO */ +static int +bio_bufferevent_write(BIO *b, const char *in, int inlen) +{ + struct bufferevent *bufev = b->ptr; + struct evbuffer *output; + size_t outlen; + + BIO_clear_retry_flags(b); + + if (!b->ptr) + return -1; + + output = bufferevent_get_output(bufev); + outlen = evbuffer_get_length(output); + + /* Copy only as much data onto the output buffer as can fit under the + * high-water mark. */ + if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) { + if (bufev->wm_write.high <= outlen) { + /* If no data can fit, we'll need to retry later. */ + BIO_set_retry_write(b); + return -1; + } + inlen = bufev->wm_write.high - outlen; + } + + EVUTIL_ASSERT(inlen > 0); + evbuffer_add(output, in, inlen); + return inlen; +} + +/* Called to handle various requests */ +static long +bio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + struct bufferevent *bufev = b->ptr; + long ret = 1; + + switch (cmd) { + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_PENDING: + ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0; + break; + case BIO_CTRL_WPENDING: + ret = evbuffer_get_length(bufferevent_get_output(bufev)) != 0; + break; + /* XXXX These two are given a special-case treatment because + * of cargo-cultism. I should come up with a better reason. */ + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +/* Called to write a string to the BIO */ +static int +bio_bufferevent_puts(BIO *b, const char *s) +{ + return bio_bufferevent_write(b, s, strlen(s)); +} + +/* Method table for the bufferevent BIO */ +static BIO_METHOD methods_bufferevent = { + BIO_TYPE_LIBEVENT, "bufferevent", + bio_bufferevent_write, + bio_bufferevent_read, + bio_bufferevent_puts, + NULL /* bio_bufferevent_gets */, + bio_bufferevent_ctrl, + bio_bufferevent_new, + bio_bufferevent_free, + NULL /* callback_ctrl */, +}; + +/* Return the method table for the bufferevents BIO */ +static BIO_METHOD * +BIO_s_bufferevent(void) +{ + return &methods_bufferevent; +} + +/* Create a new BIO to wrap communication around a bufferevent. If close_flag + * is true, the bufferevent will be freed when the BIO is closed. */ +static BIO * +BIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag) +{ + BIO *result; + if (!bufferevent) + return NULL; + if (!(result = BIO_new(BIO_s_bufferevent()))) + return NULL; + result->init = 1; + result->ptr = bufferevent; + result->shutdown = close_flag ? 1 : 0; + return result; +} + +/* -------------------- + Now, here's the OpenSSL-based implementation of bufferevent. + + The implementation comes in two flavors: one that connects its SSL object + to an underlying bufferevent using a BIO_bufferevent, and one that has the + SSL object connect to a socket directly. The latter should generally be + faster, except on Windows, where your best bet is using a + bufferevent_async. + + (OpenSSL supports many other BIO types, too. But we can't use any unless + we have a good way to get notified when they become readable/writable.) + -------------------- */ + +struct bio_data_counts { + unsigned long n_written; + unsigned long n_read; +}; + +struct bufferevent_openssl { + /* Shared fields with common bufferevent implementation code. + If we were set up with an underlying bufferevent, we use the + events here as timers only. If we have an SSL, then we use + the events as socket events. + */ + struct bufferevent_private bev; + /* An underlying bufferevent that we're directing our output to. + If it's NULL, then we're connected to an fd, not an evbuffer. */ + struct bufferevent *underlying; + /* The SSL object doing our encryption. */ + SSL *ssl; + + /* A callback that's invoked when data arrives on our outbuf so we + know to write data to the SSL. */ + struct evbuffer_cb_entry *outbuf_cb; + + /* A count of how much data the bios have read/written total. Used + for rate-limiting. */ + struct bio_data_counts counts; + + /* If this value is greater than 0, then the last SSL_write blocked, + * and we need to try it again with this many bytes. */ + ev_ssize_t last_write; + +#define NUM_ERRORS 3 + ev_uint32_t errors[NUM_ERRORS]; + + /* When we next get available space, we should say "read" instead of + "write". This can happen if there's a renegotiation during a read + operation. */ + unsigned read_blocked_on_write : 1; + /* When we next get data, we should say "write" instead of "read". */ + unsigned write_blocked_on_read : 1; + /* XXX */ + unsigned allow_dirty_shutdown : 1; + /* XXXX */ + unsigned fd_is_set : 1; + /* XXX */ + unsigned n_errors : 2; + + /* Are we currently connecting, accepting, or doing IO? */ + unsigned state : 2; +}; + +static int be_openssl_enable(struct bufferevent *, short); +static int be_openssl_disable(struct bufferevent *, short); +static void be_openssl_destruct(struct bufferevent *); +static int be_openssl_adj_timeouts(struct bufferevent *); +static int be_openssl_flush(struct bufferevent *bufev, + short iotype, enum bufferevent_flush_mode mode); +static int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); + +const struct bufferevent_ops bufferevent_ops_openssl = { + "ssl", + evutil_offsetof(struct bufferevent_openssl, bev.bev), + be_openssl_enable, + be_openssl_disable, + be_openssl_destruct, + be_openssl_adj_timeouts, + be_openssl_flush, + be_openssl_ctrl, +}; + +/* Given a bufferevent, return a pointer to the bufferevent_openssl that + * contains it, if any. */ +static inline struct bufferevent_openssl * +upcast(struct bufferevent *bev) +{ + struct bufferevent_openssl *bev_o; + if (bev->be_ops != &bufferevent_ops_openssl) + return NULL; + bev_o = (void*)( ((char*)bev) - + evutil_offsetof(struct bufferevent_openssl, bev.bev)); + EVUTIL_ASSERT(bev_o->bev.bev.be_ops == &bufferevent_ops_openssl); + return bev_o; +} + +static inline void +put_error(struct bufferevent_openssl *bev_ssl, unsigned long err) +{ + if (bev_ssl->n_errors == NUM_ERRORS) + return; + /* The error type according to openssl is "unsigned long", but + openssl never uses more than 32 bits of it. It _can't_ use more + than 32 bits of it, since it needs to report errors on systems + where long is only 32 bits. + */ + bev_ssl->errors[bev_ssl->n_errors++] = (ev_uint32_t) err; +} + +/* Have the base communications channel (either the underlying bufferevent or + * ev_read and ev_write) start reading. Take the read-blocked-on-write flag + * into account. */ +static int +start_reading(struct bufferevent_openssl *bev_ssl) +{ + if (bev_ssl->underlying) { + bufferevent_unsuspend_read(bev_ssl->underlying, + BEV_SUSPEND_FILT_READ); + return 0; + } else { + struct bufferevent *bev = &bev_ssl->bev.bev; + int r; + r = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); + if (r == 0 && bev_ssl->read_blocked_on_write) + r = _bufferevent_add_event(&bev->ev_write, + &bev->timeout_write); + return r; + } +} + +/* Have the base communications channel (either the underlying bufferevent or + * ev_read and ev_write) start writing. Take the write-blocked-on-read flag + * into account. */ +static int +start_writing(struct bufferevent_openssl *bev_ssl) +{ + int r = 0; + if (bev_ssl->underlying) { + ; + } else { + struct bufferevent *bev = &bev_ssl->bev.bev; + r = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); + if (!r && bev_ssl->write_blocked_on_read) + r = _bufferevent_add_event(&bev->ev_read, + &bev->timeout_read); + } + return r; +} + +static void +stop_reading(struct bufferevent_openssl *bev_ssl) +{ + if (bev_ssl->write_blocked_on_read) + return; + if (bev_ssl->underlying) { + bufferevent_suspend_read(bev_ssl->underlying, + BEV_SUSPEND_FILT_READ); + } else { + struct bufferevent *bev = &bev_ssl->bev.bev; + event_del(&bev->ev_read); + } +} + +static void +stop_writing(struct bufferevent_openssl *bev_ssl) +{ + if (bev_ssl->read_blocked_on_write) + return; + if (bev_ssl->underlying) { + ; + } else { + struct bufferevent *bev = &bev_ssl->bev.bev; + event_del(&bev->ev_write); + } +} + +static int +set_rbow(struct bufferevent_openssl *bev_ssl) +{ + if (!bev_ssl->underlying) + stop_reading(bev_ssl); + bev_ssl->read_blocked_on_write = 1; + return start_writing(bev_ssl); +} + +static int +set_wbor(struct bufferevent_openssl *bev_ssl) +{ + if (!bev_ssl->underlying) + stop_writing(bev_ssl); + bev_ssl->write_blocked_on_read = 1; + return start_reading(bev_ssl); +} + +static int +clear_rbow(struct bufferevent_openssl *bev_ssl) +{ + struct bufferevent *bev = &bev_ssl->bev.bev; + int r = 0; + bev_ssl->read_blocked_on_write = 0; + if (!(bev->enabled & EV_WRITE)) + stop_writing(bev_ssl); + if (bev->enabled & EV_READ) + r = start_reading(bev_ssl); + return r; +} + + +static int +clear_wbor(struct bufferevent_openssl *bev_ssl) +{ + struct bufferevent *bev = &bev_ssl->bev.bev; + int r = 0; + bev_ssl->write_blocked_on_read = 0; + if (!(bev->enabled & EV_READ)) + stop_reading(bev_ssl); + if (bev->enabled & EV_WRITE) + r = start_writing(bev_ssl); + return r; +} + +static void +conn_closed(struct bufferevent_openssl *bev_ssl, int errcode, int ret) +{ + int event = BEV_EVENT_ERROR; + int dirty_shutdown = 0; + unsigned long err; + + switch (errcode) { + case SSL_ERROR_ZERO_RETURN: + /* Possibly a clean shutdown. */ + if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN) + event = BEV_EVENT_EOF; + else + dirty_shutdown = 1; + break; + case SSL_ERROR_SYSCALL: + /* IO error; possibly a dirty shutdown. */ + if (ret == 0 && ERR_peek_error() == 0) + dirty_shutdown = 1; + break; + case SSL_ERROR_SSL: + /* Protocol error. */ + break; + case SSL_ERROR_WANT_X509_LOOKUP: + /* XXXX handle this. */ + break; + case SSL_ERROR_NONE: + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + default: + /* should be impossible; treat as normal error. */ + event_warnx("BUG: Unexpected OpenSSL error code %d", errcode); + break; + } + + while ((err = ERR_get_error())) { + put_error(bev_ssl, err); + } + + if (dirty_shutdown && bev_ssl->allow_dirty_shutdown) + event = BEV_EVENT_EOF; + + stop_reading(bev_ssl); + stop_writing(bev_ssl); + + _bufferevent_run_eventcb(&bev_ssl->bev.bev, event); +} + +static void +init_bio_counts(struct bufferevent_openssl *bev_ssl) +{ + bev_ssl->counts.n_written = + BIO_number_written(SSL_get_wbio(bev_ssl->ssl)); + bev_ssl->counts.n_read = + BIO_number_read(SSL_get_rbio(bev_ssl->ssl)); +} + +static inline void +decrement_buckets(struct bufferevent_openssl *bev_ssl) +{ + unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl)); + unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl)); + /* These next two subtractions can wrap around. That's okay. */ + unsigned long w = num_w - bev_ssl->counts.n_written; + unsigned long r = num_r - bev_ssl->counts.n_read; + if (w) + _bufferevent_decrement_write_buckets(&bev_ssl->bev, w); + if (r) + _bufferevent_decrement_read_buckets(&bev_ssl->bev, r); + bev_ssl->counts.n_written = num_w; + bev_ssl->counts.n_read = num_r; +} + +/* returns -1 on internal error, 0 on stall, 1 on progress */ +static int +do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) +{ + /* Requires lock */ + struct bufferevent *bev = &bev_ssl->bev.bev; + struct evbuffer *input = bev->input; + int r, n, i, n_used = 0, blocked = 0, atmost; + struct evbuffer_iovec space[2]; + + atmost = _bufferevent_get_read_max(&bev_ssl->bev); + if (n_to_read > atmost) + n_to_read = atmost; + + n = evbuffer_reserve_space(input, n_to_read, space, 2); + if (n < 0) + return -1; + + for (i=0; ibev.read_suspended) + break; + r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len); + if (r>0) { + if (bev_ssl->read_blocked_on_write) + if (clear_rbow(bev_ssl) < 0) + return -1; + ++n_used; + space[i].iov_len = r; + decrement_buckets(bev_ssl); + } else { + int err = SSL_get_error(bev_ssl->ssl, r); + print_err(err); + switch (err) { + case SSL_ERROR_WANT_READ: + /* Can't read until underlying has more data. */ + if (bev_ssl->read_blocked_on_write) + if (clear_rbow(bev_ssl) < 0) + return -1; + break; + case SSL_ERROR_WANT_WRITE: + /* This read operation requires a write, and the + * underlying is full */ + if (!bev_ssl->read_blocked_on_write) + if (set_rbow(bev_ssl) < 0) + return -1; + break; + default: + conn_closed(bev_ssl, err, r); + break; + } + blocked = 1; + break; /* out of the loop */ + } + } + + if (n_used) { + evbuffer_commit_space(input, space, n_used); + if (bev_ssl->underlying) + BEV_RESET_GENERIC_READ_TIMEOUT(bev); + + if (evbuffer_get_length(input) >= bev->wm_read.low) + _bufferevent_run_readcb(bev); + } + + return blocked ? 0 : 1; +} + +static int +do_write(struct bufferevent_openssl *bev_ssl, int atmost) +{ + int i, r, n, n_written = 0, blocked=0; + struct bufferevent *bev = &bev_ssl->bev.bev; + struct evbuffer *output = bev->output; + struct evbuffer_iovec space[8]; + + if (bev_ssl->last_write > 0) + atmost = bev_ssl->last_write; + else + atmost = _bufferevent_get_write_max(&bev_ssl->bev); + + n = evbuffer_peek(output, atmost, NULL, space, 8); + if (n < 0) + return -1; + + if (n > 8) + n = 8; + for (i=0; i < n; ++i) { + if (bev_ssl->bev.write_suspended) + break; + + /* SSL_write will (reasonably) return 0 if we tell it to + send 0 data. Skip this case so we don't interpret the + result as an error */ + if (space[i].iov_len == 0) + continue; + + r = SSL_write(bev_ssl->ssl, space[i].iov_base, + space[i].iov_len); + if (r > 0) { + if (bev_ssl->write_blocked_on_read) + if (clear_wbor(bev_ssl) < 0) + return -1; + n_written += r; + bev_ssl->last_write = -1; + decrement_buckets(bev_ssl); + } else { + int err = SSL_get_error(bev_ssl->ssl, r); + print_err(err); + switch (err) { + case SSL_ERROR_WANT_WRITE: + /* Can't read until underlying has more data. */ + if (bev_ssl->write_blocked_on_read) + if (clear_wbor(bev_ssl) < 0) + return -1; + bev_ssl->last_write = space[i].iov_len; + break; + case SSL_ERROR_WANT_READ: + /* This read operation requires a write, and the + * underlying is full */ + if (!bev_ssl->write_blocked_on_read) + if (set_wbor(bev_ssl) < 0) + return -1; + bev_ssl->last_write = space[i].iov_len; + break; + default: + conn_closed(bev_ssl, err, r); + bev_ssl->last_write = -1; + break; + } + blocked = 1; + break; + } + } + if (n_written) { + evbuffer_drain(output, n_written); + if (bev_ssl->underlying) + BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); + + if (evbuffer_get_length(output) <= bev->wm_write.low) + _bufferevent_run_writecb(bev); + } + return blocked ? 0 : 1; +} + +#define WRITE_FRAME 15000 + +#define READ_DEFAULT 4096 + +/* Try to figure out how many bytes to read; return 0 if we shouldn't be + * reading. */ +static int +bytes_to_read(struct bufferevent_openssl *bev) +{ + struct evbuffer *input = bev->bev.bev.input; + struct event_watermark *wm = &bev->bev.bev.wm_read; + int result = READ_DEFAULT; + ev_ssize_t limit; + /* XXX 99% of this is generic code that nearly all bufferevents will + * want. */ + + if (bev->write_blocked_on_read) { + return 0; + } + + if (! (bev->bev.bev.enabled & EV_READ)) { + return 0; + } + + if (bev->bev.read_suspended) { + return 0; + } + + if (wm->high) { + if (evbuffer_get_length(input) >= wm->high) { + return 0; + } + + result = wm->high - evbuffer_get_length(input); + } else { + result = READ_DEFAULT; + } + + /* Respect the rate limit */ + limit = _bufferevent_get_read_max(&bev->bev); + if (result > limit) { + result = limit; + } + + return result; +} + + +/* Things look readable. If write is blocked on read, write till it isn't. + * Read from the underlying buffer until we block or we hit our high-water + * mark. + */ +static void +consider_reading(struct bufferevent_openssl *bev_ssl) +{ + int r; + int n_to_read; + + while (bev_ssl->write_blocked_on_read) { + r = do_write(bev_ssl, WRITE_FRAME); + if (r <= 0) + break; + } + if (bev_ssl->write_blocked_on_read) + return; + + n_to_read = bytes_to_read(bev_ssl); + + while (n_to_read) { + if (do_read(bev_ssl, n_to_read) <= 0) + break; + + /* Read all pending data. This won't hit the network + * again, and will (most importantly) put us in a state + * where we don't need to read anything else until the + * socket is readable again. It'll potentially make us + * overrun our read high-watermark (somewhat + * regrettable). The damage to the rate-limit has + * already been done, since OpenSSL went and read a + * whole SSL record anyway. */ + n_to_read = SSL_pending(bev_ssl->ssl); + + /* XXX This if statement is actually a bad bug, added to avoid + * XXX a worse bug. + * + * The bad bug: It can potentially cause resource unfairness + * by reading too much data from the underlying bufferevent; + * it can potentially cause read looping if the underlying + * bufferevent is a bufferevent_pair and deferred callbacks + * aren't used. + * + * The worse bug: If we didn't do this, then we would + * potentially not read any more from bev_ssl->underlying + * until more data arrived there, which could lead to us + * waiting forever. + */ + if (!n_to_read && bev_ssl->underlying) + n_to_read = bytes_to_read(bev_ssl); + } + + if (!bev_ssl->underlying) { + /* Should be redundant, but let's avoid busy-looping */ + if (bev_ssl->bev.read_suspended || + !(bev_ssl->bev.bev.enabled & EV_READ)) { + event_del(&bev_ssl->bev.bev.ev_read); + } + } +} + +static void +consider_writing(struct bufferevent_openssl *bev_ssl) +{ + int r; + struct evbuffer *output = bev_ssl->bev.bev.output; + struct evbuffer *target = NULL; + struct event_watermark *wm = NULL; + + while (bev_ssl->read_blocked_on_write) { + r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */ + if (r <= 0) + break; + } + if (bev_ssl->read_blocked_on_write) + return; + if (bev_ssl->underlying) { + target = bev_ssl->underlying->output; + wm = &bev_ssl->underlying->wm_write; + } + while ((bev_ssl->bev.bev.enabled & EV_WRITE) && + (! bev_ssl->bev.write_suspended) && + evbuffer_get_length(output) && + (!target || (! wm->high || evbuffer_get_length(target) < wm->high))) { + int n_to_write; + if (wm && wm->high) + n_to_write = wm->high - evbuffer_get_length(target); + else + n_to_write = WRITE_FRAME; + r = do_write(bev_ssl, n_to_write); + if (r <= 0) + break; + } + + if (!bev_ssl->underlying) { + if (evbuffer_get_length(output) == 0) { + event_del(&bev_ssl->bev.bev.ev_write); + } else if (bev_ssl->bev.write_suspended || + !(bev_ssl->bev.bev.enabled & EV_WRITE)) { + /* Should be redundant, but let's avoid busy-looping */ + event_del(&bev_ssl->bev.bev.ev_write); + } + } +} + +static void +be_openssl_readcb(struct bufferevent *bev_base, void *ctx) +{ + struct bufferevent_openssl *bev_ssl = ctx; + consider_reading(bev_ssl); +} + +static void +be_openssl_writecb(struct bufferevent *bev_base, void *ctx) +{ + struct bufferevent_openssl *bev_ssl = ctx; + consider_writing(bev_ssl); +} + +static void +be_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx) +{ + struct bufferevent_openssl *bev_ssl = ctx; + int event = 0; + + if (what & BEV_EVENT_EOF) { + if (bev_ssl->allow_dirty_shutdown) + event = BEV_EVENT_EOF; + else + event = BEV_EVENT_ERROR; + } else if (what & BEV_EVENT_TIMEOUT) { + /* We sure didn't set this. Propagate it to the user. */ + event = what; + } else if (what & BEV_EVENT_ERROR) { + /* An error occurred on the connection. Propagate it to the user. */ + event = what; + } else if (what & BEV_EVENT_CONNECTED) { + /* Ignore it. We're saying SSL_connect() already, which will + eat it. */ + } + if (event) + _bufferevent_run_eventcb(&bev_ssl->bev.bev, event); +} + +static void +be_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr) +{ + struct bufferevent_openssl *bev_ssl = ptr; + _bufferevent_incref_and_lock(&bev_ssl->bev.bev); + if (what & EV_TIMEOUT) { + _bufferevent_run_eventcb(&bev_ssl->bev.bev, + BEV_EVENT_TIMEOUT|BEV_EVENT_READING); + } else + consider_reading(bev_ssl); + _bufferevent_decref_and_unlock(&bev_ssl->bev.bev); +} + +static void +be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr) +{ + struct bufferevent_openssl *bev_ssl = ptr; + _bufferevent_incref_and_lock(&bev_ssl->bev.bev); + if (what & EV_TIMEOUT) { + _bufferevent_run_eventcb(&bev_ssl->bev.bev, + BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING); + } + consider_writing(bev_ssl); + _bufferevent_decref_and_unlock(&bev_ssl->bev.bev); +} + +static int +set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) +{ + if (bev_ssl->underlying) { + bufferevent_setcb(bev_ssl->underlying, + be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb, + bev_ssl); + return 0; + } else { + struct bufferevent *bev = &bev_ssl->bev.bev; + int rpending=0, wpending=0, r1=0, r2=0; + if (fd < 0 && bev_ssl->fd_is_set) + fd = event_get_fd(&bev->ev_read); + if (bev_ssl->fd_is_set) { + rpending = event_pending(&bev->ev_read, EV_READ, NULL); + wpending = event_pending(&bev->ev_write, EV_WRITE, NULL); + event_del(&bev->ev_read); + event_del(&bev->ev_write); + } + event_assign(&bev->ev_read, bev->ev_base, fd, + EV_READ|EV_PERSIST, be_openssl_readeventcb, bev_ssl); + event_assign(&bev->ev_write, bev->ev_base, fd, + EV_WRITE|EV_PERSIST, be_openssl_writeeventcb, bev_ssl); + if (rpending) + r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); + if (wpending) + r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); + if (fd >= 0) { + bev_ssl->fd_is_set = 1; + } + return (r1<0 || r2<0) ? -1 : 0; + } +} + +static int +do_handshake(struct bufferevent_openssl *bev_ssl) +{ + int r; + + switch (bev_ssl->state) { + default: + case BUFFEREVENT_SSL_OPEN: + EVUTIL_ASSERT(0); + return -1; + case BUFFEREVENT_SSL_CONNECTING: + case BUFFEREVENT_SSL_ACCEPTING: + r = SSL_do_handshake(bev_ssl->ssl); + break; + } + decrement_buckets(bev_ssl); + + if (r==1) { + /* We're done! */ + bev_ssl->state = BUFFEREVENT_SSL_OPEN; + set_open_callbacks(bev_ssl, -1); /* XXXX handle failure */ + /* Call do_read and do_write as needed */ + bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled); + _bufferevent_run_eventcb(&bev_ssl->bev.bev, + BEV_EVENT_CONNECTED); + return 1; + } else { + int err = SSL_get_error(bev_ssl->ssl, r); + print_err(err); + switch (err) { + case SSL_ERROR_WANT_WRITE: + if (!bev_ssl->underlying) { + stop_reading(bev_ssl); + return start_writing(bev_ssl); + } + return 0; + case SSL_ERROR_WANT_READ: + if (!bev_ssl->underlying) { + stop_writing(bev_ssl); + return start_reading(bev_ssl); + } + return 0; + default: + conn_closed(bev_ssl, err, r); + return -1; + } + } +} + +static void +be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx) +{ + struct bufferevent_openssl *bev_ssl = ctx; + do_handshake(bev_ssl);/* XXX handle failure */ +} + +static void +be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr) +{ + struct bufferevent_openssl *bev_ssl = ptr; + + _bufferevent_incref_and_lock(&bev_ssl->bev.bev); + if (what & EV_TIMEOUT) { + _bufferevent_run_eventcb(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT); + } else + do_handshake(bev_ssl);/* XXX handle failure */ + _bufferevent_decref_and_unlock(&bev_ssl->bev.bev); +} + +static int +set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) +{ + if (bev_ssl->underlying) { + bufferevent_setcb(bev_ssl->underlying, + be_openssl_handshakecb, be_openssl_handshakecb, + be_openssl_eventcb, + bev_ssl); + return do_handshake(bev_ssl); + } else { + struct bufferevent *bev = &bev_ssl->bev.bev; + int r1=0, r2=0; + if (fd < 0 && bev_ssl->fd_is_set) + fd = event_get_fd(&bev->ev_read); + if (bev_ssl->fd_is_set) { + event_del(&bev->ev_read); + event_del(&bev->ev_write); + } + event_assign(&bev->ev_read, bev->ev_base, fd, + EV_READ|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl); + event_assign(&bev->ev_write, bev->ev_base, fd, + EV_WRITE|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl); + if (fd >= 0) { + r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); + r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); + bev_ssl->fd_is_set = 1; + } + return (r1<0 || r2<0) ? -1 : 0; + } +} + +int +bufferevent_ssl_renegotiate(struct bufferevent *bev) +{ + struct bufferevent_openssl *bev_ssl = upcast(bev); + if (!bev_ssl) + return -1; + if (SSL_renegotiate(bev_ssl->ssl) < 0) + return -1; + bev_ssl->state = BUFFEREVENT_SSL_CONNECTING; + if (set_handshake_callbacks(bev_ssl, -1) < 0) + return -1; + if (!bev_ssl->underlying) + return do_handshake(bev_ssl); + return 0; +} + +static void +be_openssl_outbuf_cb(struct evbuffer *buf, + const struct evbuffer_cb_info *cbinfo, void *arg) +{ + struct bufferevent_openssl *bev_ssl = arg; + int r = 0; + /* XXX need to hold a reference here. */ + + if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) { + if (cbinfo->orig_size == 0) + r = _bufferevent_add_event(&bev_ssl->bev.bev.ev_write, + &bev_ssl->bev.bev.timeout_write); + consider_writing(bev_ssl); + } + /* XXX Handle r < 0 */ + (void)r; +} + + +static int +be_openssl_enable(struct bufferevent *bev, short events) +{ + struct bufferevent_openssl *bev_ssl = upcast(bev); + int r1 = 0, r2 = 0; + + if (bev_ssl->state != BUFFEREVENT_SSL_OPEN) + return 0; + + if (events & EV_READ) + r1 = start_reading(bev_ssl); + if (events & EV_WRITE) + r2 = start_writing(bev_ssl); + + if (bev_ssl->underlying) { + if (events & EV_READ) + BEV_RESET_GENERIC_READ_TIMEOUT(bev); + if (events & EV_WRITE) + BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); + + if (events & EV_READ) + consider_reading(bev_ssl); + if (events & EV_WRITE) + consider_writing(bev_ssl); + } + return (r1 < 0 || r2 < 0) ? -1 : 0; +} + +static int +be_openssl_disable(struct bufferevent *bev, short events) +{ + struct bufferevent_openssl *bev_ssl = upcast(bev); + if (bev_ssl->state != BUFFEREVENT_SSL_OPEN) + return 0; + + if (events & EV_READ) + stop_reading(bev_ssl); + if (events & EV_WRITE) + stop_writing(bev_ssl); + + if (bev_ssl->underlying) { + if (events & EV_READ) + BEV_DEL_GENERIC_READ_TIMEOUT(bev); + if (events & EV_WRITE) + BEV_DEL_GENERIC_WRITE_TIMEOUT(bev); + } + return 0; +} + +static void +be_openssl_destruct(struct bufferevent *bev) +{ + struct bufferevent_openssl *bev_ssl = upcast(bev); + + if (bev_ssl->underlying) { + _bufferevent_del_generic_timeout_cbs(bev); + } else { + event_del(&bev->ev_read); + event_del(&bev->ev_write); + } + + if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) { + if (bev_ssl->underlying) { + if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) { + event_warnx("BEV_OPT_CLOSE_ON_FREE set on an " + "bufferevent with too few references"); + } else { + bufferevent_free(bev_ssl->underlying); + bev_ssl->underlying = NULL; + } + } else { + evutil_socket_t fd = -1; + BIO *bio = SSL_get_wbio(bev_ssl->ssl); + if (bio) + fd = BIO_get_fd(bio, NULL); + if (fd >= 0) + evutil_closesocket(fd); + } + SSL_free(bev_ssl->ssl); + } else { + if (bev_ssl->underlying) { + if (bev_ssl->underlying->errorcb == be_openssl_eventcb) + bufferevent_setcb(bev_ssl->underlying, + NULL,NULL,NULL,NULL); + bufferevent_unsuspend_read(bev_ssl->underlying, + BEV_SUSPEND_FILT_READ); + } + } +} + +static int +be_openssl_adj_timeouts(struct bufferevent *bev) +{ + struct bufferevent_openssl *bev_ssl = upcast(bev); + + if (bev_ssl->underlying) + return _bufferevent_generic_adj_timeouts(bev); + else { + int r1=0, r2=0; + if (event_pending(&bev->ev_read, EV_READ, NULL)) + r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read); + if (event_pending(&bev->ev_write, EV_WRITE, NULL)) + r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write); + return (r1<0 || r2<0) ? -1 : 0; + } +} + +static int +be_openssl_flush(struct bufferevent *bufev, + short iotype, enum bufferevent_flush_mode mode) +{ + /* XXXX Implement this. */ + return 0; +} + +static int +be_openssl_ctrl(struct bufferevent *bev, + enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data) +{ + struct bufferevent_openssl *bev_ssl = upcast(bev); + switch (op) { + case BEV_CTRL_SET_FD: + if (bev_ssl->underlying) + return -1; + { + BIO *bio; + bio = BIO_new_socket(data->fd, 0); + SSL_set_bio(bev_ssl->ssl, bio, bio); + bev_ssl->fd_is_set = 1; + } + if (bev_ssl->state == BUFFEREVENT_SSL_OPEN) + return set_open_callbacks(bev_ssl, data->fd); + else { + return set_handshake_callbacks(bev_ssl, data->fd); + } + case BEV_CTRL_GET_FD: + if (bev_ssl->underlying) + return -1; + if (!bev_ssl->fd_is_set) + return -1; + data->fd = event_get_fd(&bev->ev_read); + return 0; + case BEV_CTRL_GET_UNDERLYING: + if (!bev_ssl->underlying) + return -1; + data->ptr = bev_ssl->underlying; + return 0; + case BEV_CTRL_CANCEL_ALL: + default: + return -1; + } +} + +SSL * +bufferevent_openssl_get_ssl(struct bufferevent *bufev) +{ + struct bufferevent_openssl *bev_ssl = upcast(bufev); + if (!bev_ssl) + return NULL; + return bev_ssl->ssl; +} + +static struct bufferevent * +bufferevent_openssl_new_impl(struct event_base *base, + struct bufferevent *underlying, + evutil_socket_t fd, + SSL *ssl, + enum bufferevent_ssl_state state, + int options) +{ + struct bufferevent_openssl *bev_ssl = NULL; + struct bufferevent_private *bev_p = NULL; + int tmp_options = options & ~BEV_OPT_THREADSAFE; + + if (underlying != NULL && fd >= 0) + return NULL; /* Only one can be set. */ + + if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl)))) + goto err; + + bev_p = &bev_ssl->bev; + + if (bufferevent_init_common(bev_p, base, + &bufferevent_ops_openssl, tmp_options) < 0) + goto err; + + /* Don't explode if we decide to realloc a chunk we're writing from in + * the output buffer. */ + SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + bev_ssl->underlying = underlying; + bev_ssl->ssl = ssl; + + bev_ssl->outbuf_cb = evbuffer_add_cb(bev_p->bev.output, + be_openssl_outbuf_cb, bev_ssl); + + if (options & BEV_OPT_THREADSAFE) + bufferevent_enable_locking(&bev_ssl->bev.bev, NULL); + + if (underlying) { + _bufferevent_init_generic_timeout_cbs(&bev_ssl->bev.bev); + bufferevent_incref(underlying); + } + + bev_ssl->state = state; + bev_ssl->last_write = -1; + + init_bio_counts(bev_ssl); + + switch (state) { + case BUFFEREVENT_SSL_ACCEPTING: + SSL_set_accept_state(bev_ssl->ssl); + if (set_handshake_callbacks(bev_ssl, fd) < 0) + goto err; + break; + case BUFFEREVENT_SSL_CONNECTING: + SSL_set_connect_state(bev_ssl->ssl); + if (set_handshake_callbacks(bev_ssl, fd) < 0) + goto err; + break; + case BUFFEREVENT_SSL_OPEN: + if (set_open_callbacks(bev_ssl, fd) < 0) + goto err; + break; + default: + goto err; + } + + if (underlying) { + bufferevent_setwatermark(underlying, EV_READ, 0, 0); + bufferevent_enable(underlying, EV_READ|EV_WRITE); + if (state == BUFFEREVENT_SSL_OPEN) + bufferevent_suspend_read(underlying, + BEV_SUSPEND_FILT_READ); + } else { + bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE; + if (bev_ssl->fd_is_set) { + if (state != BUFFEREVENT_SSL_OPEN) + if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0) + goto err; + if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0) + goto err; + } + } + + return &bev_ssl->bev.bev; +err: + if (bev_ssl) + bufferevent_free(&bev_ssl->bev.bev); + return NULL; +} + +struct bufferevent * +bufferevent_openssl_filter_new(struct event_base *base, + struct bufferevent *underlying, + SSL *ssl, + enum bufferevent_ssl_state state, + int options) +{ + /* We don't tell the BIO to close the bufferevent; we do it ourselves + * on be_openssl_destruct */ + int close_flag = 0; /* options & BEV_OPT_CLOSE_ON_FREE; */ + BIO *bio; + if (!underlying) + return NULL; + if (!(bio = BIO_new_bufferevent(underlying, close_flag))) + return NULL; + + SSL_set_bio(ssl, bio, bio); + + return bufferevent_openssl_new_impl( + base, underlying, -1, ssl, state, options); +} + +struct bufferevent * +bufferevent_openssl_socket_new(struct event_base *base, + evutil_socket_t fd, + SSL *ssl, + enum bufferevent_ssl_state state, + int options) +{ + /* Does the SSL already have an fd? */ + BIO *bio = SSL_get_wbio(ssl); + long have_fd = -1; + + if (bio) + have_fd = BIO_get_fd(bio, NULL); + + if (have_fd >= 0) { + /* The SSL is already configured with an fd. */ + if (fd < 0) { + /* We should learn the fd from the SSL. */ + fd = (evutil_socket_t) have_fd; + } else if (have_fd == (long)fd) { + /* We already know the fd from the SSL; do nothing */ + } else { + /* We specified an fd different from that of the SSL. + This is probably an error on our part. Fail. */ + return NULL; + } + (void) BIO_set_close(bio, 0); + } else { + /* The SSL isn't configured with a BIO with an fd. */ + if (fd >= 0) { + /* ... and we have an fd we want to use. */ + bio = BIO_new_socket(fd, 0); + SSL_set_bio(ssl, bio, bio); + } else { + /* Leave the fd unset. */ + } + } + + return bufferevent_openssl_new_impl( + base, NULL, fd, ssl, state, options); +} + +unsigned long +bufferevent_get_openssl_error(struct bufferevent *bev) +{ + unsigned long err = 0; + struct bufferevent_openssl *bev_ssl; + BEV_LOCK(bev); + bev_ssl = upcast(bev); + if (bev_ssl && bev_ssl->n_errors) { + err = bev_ssl->errors[--bev_ssl->n_errors]; + } + BEV_UNLOCK(bev); + return err; +} diff --git a/libevent/bufferevent_pair.c b/libevent/bufferevent_pair.c new file mode 100644 index 0000000..6ec5cac --- /dev/null +++ b/libevent/bufferevent_pair.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2009-2012 Niels Provos, Nick Mathewson + * + * 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. + */ + +#include + +#ifdef WIN32 +#include +#endif + +#include "event2/event-config.h" + +#include "event2/util.h" +#include "event2/buffer.h" +#include "event2/bufferevent.h" +#include "event2/bufferevent_struct.h" +#include "event2/event.h" +#include "defer-internal.h" +#include "bufferevent-internal.h" +#include "mm-internal.h" +#include "util-internal.h" + +struct bufferevent_pair { + struct bufferevent_private bev; + struct bufferevent_pair *partner; +}; + + +/* Given a bufferevent that's really a bev part of a bufferevent_pair, + * return that bufferevent_filtered. Returns NULL otherwise.*/ +static inline struct bufferevent_pair * +upcast(struct bufferevent *bev) +{ + struct bufferevent_pair *bev_p; + if (bev->be_ops != &bufferevent_ops_pair) + return NULL; + bev_p = EVUTIL_UPCAST(bev, struct bufferevent_pair, bev.bev); + EVUTIL_ASSERT(bev_p->bev.bev.be_ops == &bufferevent_ops_pair); + return bev_p; +} + +#define downcast(bev_pair) (&(bev_pair)->bev.bev) + +static inline void +incref_and_lock(struct bufferevent *b) +{ + struct bufferevent_pair *bevp; + _bufferevent_incref_and_lock(b); + bevp = upcast(b); + if (bevp->partner) + _bufferevent_incref_and_lock(downcast(bevp->partner)); +} + +static inline void +decref_and_unlock(struct bufferevent *b) +{ + struct bufferevent_pair *bevp = upcast(b); + if (bevp->partner) + _bufferevent_decref_and_unlock(downcast(bevp->partner)); + _bufferevent_decref_and_unlock(b); +} + +/* XXX Handle close */ + +static void be_pair_outbuf_cb(struct evbuffer *, + const struct evbuffer_cb_info *, void *); + +static struct bufferevent_pair * +bufferevent_pair_elt_new(struct event_base *base, + int options) +{ + struct bufferevent_pair *bufev; + if (! (bufev = mm_calloc(1, sizeof(struct bufferevent_pair)))) + return NULL; + if (bufferevent_init_common(&bufev->bev, base, &bufferevent_ops_pair, + options)) { + mm_free(bufev); + return NULL; + } + if (!evbuffer_add_cb(bufev->bev.bev.output, be_pair_outbuf_cb, bufev)) { + bufferevent_free(downcast(bufev)); + return NULL; + } + + _bufferevent_init_generic_timeout_cbs(&bufev->bev.bev); + + return bufev; +} + +int +bufferevent_pair_new(struct event_base *base, int options, + struct bufferevent *pair[2]) +{ + struct bufferevent_pair *bufev1 = NULL, *bufev2 = NULL; + int tmp_options; + + options |= BEV_OPT_DEFER_CALLBACKS; + tmp_options = options & ~BEV_OPT_THREADSAFE; + + bufev1 = bufferevent_pair_elt_new(base, options); + if (!bufev1) + return -1; + bufev2 = bufferevent_pair_elt_new(base, tmp_options); + if (!bufev2) { + bufferevent_free(downcast(bufev1)); + return -1; + } + + if (options & BEV_OPT_THREADSAFE) { + /*XXXX check return */ + bufferevent_enable_locking(downcast(bufev2), bufev1->bev.lock); + } + + bufev1->partner = bufev2; + bufev2->partner = bufev1; + + evbuffer_freeze(downcast(bufev1)->input, 0); + evbuffer_freeze(downcast(bufev1)->output, 1); + evbuffer_freeze(downcast(bufev2)->input, 0); + evbuffer_freeze(downcast(bufev2)->output, 1); + + pair[0] = downcast(bufev1); + pair[1] = downcast(bufev2); + + return 0; +} + +static void +be_pair_transfer(struct bufferevent *src, struct bufferevent *dst, + int ignore_wm) +{ + size_t src_size, dst_size; + size_t n; + + evbuffer_unfreeze(src->output, 1); + evbuffer_unfreeze(dst->input, 0); + + if (dst->wm_read.high) { + dst_size = evbuffer_get_length(dst->input); + if (dst_size < dst->wm_read.high) { + n = dst->wm_read.high - dst_size; + evbuffer_remove_buffer(src->output, dst->input, n); + } else { + if (!ignore_wm) + goto done; + n = evbuffer_get_length(src->output); + evbuffer_add_buffer(dst->input, src->output); + } + } else { + n = evbuffer_get_length(src->output); + evbuffer_add_buffer(dst->input, src->output); + } + + if (n) { + BEV_RESET_GENERIC_READ_TIMEOUT(dst); + + if (evbuffer_get_length(dst->output)) + BEV_RESET_GENERIC_WRITE_TIMEOUT(dst); + else + BEV_DEL_GENERIC_WRITE_TIMEOUT(dst); + } + + src_size = evbuffer_get_length(src->output); + dst_size = evbuffer_get_length(dst->input); + + if (dst_size >= dst->wm_read.low) { + _bufferevent_run_readcb(dst); + } + if (src_size <= src->wm_write.low) { + _bufferevent_run_writecb(src); + } +done: + evbuffer_freeze(src->output, 1); + evbuffer_freeze(dst->input, 0); +} + +static inline int +be_pair_wants_to_talk(struct bufferevent_pair *src, + struct bufferevent_pair *dst) +{ + return (downcast(src)->enabled & EV_WRITE) && + (downcast(dst)->enabled & EV_READ) && + !dst->bev.read_suspended && + evbuffer_get_length(downcast(src)->output); +} + +static void +be_pair_outbuf_cb(struct evbuffer *outbuf, + const struct evbuffer_cb_info *info, void *arg) +{ + struct bufferevent_pair *bev_pair = arg; + struct bufferevent_pair *partner = bev_pair->partner; + + incref_and_lock(downcast(bev_pair)); + + if (info->n_added > info->n_deleted && partner) { + /* We got more data. If the other side's reading, then + hand it over. */ + if (be_pair_wants_to_talk(bev_pair, partner)) { + be_pair_transfer(downcast(bev_pair), downcast(partner), 0); + } + } + + decref_and_unlock(downcast(bev_pair)); +} + +static int +be_pair_enable(struct bufferevent *bufev, short events) +{ + struct bufferevent_pair *bev_p = upcast(bufev); + struct bufferevent_pair *partner = bev_p->partner; + + incref_and_lock(bufev); + + if (events & EV_READ) { + BEV_RESET_GENERIC_READ_TIMEOUT(bufev); + } + if ((events & EV_WRITE) && evbuffer_get_length(bufev->output)) + BEV_RESET_GENERIC_WRITE_TIMEOUT(bufev); + + /* We're starting to read! Does the other side have anything to write?*/ + if ((events & EV_READ) && partner && + be_pair_wants_to_talk(partner, bev_p)) { + be_pair_transfer(downcast(partner), bufev, 0); + } + /* We're starting to write! Does the other side want to read? */ + if ((events & EV_WRITE) && partner && + be_pair_wants_to_talk(bev_p, partner)) { + be_pair_transfer(bufev, downcast(partner), 0); + } + decref_and_unlock(bufev); + return 0; +} + +static int +be_pair_disable(struct bufferevent *bev, short events) +{ + if (events & EV_READ) { + BEV_DEL_GENERIC_READ_TIMEOUT(bev); + } + if (events & EV_WRITE) + BEV_DEL_GENERIC_WRITE_TIMEOUT(bev); + return 0; +} + +static void +be_pair_destruct(struct bufferevent *bev) +{ + struct bufferevent_pair *bev_p = upcast(bev); + + if (bev_p->partner) { + bev_p->partner->partner = NULL; + bev_p->partner = NULL; + } + + _bufferevent_del_generic_timeout_cbs(bev); +} + +static int +be_pair_flush(struct bufferevent *bev, short iotype, + enum bufferevent_flush_mode mode) +{ + struct bufferevent_pair *bev_p = upcast(bev); + struct bufferevent *partner; + incref_and_lock(bev); + if (!bev_p->partner) + return -1; + + partner = downcast(bev_p->partner); + + if (mode == BEV_NORMAL) + return 0; + + if ((iotype & EV_READ) != 0) + be_pair_transfer(partner, bev, 1); + + if ((iotype & EV_WRITE) != 0) + be_pair_transfer(bev, partner, 1); + + if (mode == BEV_FINISHED) { + _bufferevent_run_eventcb(partner, iotype|BEV_EVENT_EOF); + } + decref_and_unlock(bev); + return 0; +} + +struct bufferevent * +bufferevent_pair_get_partner(struct bufferevent *bev) +{ + struct bufferevent_pair *bev_p; + struct bufferevent *partner; + bev_p = upcast(bev); + if (! bev_p) + return NULL; + + incref_and_lock(bev); + partner = downcast(bev_p->partner); + decref_and_unlock(bev); + return partner; +} + +const struct bufferevent_ops bufferevent_ops_pair = { + "pair_elt", + evutil_offsetof(struct bufferevent_pair, bev.bev), + be_pair_enable, + be_pair_disable, + be_pair_destruct, + _bufferevent_generic_adj_timeouts, + be_pair_flush, + NULL, /* ctrl */ +}; diff --git a/libevent/bufferevent_ratelim.c b/libevent/bufferevent_ratelim.c new file mode 100644 index 0000000..7965390 --- /dev/null +++ b/libevent/bufferevent_ratelim.c @@ -0,0 +1,1011 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * Copyright (c) 2002-2006 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + */ + +#include +#include +#include +#include + +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/util.h" +#include "event2/bufferevent.h" +#include "event2/bufferevent_struct.h" +#include "event2/buffer.h" + +#include "ratelim-internal.h" + +#include "bufferevent-internal.h" +#include "mm-internal.h" +#include "util-internal.h" +#include "event-internal.h" + +int +ev_token_bucket_init(struct ev_token_bucket *bucket, + const struct ev_token_bucket_cfg *cfg, + ev_uint32_t current_tick, + int reinitialize) +{ + if (reinitialize) { + /* on reinitialization, we only clip downwards, since we've + already used who-knows-how-much bandwidth this tick. We + leave "last_updated" as it is; the next update will add the + appropriate amount of bandwidth to the bucket. + */ + if (bucket->read_limit > (ev_int64_t) cfg->read_maximum) + bucket->read_limit = cfg->read_maximum; + if (bucket->write_limit > (ev_int64_t) cfg->write_maximum) + bucket->write_limit = cfg->write_maximum; + } else { + bucket->read_limit = cfg->read_rate; + bucket->write_limit = cfg->write_rate; + bucket->last_updated = current_tick; + } + return 0; +} + +int +ev_token_bucket_update(struct ev_token_bucket *bucket, + const struct ev_token_bucket_cfg *cfg, + ev_uint32_t current_tick) +{ + /* It's okay if the tick number overflows, since we'll just + * wrap around when we do the unsigned substraction. */ + unsigned n_ticks = current_tick - bucket->last_updated; + + /* Make sure some ticks actually happened, and that time didn't + * roll back. */ + if (n_ticks == 0 || n_ticks > INT_MAX) + return 0; + + /* Naively, we would say + bucket->limit += n_ticks * cfg->rate; + + if (bucket->limit > cfg->maximum) + bucket->limit = cfg->maximum; + + But we're worried about overflow, so we do it like this: + */ + + if ((cfg->read_maximum - bucket->read_limit) / n_ticks < cfg->read_rate) + bucket->read_limit = cfg->read_maximum; + else + bucket->read_limit += n_ticks * cfg->read_rate; + + + if ((cfg->write_maximum - bucket->write_limit) / n_ticks < cfg->write_rate) + bucket->write_limit = cfg->write_maximum; + else + bucket->write_limit += n_ticks * cfg->write_rate; + + + bucket->last_updated = current_tick; + + return 1; +} + +static inline void +bufferevent_update_buckets(struct bufferevent_private *bev) +{ + /* Must hold lock on bev. */ + struct timeval now; + unsigned tick; + event_base_gettimeofday_cached(bev->bev.ev_base, &now); + tick = ev_token_bucket_get_tick(&now, bev->rate_limiting->cfg); + if (tick != bev->rate_limiting->limit.last_updated) + ev_token_bucket_update(&bev->rate_limiting->limit, + bev->rate_limiting->cfg, tick); +} + +ev_uint32_t +ev_token_bucket_get_tick(const struct timeval *tv, + const struct ev_token_bucket_cfg *cfg) +{ + /* This computation uses two multiplies and a divide. We could do + * fewer if we knew that the tick length was an integer number of + * seconds, or if we knew it divided evenly into a second. We should + * investigate that more. + */ + + /* We cast to an ev_uint64_t first, since we don't want to overflow + * before we do the final divide. */ + ev_uint64_t msec = (ev_uint64_t)tv->tv_sec * 1000 + tv->tv_usec / 1000; + return (unsigned)(msec / cfg->msec_per_tick); +} + +struct ev_token_bucket_cfg * +ev_token_bucket_cfg_new(size_t read_rate, size_t read_burst, + size_t write_rate, size_t write_burst, + const struct timeval *tick_len) +{ + struct ev_token_bucket_cfg *r; + struct timeval g; + if (! tick_len) { + g.tv_sec = 1; + g.tv_usec = 0; + tick_len = &g; + } + if (read_rate > read_burst || write_rate > write_burst || + read_rate < 1 || write_rate < 1) + return NULL; + if (read_rate > EV_RATE_LIMIT_MAX || + write_rate > EV_RATE_LIMIT_MAX || + read_burst > EV_RATE_LIMIT_MAX || + write_burst > EV_RATE_LIMIT_MAX) + return NULL; + r = mm_calloc(1, sizeof(struct ev_token_bucket_cfg)); + if (!r) + return NULL; + r->read_rate = read_rate; + r->write_rate = write_rate; + r->read_maximum = read_burst; + r->write_maximum = write_burst; + memcpy(&r->tick_timeout, tick_len, sizeof(struct timeval)); + r->msec_per_tick = (tick_len->tv_sec * 1000) + + (tick_len->tv_usec & COMMON_TIMEOUT_MICROSECONDS_MASK)/1000; + return r; +} + +void +ev_token_bucket_cfg_free(struct ev_token_bucket_cfg *cfg) +{ + mm_free(cfg); +} + +/* No matter how big our bucket gets, don't try to read more than this + * much in a single read operation. */ +#define MAX_TO_READ_EVER 16384 +/* No matter how big our bucket gets, don't try to write more than this + * much in a single write operation. */ +#define MAX_TO_WRITE_EVER 16384 + +#define LOCK_GROUP(g) EVLOCK_LOCK((g)->lock, 0) +#define UNLOCK_GROUP(g) EVLOCK_UNLOCK((g)->lock, 0) + +static int _bev_group_suspend_reading(struct bufferevent_rate_limit_group *g); +static int _bev_group_suspend_writing(struct bufferevent_rate_limit_group *g); +static void _bev_group_unsuspend_reading(struct bufferevent_rate_limit_group *g); +static void _bev_group_unsuspend_writing(struct bufferevent_rate_limit_group *g); + +/** Helper: figure out the maximum amount we should write if is_write, or + the maximum amount we should read if is_read. Return that maximum, or + 0 if our bucket is wholly exhausted. + */ +static inline ev_ssize_t +_bufferevent_get_rlim_max(struct bufferevent_private *bev, int is_write) +{ + /* needs lock on bev. */ + ev_ssize_t max_so_far = is_write?MAX_TO_WRITE_EVER:MAX_TO_READ_EVER; + +#define LIM(x) \ + (is_write ? (x).write_limit : (x).read_limit) + +#define GROUP_SUSPENDED(g) \ + (is_write ? (g)->write_suspended : (g)->read_suspended) + + /* Sets max_so_far to MIN(x, max_so_far) */ +#define CLAMPTO(x) \ + do { \ + if (max_so_far > (x)) \ + max_so_far = (x); \ + } while (0); + + if (!bev->rate_limiting) + return max_so_far; + + /* If rate-limiting is enabled at all, update the appropriate + bucket, and take the smaller of our rate limit and the group + rate limit. + */ + + if (bev->rate_limiting->cfg) { + bufferevent_update_buckets(bev); + max_so_far = LIM(bev->rate_limiting->limit); + } + if (bev->rate_limiting->group) { + struct bufferevent_rate_limit_group *g = + bev->rate_limiting->group; + ev_ssize_t share; + LOCK_GROUP(g); + if (GROUP_SUSPENDED(g)) { + /* We can get here if we failed to lock this + * particular bufferevent while suspending the whole + * group. */ + if (is_write) + bufferevent_suspend_write(&bev->bev, + BEV_SUSPEND_BW_GROUP); + else + bufferevent_suspend_read(&bev->bev, + BEV_SUSPEND_BW_GROUP); + share = 0; + } else { + /* XXXX probably we should divide among the active + * members, not the total members. */ + share = LIM(g->rate_limit) / g->n_members; + if (share < g->min_share) + share = g->min_share; + } + UNLOCK_GROUP(g); + CLAMPTO(share); + } + + if (max_so_far < 0) + max_so_far = 0; + return max_so_far; +} + +ev_ssize_t +_bufferevent_get_read_max(struct bufferevent_private *bev) +{ + return _bufferevent_get_rlim_max(bev, 0); +} + +ev_ssize_t +_bufferevent_get_write_max(struct bufferevent_private *bev) +{ + return _bufferevent_get_rlim_max(bev, 1); +} + +int +_bufferevent_decrement_read_buckets(struct bufferevent_private *bev, ev_ssize_t bytes) +{ + /* XXXXX Make sure all users of this function check its return value */ + int r = 0; + /* need to hold lock on bev */ + if (!bev->rate_limiting) + return 0; + + if (bev->rate_limiting->cfg) { + bev->rate_limiting->limit.read_limit -= bytes; + if (bev->rate_limiting->limit.read_limit <= 0) { + bufferevent_suspend_read(&bev->bev, BEV_SUSPEND_BW); + if (event_add(&bev->rate_limiting->refill_bucket_event, + &bev->rate_limiting->cfg->tick_timeout) < 0) + r = -1; + } else if (bev->read_suspended & BEV_SUSPEND_BW) { + if (!(bev->write_suspended & BEV_SUSPEND_BW)) + event_del(&bev->rate_limiting->refill_bucket_event); + bufferevent_unsuspend_read(&bev->bev, BEV_SUSPEND_BW); + } + } + + if (bev->rate_limiting->group) { + LOCK_GROUP(bev->rate_limiting->group); + bev->rate_limiting->group->rate_limit.read_limit -= bytes; + bev->rate_limiting->group->total_read += bytes; + if (bev->rate_limiting->group->rate_limit.read_limit <= 0) { + _bev_group_suspend_reading(bev->rate_limiting->group); + } else if (bev->rate_limiting->group->read_suspended) { + _bev_group_unsuspend_reading(bev->rate_limiting->group); + } + UNLOCK_GROUP(bev->rate_limiting->group); + } + + return r; +} + +int +_bufferevent_decrement_write_buckets(struct bufferevent_private *bev, ev_ssize_t bytes) +{ + /* XXXXX Make sure all users of this function check its return value */ + int r = 0; + /* need to hold lock */ + if (!bev->rate_limiting) + return 0; + + if (bev->rate_limiting->cfg) { + bev->rate_limiting->limit.write_limit -= bytes; + if (bev->rate_limiting->limit.write_limit <= 0) { + bufferevent_suspend_write(&bev->bev, BEV_SUSPEND_BW); + if (event_add(&bev->rate_limiting->refill_bucket_event, + &bev->rate_limiting->cfg->tick_timeout) < 0) + r = -1; + } else if (bev->write_suspended & BEV_SUSPEND_BW) { + if (!(bev->read_suspended & BEV_SUSPEND_BW)) + event_del(&bev->rate_limiting->refill_bucket_event); + bufferevent_unsuspend_write(&bev->bev, BEV_SUSPEND_BW); + } + } + + if (bev->rate_limiting->group) { + LOCK_GROUP(bev->rate_limiting->group); + bev->rate_limiting->group->rate_limit.write_limit -= bytes; + bev->rate_limiting->group->total_written += bytes; + if (bev->rate_limiting->group->rate_limit.write_limit <= 0) { + _bev_group_suspend_writing(bev->rate_limiting->group); + } else if (bev->rate_limiting->group->write_suspended) { + _bev_group_unsuspend_writing(bev->rate_limiting->group); + } + UNLOCK_GROUP(bev->rate_limiting->group); + } + + return r; +} + +/** Stop reading on every bufferevent in g */ +static int +_bev_group_suspend_reading(struct bufferevent_rate_limit_group *g) +{ + /* Needs group lock */ + struct bufferevent_private *bev; + g->read_suspended = 1; + g->pending_unsuspend_read = 0; + + /* Note that in this loop we call EVLOCK_TRY_LOCK instead of BEV_LOCK, + to prevent a deadlock. (Ordinarily, the group lock nests inside + the bufferevent locks. If we are unable to lock any individual + bufferevent, it will find out later when it looks at its limit + and sees that its group is suspended. + */ + TAILQ_FOREACH(bev, &g->members, rate_limiting->next_in_group) { + if (EVLOCK_TRY_LOCK(bev->lock)) { + bufferevent_suspend_read(&bev->bev, + BEV_SUSPEND_BW_GROUP); + EVLOCK_UNLOCK(bev->lock, 0); + } + } + return 0; +} + +/** Stop writing on every bufferevent in g */ +static int +_bev_group_suspend_writing(struct bufferevent_rate_limit_group *g) +{ + /* Needs group lock */ + struct bufferevent_private *bev; + g->write_suspended = 1; + g->pending_unsuspend_write = 0; + TAILQ_FOREACH(bev, &g->members, rate_limiting->next_in_group) { + if (EVLOCK_TRY_LOCK(bev->lock)) { + bufferevent_suspend_write(&bev->bev, + BEV_SUSPEND_BW_GROUP); + EVLOCK_UNLOCK(bev->lock, 0); + } + } + return 0; +} + +/** Timer callback invoked on a single bufferevent with one or more exhausted + buckets when they are ready to refill. */ +static void +_bev_refill_callback(evutil_socket_t fd, short what, void *arg) +{ + unsigned tick; + struct timeval now; + struct bufferevent_private *bev = arg; + int again = 0; + BEV_LOCK(&bev->bev); + if (!bev->rate_limiting || !bev->rate_limiting->cfg) { + BEV_UNLOCK(&bev->bev); + return; + } + + /* First, update the bucket */ + event_base_gettimeofday_cached(bev->bev.ev_base, &now); + tick = ev_token_bucket_get_tick(&now, + bev->rate_limiting->cfg); + ev_token_bucket_update(&bev->rate_limiting->limit, + bev->rate_limiting->cfg, + tick); + + /* Now unsuspend any read/write operations as appropriate. */ + if ((bev->read_suspended & BEV_SUSPEND_BW)) { + if (bev->rate_limiting->limit.read_limit > 0) + bufferevent_unsuspend_read(&bev->bev, BEV_SUSPEND_BW); + else + again = 1; + } + if ((bev->write_suspended & BEV_SUSPEND_BW)) { + if (bev->rate_limiting->limit.write_limit > 0) + bufferevent_unsuspend_write(&bev->bev, BEV_SUSPEND_BW); + else + again = 1; + } + if (again) { + /* One or more of the buckets may need another refill if they + started negative. + + XXXX if we need to be quiet for more ticks, we should + maybe figure out what timeout we really want. + */ + /* XXXX Handle event_add failure somehow */ + event_add(&bev->rate_limiting->refill_bucket_event, + &bev->rate_limiting->cfg->tick_timeout); + } + BEV_UNLOCK(&bev->bev); +} + +/** Helper: grab a random element from a bufferevent group. */ +static struct bufferevent_private * +_bev_group_random_element(struct bufferevent_rate_limit_group *group) +{ + int which; + struct bufferevent_private *bev; + + /* requires group lock */ + + if (!group->n_members) + return NULL; + + EVUTIL_ASSERT(! TAILQ_EMPTY(&group->members)); + + which = _evutil_weakrand() % group->n_members; + + bev = TAILQ_FIRST(&group->members); + while (which--) + bev = TAILQ_NEXT(bev, rate_limiting->next_in_group); + + return bev; +} + +/** Iterate over the elements of a rate-limiting group 'g' with a random + starting point, assigning each to the variable 'bev', and executing the + block 'block'. + + We do this in a half-baked effort to get fairness among group members. + XXX Round-robin or some kind of priority queue would be even more fair. + */ +#define FOREACH_RANDOM_ORDER(block) \ + do { \ + first = _bev_group_random_element(g); \ + for (bev = first; bev != TAILQ_END(&g->members); \ + bev = TAILQ_NEXT(bev, rate_limiting->next_in_group)) { \ + block ; \ + } \ + for (bev = TAILQ_FIRST(&g->members); bev && bev != first; \ + bev = TAILQ_NEXT(bev, rate_limiting->next_in_group)) { \ + block ; \ + } \ + } while (0) + +static void +_bev_group_unsuspend_reading(struct bufferevent_rate_limit_group *g) +{ + int again = 0; + struct bufferevent_private *bev, *first; + + g->read_suspended = 0; + FOREACH_RANDOM_ORDER({ + if (EVLOCK_TRY_LOCK(bev->lock)) { + bufferevent_unsuspend_read(&bev->bev, + BEV_SUSPEND_BW_GROUP); + EVLOCK_UNLOCK(bev->lock, 0); + } else { + again = 1; + } + }); + g->pending_unsuspend_read = again; +} + +static void +_bev_group_unsuspend_writing(struct bufferevent_rate_limit_group *g) +{ + int again = 0; + struct bufferevent_private *bev, *first; + g->write_suspended = 0; + + FOREACH_RANDOM_ORDER({ + if (EVLOCK_TRY_LOCK(bev->lock)) { + bufferevent_unsuspend_write(&bev->bev, + BEV_SUSPEND_BW_GROUP); + EVLOCK_UNLOCK(bev->lock, 0); + } else { + again = 1; + } + }); + g->pending_unsuspend_write = again; +} + +/** Callback invoked every tick to add more elements to the group bucket + and unsuspend group members as needed. + */ +static void +_bev_group_refill_callback(evutil_socket_t fd, short what, void *arg) +{ + struct bufferevent_rate_limit_group *g = arg; + unsigned tick; + struct timeval now; + + event_base_gettimeofday_cached(event_get_base(&g->master_refill_event), &now); + + LOCK_GROUP(g); + + tick = ev_token_bucket_get_tick(&now, &g->rate_limit_cfg); + ev_token_bucket_update(&g->rate_limit, &g->rate_limit_cfg, tick); + + if (g->pending_unsuspend_read || + (g->read_suspended && (g->rate_limit.read_limit >= g->min_share))) { + _bev_group_unsuspend_reading(g); + } + if (g->pending_unsuspend_write || + (g->write_suspended && (g->rate_limit.write_limit >= g->min_share))){ + _bev_group_unsuspend_writing(g); + } + + /* XXXX Rather than waiting to the next tick to unsuspend stuff + * with pending_unsuspend_write/read, we should do it on the + * next iteration of the mainloop. + */ + + UNLOCK_GROUP(g); +} + +int +bufferevent_set_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg) +{ + struct bufferevent_private *bevp = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + int r = -1; + struct bufferevent_rate_limit *rlim; + struct timeval now; + ev_uint32_t tick; + int reinit = 0, suspended = 0; + /* XXX reference-count cfg */ + + BEV_LOCK(bev); + + if (cfg == NULL) { + if (bevp->rate_limiting) { + rlim = bevp->rate_limiting; + rlim->cfg = NULL; + bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW); + bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW); + if (event_initialized(&rlim->refill_bucket_event)) + event_del(&rlim->refill_bucket_event); + } + r = 0; + goto done; + } + + event_base_gettimeofday_cached(bev->ev_base, &now); + tick = ev_token_bucket_get_tick(&now, cfg); + + if (bevp->rate_limiting && bevp->rate_limiting->cfg == cfg) { + /* no-op */ + r = 0; + goto done; + } + if (bevp->rate_limiting == NULL) { + rlim = mm_calloc(1, sizeof(struct bufferevent_rate_limit)); + if (!rlim) + goto done; + bevp->rate_limiting = rlim; + } else { + rlim = bevp->rate_limiting; + } + reinit = rlim->cfg != NULL; + + rlim->cfg = cfg; + ev_token_bucket_init(&rlim->limit, cfg, tick, reinit); + + if (reinit) { + EVUTIL_ASSERT(event_initialized(&rlim->refill_bucket_event)); + event_del(&rlim->refill_bucket_event); + } + evtimer_assign(&rlim->refill_bucket_event, bev->ev_base, + _bev_refill_callback, bevp); + + if (rlim->limit.read_limit > 0) { + bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW); + } else { + bufferevent_suspend_read(bev, BEV_SUSPEND_BW); + suspended=1; + } + if (rlim->limit.write_limit > 0) { + bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW); + } else { + bufferevent_suspend_write(bev, BEV_SUSPEND_BW); + suspended = 1; + } + + if (suspended) + event_add(&rlim->refill_bucket_event, &cfg->tick_timeout); + + r = 0; + +done: + BEV_UNLOCK(bev); + return r; +} + +struct bufferevent_rate_limit_group * +bufferevent_rate_limit_group_new(struct event_base *base, + const struct ev_token_bucket_cfg *cfg) +{ + struct bufferevent_rate_limit_group *g; + struct timeval now; + ev_uint32_t tick; + + event_base_gettimeofday_cached(base, &now); + tick = ev_token_bucket_get_tick(&now, cfg); + + g = mm_calloc(1, sizeof(struct bufferevent_rate_limit_group)); + if (!g) + return NULL; + memcpy(&g->rate_limit_cfg, cfg, sizeof(g->rate_limit_cfg)); + TAILQ_INIT(&g->members); + + ev_token_bucket_init(&g->rate_limit, cfg, tick, 0); + + event_assign(&g->master_refill_event, base, -1, EV_PERSIST, + _bev_group_refill_callback, g); + /*XXXX handle event_add failure */ + event_add(&g->master_refill_event, &cfg->tick_timeout); + + EVTHREAD_ALLOC_LOCK(g->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + + bufferevent_rate_limit_group_set_min_share(g, 64); + + return g; +} + +int +bufferevent_rate_limit_group_set_cfg( + struct bufferevent_rate_limit_group *g, + const struct ev_token_bucket_cfg *cfg) +{ + int same_tick; + if (!g || !cfg) + return -1; + + LOCK_GROUP(g); + same_tick = evutil_timercmp( + &g->rate_limit_cfg.tick_timeout, &cfg->tick_timeout, ==); + memcpy(&g->rate_limit_cfg, cfg, sizeof(g->rate_limit_cfg)); + + if (g->rate_limit.read_limit > (ev_ssize_t)cfg->read_maximum) + g->rate_limit.read_limit = cfg->read_maximum; + if (g->rate_limit.write_limit > (ev_ssize_t)cfg->write_maximum) + g->rate_limit.write_limit = cfg->write_maximum; + + if (!same_tick) { + /* This can cause a hiccup in the schedule */ + event_add(&g->master_refill_event, &cfg->tick_timeout); + } + + /* The new limits might force us to adjust min_share differently. */ + bufferevent_rate_limit_group_set_min_share(g, g->configured_min_share); + + UNLOCK_GROUP(g); + return 0; +} + +int +bufferevent_rate_limit_group_set_min_share( + struct bufferevent_rate_limit_group *g, + size_t share) +{ + if (share > EV_SSIZE_MAX) + return -1; + + g->configured_min_share = share; + + /* Can't set share to less than the one-tick maximum. IOW, at steady + * state, at least one connection can go per tick. */ + if (share > g->rate_limit_cfg.read_rate) + share = g->rate_limit_cfg.read_rate; + if (share > g->rate_limit_cfg.write_rate) + share = g->rate_limit_cfg.write_rate; + + g->min_share = share; + return 0; +} + +void +bufferevent_rate_limit_group_free(struct bufferevent_rate_limit_group *g) +{ + LOCK_GROUP(g); + EVUTIL_ASSERT(0 == g->n_members); + event_del(&g->master_refill_event); + UNLOCK_GROUP(g); + EVTHREAD_FREE_LOCK(g->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + mm_free(g); +} + +int +bufferevent_add_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g) +{ + int wsuspend, rsuspend; + struct bufferevent_private *bevp = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + BEV_LOCK(bev); + + if (!bevp->rate_limiting) { + struct bufferevent_rate_limit *rlim; + rlim = mm_calloc(1, sizeof(struct bufferevent_rate_limit)); + if (!rlim) { + BEV_UNLOCK(bev); + return -1; + } + evtimer_assign(&rlim->refill_bucket_event, bev->ev_base, + _bev_refill_callback, bevp); + bevp->rate_limiting = rlim; + } + + if (bevp->rate_limiting->group == g) { + BEV_UNLOCK(bev); + return 0; + } + if (bevp->rate_limiting->group) + bufferevent_remove_from_rate_limit_group(bev); + + LOCK_GROUP(g); + bevp->rate_limiting->group = g; + ++g->n_members; + TAILQ_INSERT_TAIL(&g->members, bevp, rate_limiting->next_in_group); + + rsuspend = g->read_suspended; + wsuspend = g->write_suspended; + + UNLOCK_GROUP(g); + + if (rsuspend) + bufferevent_suspend_read(bev, BEV_SUSPEND_BW_GROUP); + if (wsuspend) + bufferevent_suspend_write(bev, BEV_SUSPEND_BW_GROUP); + + BEV_UNLOCK(bev); + return 0; +} + +int +bufferevent_remove_from_rate_limit_group(struct bufferevent *bev) +{ + return bufferevent_remove_from_rate_limit_group_internal(bev, 1); +} + +int +bufferevent_remove_from_rate_limit_group_internal(struct bufferevent *bev, + int unsuspend) +{ + struct bufferevent_private *bevp = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + BEV_LOCK(bev); + if (bevp->rate_limiting && bevp->rate_limiting->group) { + struct bufferevent_rate_limit_group *g = + bevp->rate_limiting->group; + LOCK_GROUP(g); + bevp->rate_limiting->group = NULL; + --g->n_members; + TAILQ_REMOVE(&g->members, bevp, rate_limiting->next_in_group); + UNLOCK_GROUP(g); + } + if (unsuspend) { + bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW_GROUP); + bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW_GROUP); + } + BEV_UNLOCK(bev); + return 0; +} + +/* === + * API functions to expose rate limits. + * + * Don't use these from inside Libevent; they're meant to be for use by + * the program. + * === */ + +/* Mostly you don't want to use this function from inside libevent; + * _bufferevent_get_read_max() is more likely what you want*/ +ev_ssize_t +bufferevent_get_read_limit(struct bufferevent *bev) +{ + ev_ssize_t r; + struct bufferevent_private *bevp; + BEV_LOCK(bev); + bevp = BEV_UPCAST(bev); + if (bevp->rate_limiting && bevp->rate_limiting->cfg) { + bufferevent_update_buckets(bevp); + r = bevp->rate_limiting->limit.read_limit; + } else { + r = EV_SSIZE_MAX; + } + BEV_UNLOCK(bev); + return r; +} + +/* Mostly you don't want to use this function from inside libevent; + * _bufferevent_get_write_max() is more likely what you want*/ +ev_ssize_t +bufferevent_get_write_limit(struct bufferevent *bev) +{ + ev_ssize_t r; + struct bufferevent_private *bevp; + BEV_LOCK(bev); + bevp = BEV_UPCAST(bev); + if (bevp->rate_limiting && bevp->rate_limiting->cfg) { + bufferevent_update_buckets(bevp); + r = bevp->rate_limiting->limit.write_limit; + } else { + r = EV_SSIZE_MAX; + } + BEV_UNLOCK(bev); + return r; +} + +ev_ssize_t +bufferevent_get_max_to_read(struct bufferevent *bev) +{ + ev_ssize_t r; + BEV_LOCK(bev); + r = _bufferevent_get_read_max(BEV_UPCAST(bev)); + BEV_UNLOCK(bev); + return r; +} + +ev_ssize_t +bufferevent_get_max_to_write(struct bufferevent *bev) +{ + ev_ssize_t r; + BEV_LOCK(bev); + r = _bufferevent_get_write_max(BEV_UPCAST(bev)); + BEV_UNLOCK(bev); + return r; +} + + +/* Mostly you don't want to use this function from inside libevent; + * _bufferevent_get_read_max() is more likely what you want*/ +ev_ssize_t +bufferevent_rate_limit_group_get_read_limit( + struct bufferevent_rate_limit_group *grp) +{ + ev_ssize_t r; + LOCK_GROUP(grp); + r = grp->rate_limit.read_limit; + UNLOCK_GROUP(grp); + return r; +} + +/* Mostly you don't want to use this function from inside libevent; + * _bufferevent_get_write_max() is more likely what you want. */ +ev_ssize_t +bufferevent_rate_limit_group_get_write_limit( + struct bufferevent_rate_limit_group *grp) +{ + ev_ssize_t r; + LOCK_GROUP(grp); + r = grp->rate_limit.write_limit; + UNLOCK_GROUP(grp); + return r; +} + +int +bufferevent_decrement_read_limit(struct bufferevent *bev, ev_ssize_t decr) +{ + int r = 0; + ev_ssize_t old_limit, new_limit; + struct bufferevent_private *bevp; + BEV_LOCK(bev); + bevp = BEV_UPCAST(bev); + EVUTIL_ASSERT(bevp->rate_limiting && bevp->rate_limiting->cfg); + old_limit = bevp->rate_limiting->limit.read_limit; + + new_limit = (bevp->rate_limiting->limit.read_limit -= decr); + if (old_limit > 0 && new_limit <= 0) { + bufferevent_suspend_read(bev, BEV_SUSPEND_BW); + if (event_add(&bevp->rate_limiting->refill_bucket_event, + &bevp->rate_limiting->cfg->tick_timeout) < 0) + r = -1; + } else if (old_limit <= 0 && new_limit > 0) { + if (!(bevp->write_suspended & BEV_SUSPEND_BW)) + event_del(&bevp->rate_limiting->refill_bucket_event); + bufferevent_unsuspend_read(bev, BEV_SUSPEND_BW); + } + + BEV_UNLOCK(bev); + return r; +} + +int +bufferevent_decrement_write_limit(struct bufferevent *bev, ev_ssize_t decr) +{ + /* XXXX this is mostly copy-and-paste from + * bufferevent_decrement_read_limit */ + int r = 0; + ev_ssize_t old_limit, new_limit; + struct bufferevent_private *bevp; + BEV_LOCK(bev); + bevp = BEV_UPCAST(bev); + EVUTIL_ASSERT(bevp->rate_limiting && bevp->rate_limiting->cfg); + old_limit = bevp->rate_limiting->limit.write_limit; + + new_limit = (bevp->rate_limiting->limit.write_limit -= decr); + if (old_limit > 0 && new_limit <= 0) { + bufferevent_suspend_write(bev, BEV_SUSPEND_BW); + if (event_add(&bevp->rate_limiting->refill_bucket_event, + &bevp->rate_limiting->cfg->tick_timeout) < 0) + r = -1; + } else if (old_limit <= 0 && new_limit > 0) { + if (!(bevp->read_suspended & BEV_SUSPEND_BW)) + event_del(&bevp->rate_limiting->refill_bucket_event); + bufferevent_unsuspend_write(bev, BEV_SUSPEND_BW); + } + + BEV_UNLOCK(bev); + return r; +} + +int +bufferevent_rate_limit_group_decrement_read( + struct bufferevent_rate_limit_group *grp, ev_ssize_t decr) +{ + int r = 0; + ev_ssize_t old_limit, new_limit; + LOCK_GROUP(grp); + old_limit = grp->rate_limit.read_limit; + new_limit = (grp->rate_limit.read_limit -= decr); + + if (old_limit > 0 && new_limit <= 0) { + _bev_group_suspend_reading(grp); + } else if (old_limit <= 0 && new_limit > 0) { + _bev_group_unsuspend_reading(grp); + } + + UNLOCK_GROUP(grp); + return r; +} + +int +bufferevent_rate_limit_group_decrement_write( + struct bufferevent_rate_limit_group *grp, ev_ssize_t decr) +{ + int r = 0; + ev_ssize_t old_limit, new_limit; + LOCK_GROUP(grp); + old_limit = grp->rate_limit.write_limit; + new_limit = (grp->rate_limit.write_limit -= decr); + + if (old_limit > 0 && new_limit <= 0) { + _bev_group_suspend_writing(grp); + } else if (old_limit <= 0 && new_limit > 0) { + _bev_group_unsuspend_writing(grp); + } + + UNLOCK_GROUP(grp); + return r; +} + +void +bufferevent_rate_limit_group_get_totals(struct bufferevent_rate_limit_group *grp, + ev_uint64_t *total_read_out, ev_uint64_t *total_written_out) +{ + EVUTIL_ASSERT(grp != NULL); + if (total_read_out) + *total_read_out = grp->total_read; + if (total_written_out) + *total_written_out = grp->total_written; +} + +void +bufferevent_rate_limit_group_reset_totals(struct bufferevent_rate_limit_group *grp) +{ + grp->total_read = grp->total_written = 0; +} diff --git a/libevent/bufferevent_sock.c b/libevent/bufferevent_sock.c new file mode 100644 index 0000000..9050eda --- /dev/null +++ b/libevent/bufferevent_sock.c @@ -0,0 +1,693 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * Copyright (c) 2002-2006 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + */ + +#include + +#include "event2/event-config.h" + +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#ifdef _EVENT_HAVE_STDARG_H +#include +#endif +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif + +#ifdef WIN32 +#include +#include +#endif + +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef _EVENT_HAVE_NETINET_IN_H +#include +#endif +#ifdef _EVENT_HAVE_NETINET_IN6_H +#include +#endif + +#include "event2/util.h" +#include "event2/bufferevent.h" +#include "event2/buffer.h" +#include "event2/bufferevent_struct.h" +#include "event2/bufferevent_compat.h" +#include "event2/event.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "bufferevent-internal.h" +#include "util-internal.h" +#ifdef WIN32 +#include "iocp-internal.h" +#endif + +/* prototypes */ +static int be_socket_enable(struct bufferevent *, short); +static int be_socket_disable(struct bufferevent *, short); +static void be_socket_destruct(struct bufferevent *); +static int be_socket_adj_timeouts(struct bufferevent *); +static int be_socket_flush(struct bufferevent *, short, enum bufferevent_flush_mode); +static int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); + +static void be_socket_setfd(struct bufferevent *, evutil_socket_t); + +const struct bufferevent_ops bufferevent_ops_socket = { + "socket", + evutil_offsetof(struct bufferevent_private, bev), + be_socket_enable, + be_socket_disable, + be_socket_destruct, + be_socket_adj_timeouts, + be_socket_flush, + be_socket_ctrl, +}; + +#define be_socket_add(ev, t) \ + _bufferevent_add_event((ev), (t)) + +static void +bufferevent_socket_outbuf_cb(struct evbuffer *buf, + const struct evbuffer_cb_info *cbinfo, + void *arg) +{ + struct bufferevent *bufev = arg; + struct bufferevent_private *bufev_p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + + if (cbinfo->n_added && + (bufev->enabled & EV_WRITE) && + !event_pending(&bufev->ev_write, EV_WRITE, NULL) && + !bufev_p->write_suspended) { + /* Somebody added data to the buffer, and we would like to + * write, and we were not writing. So, start writing. */ + if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) == -1) { + /* Should we log this? */ + } + } +} + +static void +bufferevent_readcb(evutil_socket_t fd, short event, void *arg) +{ + struct bufferevent *bufev = arg; + struct bufferevent_private *bufev_p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + struct evbuffer *input; + int res = 0; + short what = BEV_EVENT_READING; + ev_ssize_t howmuch = -1, readmax=-1; + + _bufferevent_incref_and_lock(bufev); + + if (event == EV_TIMEOUT) { + what |= BEV_EVENT_TIMEOUT; + goto error; + } + + input = bufev->input; + + /* + * If we have a high watermark configured then we don't want to + * read more data than would make us reach the watermark. + */ + if (bufev->wm_read.high != 0) { + howmuch = bufev->wm_read.high - evbuffer_get_length(input); + /* we somehow lowered the watermark, stop reading */ + if (howmuch <= 0) { + bufferevent_wm_suspend_read(bufev); + goto done; + } + } + readmax = _bufferevent_get_read_max(bufev_p); + if (howmuch < 0 || howmuch > readmax) /* The use of -1 for "unlimited" + * uglifies this code. XXXX */ + howmuch = readmax; + if (bufev_p->read_suspended) + goto done; + + evbuffer_unfreeze(input, 0); + res = evbuffer_read(input, fd, (int)howmuch); /* XXXX evbuffer_read would do better to take and return ev_ssize_t */ + evbuffer_freeze(input, 0); + + if (res == -1) { + int err = evutil_socket_geterror(fd); + if (EVUTIL_ERR_RW_RETRIABLE(err)) + goto reschedule; + /* error case */ + what |= BEV_EVENT_ERROR; + } else if (res == 0) { + /* eof case */ + what |= BEV_EVENT_EOF; + } + + if (res <= 0) + goto error; + + _bufferevent_decrement_read_buckets(bufev_p, res); + + /* Invoke the user callback - must always be called last */ + if (evbuffer_get_length(input) >= bufev->wm_read.low) + _bufferevent_run_readcb(bufev); + + goto done; + + reschedule: + goto done; + + error: + bufferevent_disable(bufev, EV_READ); + _bufferevent_run_eventcb(bufev, what); + + done: + _bufferevent_decref_and_unlock(bufev); +} + +static void +bufferevent_writecb(evutil_socket_t fd, short event, void *arg) +{ + struct bufferevent *bufev = arg; + struct bufferevent_private *bufev_p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + int res = 0; + short what = BEV_EVENT_WRITING; + int connected = 0; + ev_ssize_t atmost = -1; + + _bufferevent_incref_and_lock(bufev); + + if (event == EV_TIMEOUT) { + what |= BEV_EVENT_TIMEOUT; + goto error; + } + if (bufev_p->connecting) { + int c = evutil_socket_finished_connecting(fd); + /* we need to fake the error if the connection was refused + * immediately - usually connection to localhost on BSD */ + if (bufev_p->connection_refused) { + bufev_p->connection_refused = 0; + c = -1; + } + + if (c == 0) + goto done; + + bufev_p->connecting = 0; + if (c < 0) { + event_del(&bufev->ev_write); + event_del(&bufev->ev_read); + _bufferevent_run_eventcb(bufev, BEV_EVENT_ERROR); + goto done; + } else { + connected = 1; +#ifdef WIN32 + if (BEV_IS_ASYNC(bufev)) { + event_del(&bufev->ev_write); + bufferevent_async_set_connected(bufev); + _bufferevent_run_eventcb(bufev, + BEV_EVENT_CONNECTED); + goto done; + } +#endif + _bufferevent_run_eventcb(bufev, + BEV_EVENT_CONNECTED); + if (!(bufev->enabled & EV_WRITE) || + bufev_p->write_suspended) { + event_del(&bufev->ev_write); + goto done; + } + } + } + + atmost = _bufferevent_get_write_max(bufev_p); + + if (bufev_p->write_suspended) + goto done; + + if (evbuffer_get_length(bufev->output)) { + evbuffer_unfreeze(bufev->output, 1); + res = evbuffer_write_atmost(bufev->output, fd, atmost); + evbuffer_freeze(bufev->output, 1); + if (res == -1) { + int err = evutil_socket_geterror(fd); + if (EVUTIL_ERR_RW_RETRIABLE(err)) + goto reschedule; + what |= BEV_EVENT_ERROR; + } else if (res == 0) { + /* eof case + XXXX Actually, a 0 on write doesn't indicate + an EOF. An ECONNRESET might be more typical. + */ + what |= BEV_EVENT_EOF; + } + if (res <= 0) + goto error; + + _bufferevent_decrement_write_buckets(bufev_p, res); + } + + if (evbuffer_get_length(bufev->output) == 0) { + event_del(&bufev->ev_write); + } + + /* + * Invoke the user callback if our buffer is drained or below the + * low watermark. + */ + if ((res || !connected) && + evbuffer_get_length(bufev->output) <= bufev->wm_write.low) { + _bufferevent_run_writecb(bufev); + } + + goto done; + + reschedule: + if (evbuffer_get_length(bufev->output) == 0) { + event_del(&bufev->ev_write); + } + goto done; + + error: + bufferevent_disable(bufev, EV_WRITE); + _bufferevent_run_eventcb(bufev, what); + + done: + _bufferevent_decref_and_unlock(bufev); +} + +struct bufferevent * +bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, + int options) +{ + struct bufferevent_private *bufev_p; + struct bufferevent *bufev; + +#ifdef WIN32 + if (base && event_base_get_iocp(base)) + return bufferevent_async_new(base, fd, options); +#endif + + if ((bufev_p = mm_calloc(1, sizeof(struct bufferevent_private)))== NULL) + return NULL; + + if (bufferevent_init_common(bufev_p, base, &bufferevent_ops_socket, + options) < 0) { + mm_free(bufev_p); + return NULL; + } + bufev = &bufev_p->bev; + evbuffer_set_flags(bufev->output, EVBUFFER_FLAG_DRAINS_TO_FD); + + event_assign(&bufev->ev_read, bufev->ev_base, fd, + EV_READ|EV_PERSIST, bufferevent_readcb, bufev); + event_assign(&bufev->ev_write, bufev->ev_base, fd, + EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev); + + evbuffer_add_cb(bufev->output, bufferevent_socket_outbuf_cb, bufev); + + evbuffer_freeze(bufev->input, 0); + evbuffer_freeze(bufev->output, 1); + + return bufev; +} + +int +bufferevent_socket_connect(struct bufferevent *bev, + struct sockaddr *sa, int socklen) +{ + struct bufferevent_private *bufev_p = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + + evutil_socket_t fd; + int r = 0; + int result=-1; + int ownfd = 0; + + _bufferevent_incref_and_lock(bev); + + if (!bufev_p) + goto done; + + fd = bufferevent_getfd(bev); + if (fd < 0) { + if (!sa) + goto done; + fd = socket(sa->sa_family, SOCK_STREAM, 0); + if (fd < 0) + goto done; + if (evutil_make_socket_nonblocking(fd)<0) + goto done; + ownfd = 1; + } + if (sa) { +#ifdef WIN32 + if (bufferevent_async_can_connect(bev)) { + bufferevent_setfd(bev, fd); + r = bufferevent_async_connect(bev, fd, sa, socklen); + if (r < 0) + goto freesock; + bufev_p->connecting = 1; + result = 0; + goto done; + } else +#endif + r = evutil_socket_connect(&fd, sa, socklen); + if (r < 0) + goto freesock; + } +#ifdef WIN32 + /* ConnectEx() isn't always around, even when IOCP is enabled. + * Here, we borrow the socket object's write handler to fall back + * on a non-blocking connect() when ConnectEx() is unavailable. */ + if (BEV_IS_ASYNC(bev)) { + event_assign(&bev->ev_write, bev->ev_base, fd, + EV_WRITE|EV_PERSIST, bufferevent_writecb, bev); + } +#endif + bufferevent_setfd(bev, fd); + if (r == 0) { + if (! be_socket_enable(bev, EV_WRITE)) { + bufev_p->connecting = 1; + result = 0; + goto done; + } + } else if (r == 1) { + /* The connect succeeded already. How very BSD of it. */ + result = 0; + bufev_p->connecting = 1; + event_active(&bev->ev_write, EV_WRITE, 1); + } else { + /* The connect failed already. How very BSD of it. */ + bufev_p->connection_refused = 1; + bufev_p->connecting = 1; + result = 0; + event_active(&bev->ev_write, EV_WRITE, 1); + } + + goto done; + +freesock: + _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); + if (ownfd) + evutil_closesocket(fd); + /* do something about the error? */ +done: + _bufferevent_decref_and_unlock(bev); + return result; +} + +static void +bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai, + void *arg) +{ + struct bufferevent *bev = arg; + struct bufferevent_private *bev_p = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + int r; + BEV_LOCK(bev); + + bufferevent_unsuspend_write(bev, BEV_SUSPEND_LOOKUP); + bufferevent_unsuspend_read(bev, BEV_SUSPEND_LOOKUP); + + if (result != 0) { + bev_p->dns_error = result; + _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); + _bufferevent_decref_and_unlock(bev); + if (ai) + evutil_freeaddrinfo(ai); + return; + } + + /* XXX use the other addrinfos? */ + /* XXX use this return value */ + r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen); + (void)r; + _bufferevent_decref_and_unlock(bev); + evutil_freeaddrinfo(ai); +} + +int +bufferevent_socket_connect_hostname(struct bufferevent *bev, + struct evdns_base *evdns_base, int family, const char *hostname, int port) +{ + char portbuf[10]; + struct evutil_addrinfo hint; + int err; + struct bufferevent_private *bev_p = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + + if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) + return -1; + if (port < 1 || port > 65535) + return -1; + + BEV_LOCK(bev); + bev_p->dns_error = 0; + BEV_UNLOCK(bev); + + evutil_snprintf(portbuf, sizeof(portbuf), "%d", port); + + memset(&hint, 0, sizeof(hint)); + hint.ai_family = family; + hint.ai_protocol = IPPROTO_TCP; + hint.ai_socktype = SOCK_STREAM; + + bufferevent_suspend_write(bev, BEV_SUSPEND_LOOKUP); + bufferevent_suspend_read(bev, BEV_SUSPEND_LOOKUP); + + bufferevent_incref(bev); + err = evutil_getaddrinfo_async(evdns_base, hostname, portbuf, + &hint, bufferevent_connect_getaddrinfo_cb, bev); + + if (err == 0) { + return 0; + } else { + bufferevent_unsuspend_write(bev, BEV_SUSPEND_LOOKUP); + bufferevent_unsuspend_read(bev, BEV_SUSPEND_LOOKUP); + return -1; + } +} + +int +bufferevent_socket_get_dns_error(struct bufferevent *bev) +{ + int rv; + struct bufferevent_private *bev_p = + EVUTIL_UPCAST(bev, struct bufferevent_private, bev); + + BEV_LOCK(bev); + rv = bev_p->dns_error; + BEV_LOCK(bev); + + return rv; +} + +/* + * Create a new buffered event object. + * + * The read callback is invoked whenever we read new data. + * The write callback is invoked whenever the output buffer is drained. + * The error callback is invoked on a write/read error or on EOF. + * + * Both read and write callbacks maybe NULL. The error callback is not + * allowed to be NULL and have to be provided always. + */ + +struct bufferevent * +bufferevent_new(evutil_socket_t fd, + bufferevent_data_cb readcb, bufferevent_data_cb writecb, + bufferevent_event_cb eventcb, void *cbarg) +{ + struct bufferevent *bufev; + + if (!(bufev = bufferevent_socket_new(NULL, fd, 0))) + return NULL; + + bufferevent_setcb(bufev, readcb, writecb, eventcb, cbarg); + + return bufev; +} + + +static int +be_socket_enable(struct bufferevent *bufev, short event) +{ + if (event & EV_READ) { + if (be_socket_add(&bufev->ev_read,&bufev->timeout_read) == -1) + return -1; + } + if (event & EV_WRITE) { + if (be_socket_add(&bufev->ev_write,&bufev->timeout_write) == -1) + return -1; + } + return 0; +} + +static int +be_socket_disable(struct bufferevent *bufev, short event) +{ + struct bufferevent_private *bufev_p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + if (event & EV_READ) { + if (event_del(&bufev->ev_read) == -1) + return -1; + } + /* Don't actually disable the write if we are trying to connect. */ + if ((event & EV_WRITE) && ! bufev_p->connecting) { + if (event_del(&bufev->ev_write) == -1) + return -1; + } + return 0; +} + +static void +be_socket_destruct(struct bufferevent *bufev) +{ + struct bufferevent_private *bufev_p = + EVUTIL_UPCAST(bufev, struct bufferevent_private, bev); + evutil_socket_t fd; + EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket); + + fd = event_get_fd(&bufev->ev_read); + + event_del(&bufev->ev_read); + event_del(&bufev->ev_write); + + if ((bufev_p->options & BEV_OPT_CLOSE_ON_FREE) && fd >= 0) + EVUTIL_CLOSESOCKET(fd); +} + +static int +be_socket_adj_timeouts(struct bufferevent *bufev) +{ + int r = 0; + if (event_pending(&bufev->ev_read, EV_READ, NULL)) + if (be_socket_add(&bufev->ev_read, &bufev->timeout_read) < 0) + r = -1; + if (event_pending(&bufev->ev_write, EV_WRITE, NULL)) { + if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) < 0) + r = -1; + } + return r; +} + +static int +be_socket_flush(struct bufferevent *bev, short iotype, + enum bufferevent_flush_mode mode) +{ + return 0; +} + + +static void +be_socket_setfd(struct bufferevent *bufev, evutil_socket_t fd) +{ + BEV_LOCK(bufev); + EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket); + + event_del(&bufev->ev_read); + event_del(&bufev->ev_write); + + event_assign(&bufev->ev_read, bufev->ev_base, fd, + EV_READ|EV_PERSIST, bufferevent_readcb, bufev); + event_assign(&bufev->ev_write, bufev->ev_base, fd, + EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev); + + if (fd >= 0) + bufferevent_enable(bufev, bufev->enabled); + + BEV_UNLOCK(bufev); +} + +/* XXXX Should non-socket bufferevents support this? */ +int +bufferevent_priority_set(struct bufferevent *bufev, int priority) +{ + int r = -1; + + BEV_LOCK(bufev); + if (bufev->be_ops != &bufferevent_ops_socket) + goto done; + + if (event_priority_set(&bufev->ev_read, priority) == -1) + goto done; + if (event_priority_set(&bufev->ev_write, priority) == -1) + goto done; + + r = 0; +done: + BEV_UNLOCK(bufev); + return r; +} + +/* XXXX Should non-socket bufferevents support this? */ +int +bufferevent_base_set(struct event_base *base, struct bufferevent *bufev) +{ + int res = -1; + + BEV_LOCK(bufev); + if (bufev->be_ops != &bufferevent_ops_socket) + goto done; + + bufev->ev_base = base; + + res = event_base_set(base, &bufev->ev_read); + if (res == -1) + goto done; + + res = event_base_set(base, &bufev->ev_write); +done: + BEV_UNLOCK(bufev); + return res; +} + +static int +be_socket_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, + union bufferevent_ctrl_data *data) +{ + switch (op) { + case BEV_CTRL_SET_FD: + be_socket_setfd(bev, data->fd); + return 0; + case BEV_CTRL_GET_FD: + data->fd = event_get_fd(&bev->ev_read); + return 0; + case BEV_CTRL_GET_UNDERLYING: + case BEV_CTRL_CANCEL_ALL: + default: + return -1; + } +} diff --git a/libevent/changelist-internal.h b/libevent/changelist-internal.h new file mode 100644 index 0000000..6ed432a --- /dev/null +++ b/libevent/changelist-internal.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _CHANGELIST_H_ +#define _CHANGELIST_H_ + +/* + A "changelist" is a list of all the fd status changes that should be made + between calls to the backend's dispatch function. There are a few reasons + that a backend would want to queue changes like this rather than processing + them immediately. + + 1) Sometimes applications will add and delete the same event more than + once between calls to dispatch. Processing these changes immediately + is needless, and potentially expensive (especially if we're on a system + that makes one syscall per changed event). + + 2) Sometimes we can coalesce multiple changes on the same fd into a single + syscall if we know about them in advance. For example, epoll can do an + add and a delete at the same time, but only if we have found out about + both of them before we tell epoll. + + 3) Sometimes adding an event that we immediately delete can cause + unintended consequences: in kqueue, this makes pending events get + reported spuriously. + */ + +#include "event2/util.h" + +/** Represents a */ +struct event_change { + /** The fd or signal whose events are to be changed */ + evutil_socket_t fd; + /* The events that were enabled on the fd before any of these changes + were made. May include EV_READ or EV_WRITE. */ + short old_events; + + /* The changes that we want to make in reading and writing on this fd. + * If this is a signal, then read_change has EV_CHANGE_SIGNAL set, + * and write_change is unused. */ + ev_uint8_t read_change; + ev_uint8_t write_change; +}; + +/* Flags for read_change and write_change. */ + +/* If set, add the event. */ +#define EV_CHANGE_ADD 0x01 +/* If set, delete the event. Exclusive with EV_CHANGE_ADD */ +#define EV_CHANGE_DEL 0x02 +/* If set, this event refers a signal, not an fd. */ +#define EV_CHANGE_SIGNAL EV_SIGNAL +/* Set for persistent events. Currently not used. */ +#define EV_CHANGE_PERSIST EV_PERSIST +/* Set for adding edge-triggered events. */ +#define EV_CHANGE_ET EV_ET + +/* The value of fdinfo_size that a backend should use if it is letting + * changelist handle its add and delete functions. */ +#define EVENT_CHANGELIST_FDINFO_SIZE sizeof(int) + +/** Set up the data fields in a changelist. */ +void event_changelist_init(struct event_changelist *changelist); +/** Remove every change in the changelist, and make corresponding changes + * in the event maps in the base. This function is generally used right + * after making all the changes in the changelist. */ +void event_changelist_remove_all(struct event_changelist *changelist, + struct event_base *base); +/** Free all memory held in a changelist. */ +void event_changelist_freemem(struct event_changelist *changelist); + +/** Implementation of eventop_add that queues the event in a changelist. */ +int event_changelist_add(struct event_base *base, evutil_socket_t fd, short old, short events, + void *p); +/** Implementation of eventop_del that queues the event in a changelist. */ +int event_changelist_del(struct event_base *base, evutil_socket_t fd, short old, short events, + void *p); + +#endif diff --git a/libevent/compat/sys/queue.h b/libevent/compat/sys/queue.h new file mode 100644 index 0000000..53dd10d --- /dev/null +++ b/libevent/compat/sys/queue.h @@ -0,0 +1,488 @@ +/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#ifndef WIN32 +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} +#endif + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ + if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = CIRCLEQ_LAST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_PREV(var, field)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = CIRCLEQ_END(head); \ + (head)->cqh_last = CIRCLEQ_END(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \ + if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/libevent/config.h.in b/libevent/config.h.in new file mode 100644 index 0000000..e86379f --- /dev/null +++ b/libevent/config.h.in @@ -0,0 +1,436 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if libevent should build without support for a debug mode */ +#undef DISABLE_DEBUG_MODE + +/* Define if libevent should not allow replacing the mm functions */ +#undef DISABLE_MM_REPLACEMENT + +/* Define if libevent should not be compiled with thread support */ +#undef DISABLE_THREAD_SUPPORT + +/* Define to 1 if you have the `arc4random' function. */ +#undef HAVE_ARC4RANDOM + +/* Define to 1 if you have the `arc4random_buf' function. */ +#undef HAVE_ARC4RANDOM_BUF + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the declaration of `CTL_KERN', and to 0 if you + don't. */ +#undef HAVE_DECL_CTL_KERN + +/* Define to 1 if you have the declaration of `KERN_ARND', and to 0 if you + don't. */ +#undef HAVE_DECL_KERN_ARND + +/* Define to 1 if you have the declaration of `KERN_RANDOM', and to 0 if you + don't. */ +#undef HAVE_DECL_KERN_RANDOM + +/* Define to 1 if you have the declaration of `RANDOM_UUID', and to 0 if you + don't. */ +#undef HAVE_DECL_RANDOM_UUID + +/* Define if /dev/poll is available */ +#undef HAVE_DEVPOLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define if your system supports the epoll system calls */ +#undef HAVE_EPOLL + +/* Define to 1 if you have the `epoll_ctl' function. */ +#undef HAVE_EPOLL_CTL + +/* Define to 1 if you have the `eventfd' function. */ +#undef HAVE_EVENTFD + +/* Define if your system supports event ports */ +#undef HAVE_EVENT_PORTS + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if the system has the type `fd_mask'. */ +#undef HAVE_FD_MASK + +/* Do we have getaddrinfo()? */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `getegid' function. */ +#undef HAVE_GETEGID + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define this if you have any gethostbyname_r() */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define this if gethostbyname_r takes 3 arguments */ +#undef HAVE_GETHOSTBYNAME_R_3_ARG + +/* Define this if gethostbyname_r takes 5 arguments */ +#undef HAVE_GETHOSTBYNAME_R_5_ARG + +/* Define this if gethostbyname_r takes 6 arguments */ +#undef HAVE_GETHOSTBYNAME_R_6_ARG + +/* Define to 1 if you have the `getnameinfo' function. */ +#undef HAVE_GETNAMEINFO + +/* Define to 1 if you have the `getprotobynumber' function. */ +#undef HAVE_GETPROTOBYNUMBER + +/* Define to 1 if you have the `getservbyname' function. */ +#undef HAVE_GETSERVBYNAME + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `inet_aton' function. */ +#undef HAVE_INET_ATON + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `issetugid' function. */ +#undef HAVE_ISSETUGID + +/* Define to 1 if you have the `kqueue' function. */ +#undef HAVE_KQUEUE + +/* Define if the system has zlib */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mmap' function. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN6_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define if the system has openssl */ +#undef HAVE_OPENSSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_BIO_H + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have the `port_create' function. */ +#undef HAVE_PORT_CREATE + +/* Define to 1 if you have the header file. */ +#undef HAVE_PORT_H + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define if we have pthreads on this system */ +#undef HAVE_PTHREADS + +/* Define to 1 if you have the `putenv' function. */ +#undef HAVE_PUTENV + +/* Define to 1 if the system has the type `sa_family_t'. */ +#undef HAVE_SA_FAMILY_T + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `sendfile' function. */ +#undef HAVE_SENDFILE + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define if F_SETFD is defined in */ +#undef HAVE_SETFD + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the `signal' function. */ +#undef HAVE_SIGNAL + +/* Define to 1 if you have the `splice' function. */ +#undef HAVE_SPLICE + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strsep' function. */ +#undef HAVE_STRSEP + +/* Define to 1 if you have the `strtok_r' function. */ +#undef HAVE_STRTOK_R + +/* Define to 1 if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define to 1 if the system has the type `struct addrinfo'. */ +#undef HAVE_STRUCT_ADDRINFO + +/* Define to 1 if the system has the type `struct in6_addr'. */ +#undef HAVE_STRUCT_IN6_ADDR + +/* Define to 1 if `s6_addr16' is a member of `struct in6_addr'. */ +#undef HAVE_STRUCT_IN6_ADDR_S6_ADDR16 + +/* Define to 1 if `s6_addr32' is a member of `struct in6_addr'. */ +#undef HAVE_STRUCT_IN6_ADDR_S6_ADDR32 + +/* Define to 1 if the system has the type `struct sockaddr_in6'. */ +#undef HAVE_STRUCT_SOCKADDR_IN6 + +/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */ +#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN + +/* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */ +#undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY + +/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY + +/* Define to 1 if you have the `sysctl' function. */ +#undef HAVE_SYSCTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DEVPOLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EPOLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EVENTFD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EVENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_QUEUE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SENDFILE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define if TAILQ_FOREACH is defined in */ +#undef HAVE_TAILQFOREACH + +/* Define if timeradd is defined in */ +#undef HAVE_TIMERADD + +/* Define if timerclear is defined in */ +#undef HAVE_TIMERCLEAR + +/* Define if timercmp is defined in */ +#undef HAVE_TIMERCMP + +/* Define if timerisset is defined in */ +#undef HAVE_TIMERISSET + +/* Define to 1 if the system has the type `uint16_t'. */ +#undef HAVE_UINT16_T + +/* Define to 1 if the system has the type `uint32_t'. */ +#undef HAVE_UINT32_T + +/* Define to 1 if the system has the type `uint64_t'. */ +#undef HAVE_UINT64_T + +/* Define to 1 if the system has the type `uint8_t'. */ +#undef HAVE_UINT8_T + +/* Define to 1 if the system has the type `uintptr_t'. */ +#undef HAVE_UINTPTR_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV + +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + +/* Define if kqueue works correctly with pipes */ +#undef HAVE_WORKING_KQUEUE + +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Numeric representation of the version */ +#undef NUMERIC_VERSION + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* The size of `pthread_t', as computed by sizeof. */ +#undef SIZEOF_PTHREAD_T + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* The size of `void *', as computed by sizeof. */ +#undef SIZEOF_VOID_P + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define to appropriate substitue if compiler doesnt have __func__ */ +#undef __func__ + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to unsigned int if you dont have it */ +#undef socklen_t + +/* Define to `int' if does not define. */ +#undef ssize_t diff --git a/libevent/configure b/libevent/configure new file mode 100755 index 0000000..6e4d47b --- /dev/null +++ b/libevent/configure @@ -0,0 +1,17492 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="event.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +INSTALL_LIBEVENT_FALSE +INSTALL_LIBEVENT_TRUE +LIBEVENT_GC_SECTIONS +OPENSSL_FALSE +OPENSSL_TRUE +PTHREADS_FALSE +PTHREADS_TRUE +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CC +acx_pthread_config +SIGNAL_SUPPORT_FALSE +SIGNAL_SUPPORT_TRUE +EVPORT_BACKEND_FALSE +EVPORT_BACKEND_TRUE +EPOLL_BACKEND_FALSE +EPOLL_BACKEND_TRUE +LIBOBJS +KQUEUE_BACKEND_FALSE +KQUEUE_BACKEND_TRUE +DEVPOLL_BACKEND_FALSE +DEVPOLL_BACKEND_TRUE +POLL_BACKEND_FALSE +POLL_BACKEND_TRUE +SELECT_BACKEND_FALSE +SELECT_BACKEND_TRUE +BUILD_WITH_NO_UNDEFINED_FALSE +BUILD_WITH_NO_UNDEFINED_TRUE +BUILD_CYGWIN_FALSE +BUILD_CYGWIN_TRUE +BUILD_WIN32_FALSE +BUILD_WIN32_TRUE +OPENSSL_LIBS +OPENSSL_LIBADD +EV_LIB_GDI +EV_LIB_WS32 +ZLIB_REGRESS_FALSE +ZLIB_REGRESS_TRUE +ZLIB_LIBS +BUILD_REGRESS_FALSE +BUILD_REGRESS_TRUE +LIBTOOL_DEPS +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +SED +LIBTOOL +EGREP +GREP +CPP +LN_S +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +enable_gcc_warnings +enable_thread_support +enable_malloc_replacement +enable_openssl +enable_debug_mode +enable_libevent_install +enable_libevent_regress +enable_function_sections +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-gcc-warnings enable verbose warnings with GCC + --disable-thread-support + disable support for threading + --disable-malloc-replacement + disable support for replacing the memory mgt + functions + --disable-openssl disable support for openssl encryption + --disable-debug-mode disable support for running in debug mode + --disable-libevent-install, disable installation of libevent + + --disable-libevent-regress, skip regress in make check + + --enable-function-sections, make static library allow smaller binaries with --gc-sections + + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 &5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + +am__api_version='1.12' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + + PACKAGE=libevent + VERSION=2.0.18-stable + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +ac_config_headers="$ac_config_headers config.h" + + +$as_echo "#define NUMERIC_VERSION 0x02001200" >>confdefs.h + + +if test "$prefix" = "NONE"; then + prefix="/usr/local" +fi + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +case "$host_os" in + + osf5*) + CFLAGS="$CFLAGS -D_OSF_SOURCE" + ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +if test "x$CC" != xcc; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 +$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 +$as_echo_n "checking whether cc understands -c and -o together... " >&6; } +fi +set dummy $CC; ac_cc=`$as_echo "$2" | + sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' +rm -f conftest2.* +if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.$ac_ext >&5' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' + rm -f conftest2.* + if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f core conftest* + +fi +if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h + +fi + +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +if test $ac_cv_c_compiler_gnu = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 +$as_echo_n "checking whether $CC needs -traditional... " >&6; } +if ${ac_cv_prog_gcc_traditional+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_pattern="Autoconf.*'x'" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TIOCGETP +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +else + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TCGETA +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 +$as_echo "$ac_cv_prog_gcc_traditional" >&6; } + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + + +if test "$GCC" = "yes" ; then + # Enable many gcc warnings by default... + CFLAGS="$CFLAGS -Wall" + # And disable the strict-aliasing optimization, since it breaks + # our sockaddr-handling code in strange ways. + CFLAGS="$CFLAGS -fno-strict-aliasing" +fi + +# OS X Lion started deprecating the system openssl. Let's just disable +# all deprecation warnings on OS X. +case "$host_os" in + + darwin*) + CFLAGS="$CFLAGS -Wno-deprecated-declarations" + ;; +esac + +# Check whether --enable-gcc-warnings was given. +if test "${enable_gcc_warnings+set}" = set; then : + enableval=$enable_gcc_warnings; +fi + +# Check whether --enable-thread-support was given. +if test "${enable_thread_support+set}" = set; then : + enableval=$enable_thread_support; +else + enable_thread_support=yes +fi + +# Check whether --enable-malloc-replacement was given. +if test "${enable_malloc_replacement+set}" = set; then : + enableval=$enable_malloc_replacement; +else + enable_malloc_replacement=yes +fi + +# Check whether --enable-openssl was given. +if test "${enable_openssl+set}" = set; then : + enableval=$enable_openssl; +else + enable_openssl=yes +fi + +# Check whether --enable-debug-mode was given. +if test "${enable_debug_mode+set}" = set; then : + enableval=$enable_debug_mode; +else + enable_debug_mode=yes +fi + +# Check whether --enable-libevent-install was given. +if test "${enable_libevent_install+set}" = set; then : + enableval=$enable_libevent_install; +else + enable_libevent_install=yes +fi + +# Check whether --enable-libevent-regress was given. +if test "${enable_libevent_regress+set}" = set; then : + enableval=$enable_libevent_regress; +else + enable_libevent_regress=yes +fi + +# Check whether --enable-function-sections was given. +if test "${enable_function_sections+set}" = set; then : + enableval=$enable_function_sections; +else + enable_function_sections=no +fi + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.2' +macro_revision='1.3337' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + + + if test "$enable_libevent_regress" = "yes"; then + BUILD_REGRESS_TRUE= + BUILD_REGRESS_FALSE='#' +else + BUILD_REGRESS_TRUE='#' + BUILD_REGRESS_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntoa" >&5 +$as_echo_n "checking for library containing inet_ntoa... " >&6; } +if ${ac_cv_search_inet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_ntoa (); +int +main () +{ +return inet_ntoa (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inet_ntoa=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inet_ntoa+:} false; then : + break +fi +done +if ${ac_cv_search_inet_ntoa+:} false; then : + +else + ac_cv_search_inet_ntoa=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_ntoa" >&5 +$as_echo "$ac_cv_search_inet_ntoa" >&6; } +ac_res=$ac_cv_search_inet_ntoa +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_aton" >&5 +$as_echo_n "checking for library containing inet_aton... " >&6; } +if ${ac_cv_search_inet_aton+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_aton (); +int +main () +{ +return inet_aton (); + ; + return 0; +} +_ACEOF +for ac_lib in '' resolv; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inet_aton=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inet_aton+:} false; then : + break +fi +done +if ${ac_cv_search_inet_aton+:} false; then : + +else + ac_cv_search_inet_aton=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_aton" >&5 +$as_echo "$ac_cv_search_inet_aton" >&6; } +ac_res=$ac_cv_search_inet_aton +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break +fi +done +if ${ac_cv_search_clock_gettime+:} false; then : + +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sendfile" >&5 +$as_echo_n "checking for library containing sendfile... " >&6; } +if ${ac_cv_search_sendfile+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sendfile (); +int +main () +{ +return sendfile (); + ; + return 0; +} +_ACEOF +for ac_lib in '' sendfile; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_sendfile=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_sendfile+:} false; then : + break +fi +done +if ${ac_cv_search_sendfile+:} false; then : + +else + ac_cv_search_sendfile=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sendfile" >&5 +$as_echo "$ac_cv_search_sendfile" >&6; } +ac_res=$ac_cv_search_sendfile +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for WIN32" >&5 +$as_echo_n "checking for WIN32... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef WIN32 +die horribly +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + bwin32=true; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + bwin32=false; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CYGWIN" >&5 +$as_echo_n "checking for CYGWIN... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __CYGWIN__ +die horribly +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cygwin=true; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + cygwin=false; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + +fi + +done + + +if test "x$ac_cv_header_zlib_h" = "xyes"; then +save_LIBS="$LIBS" +LIBS="" +ZLIB_LIBS="" +have_zlib=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inflateEnd" >&5 +$as_echo_n "checking for library containing inflateEnd... " >&6; } +if ${ac_cv_search_inflateEnd+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inflateEnd (); +int +main () +{ +return inflateEnd (); + ; + return 0; +} +_ACEOF +for ac_lib in '' z; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inflateEnd=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inflateEnd+:} false; then : + break +fi +done +if ${ac_cv_search_inflateEnd+:} false; then : + +else + ac_cv_search_inflateEnd=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inflateEnd" >&5 +$as_echo "$ac_cv_search_inflateEnd" >&6; } +ac_res=$ac_cv_search_inflateEnd +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_zlib=yes + ZLIB_LIBS="$LIBS" + +$as_echo "#define HAVE_LIBZ 1" >>confdefs.h + +fi + +LIBS="$save_LIBS" + +fi + if test "$have_zlib" = "yes"; then + ZLIB_REGRESS_TRUE= + ZLIB_REGRESS_FALSE='#' +else + ZLIB_REGRESS_TRUE='#' + ZLIB_REGRESS_FALSE= +fi + + +if test "$bwin32" = true; then + EV_LIB_WS32=-lws2_32 + EV_LIB_GDI=-lgdi32 +else + EV_LIB_WS32= + EV_LIB_GDI= +fi + + + + +for ac_header in openssl/bio.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "openssl/bio.h" "ac_cv_header_openssl_bio_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_bio_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_BIO_H 1 +_ACEOF + +fi + +done + + +if test "$enable_openssl" = "yes"; then +save_LIBS="$LIBS" +LIBS="" +OPENSSL_LIBS="" +have_openssl=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_new" >&5 +$as_echo_n "checking for library containing SSL_new... " >&6; } +if ${ac_cv_search_SSL_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SSL_new (); +int +main () +{ +return SSL_new (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ssl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib -lcrypto $EV_LIB_GDI $EV_LIB_WS32 $OPENSSL_LIBADD $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_SSL_new=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_SSL_new+:} false; then : + break +fi +done +if ${ac_cv_search_SSL_new+:} false; then : + +else + ac_cv_search_SSL_new=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_new" >&5 +$as_echo "$ac_cv_search_SSL_new" >&6; } +ac_res=$ac_cv_search_SSL_new +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_openssl=yes + OPENSSL_LIBS="$LIBS -lcrypto $EV_LIB_GDI $EV_LIB_WS32 $OPENSSL_LIBADD" + +$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h + +else + have_openssl=no +fi + +LIBS="$save_LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +for ac_header in fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in.h netinet/in6.h sys/socket.h sys/uio.h arpa/inet.h sys/eventfd.h sys/mman.h sys/sendfile.h sys/wait.h netdb.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/sysctl.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" " +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +" +if test "x$ac_cv_header_sys_sysctl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SYSCTL_H 1 +_ACEOF + +fi + +done + +if test "x$ac_cv_header_sys_queue_h" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TAILQ_FOREACH in sys/queue.h" >&5 +$as_echo_n "checking for TAILQ_FOREACH in sys/queue.h... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef TAILQ_FOREACH + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_TAILQFOREACH 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for timeradd in sys/time.h" >&5 +$as_echo_n "checking for timeradd in sys/time.h... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef timeradd + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + +$as_echo "#define HAVE_TIMERADD 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for timercmp in sys/time.h" >&5 +$as_echo_n "checking for timercmp in sys/time.h... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef timercmp + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + +$as_echo "#define HAVE_TIMERCMP 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for timerclear in sys/time.h" >&5 +$as_echo_n "checking for timerclear in sys/time.h... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef timerclear + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + +$as_echo "#define HAVE_TIMERCLEAR 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for timerisset in sys/time.h" >&5 +$as_echo_n "checking for timerisset in sys/time.h... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef timerisset + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + +$as_echo "#define HAVE_TIMERISSET 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + +fi + +if test "x$ac_cv_header_sys_sysctl_h" = "xyes"; then + ac_fn_c_check_decl "$LINENO" "CTL_KERN" "ac_cv_have_decl_CTL_KERN" "#include + #include + +" +if test "x$ac_cv_have_decl_CTL_KERN" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_CTL_KERN $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "KERN_RANDOM" "ac_cv_have_decl_KERN_RANDOM" "#include + #include + +" +if test "x$ac_cv_have_decl_KERN_RANDOM" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_KERN_RANDOM $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "RANDOM_UUID" "ac_cv_have_decl_RANDOM_UUID" "#include + #include + +" +if test "x$ac_cv_have_decl_RANDOM_UUID" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_RANDOM_UUID $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "KERN_ARND" "ac_cv_have_decl_KERN_ARND" "#include + #include + +" +if test "x$ac_cv_have_decl_KERN_ARND" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_KERN_ARND $ac_have_decl +_ACEOF + +fi + + if test x$bwin32 = xtrue; then + BUILD_WIN32_TRUE= + BUILD_WIN32_FALSE='#' +else + BUILD_WIN32_TRUE='#' + BUILD_WIN32_FALSE= +fi + + if test x$cygwin = xtrue; then + BUILD_CYGWIN_TRUE= + BUILD_CYGWIN_FALSE='#' +else + BUILD_CYGWIN_TRUE='#' + BUILD_CYGWIN_FALSE= +fi + + if test x$bwin32 = xtrue || test x$cygwin = xtrue; then + BUILD_WITH_NO_UNDEFINED_TRUE= + BUILD_WITH_NO_UNDEFINED_FALSE='#' +else + BUILD_WITH_NO_UNDEFINED_TRUE='#' + BUILD_WITH_NO_UNDEFINED_FALSE= +fi + + +if test x$bwin32 = xtrue; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getservbyname" >&5 +$as_echo_n "checking for library containing getservbyname... " >&6; } +if ${ac_cv_search_getservbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getservbyname (); +int +main () +{ +return getservbyname (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ws2_32; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_getservbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_getservbyname+:} false; then : + break +fi +done +if ${ac_cv_search_getservbyname+:} false; then : + +else + ac_cv_search_getservbyname=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getservbyname" >&5 +$as_echo "$ac_cv_search_getservbyname" >&6; } +ac_res=$ac_cv_search_getservbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + + +for ac_func in gettimeofday vasprintf fcntl clock_gettime strtok_r strsep +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in getnameinfo strlcpy inet_ntop inet_pton signal sigaction strtoll inet_aton pipe eventfd sendfile mmap splice arc4random arc4random_buf issetugid geteuid getegid getprotobynumber setenv unsetenv putenv sysctl +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 +$as_echo_n "checking for getaddrinfo... " >&6; } +if ${libevent_cv_getaddrinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #ifdef HAVE_NETDB_H + #include + #endif + +int +main () +{ + + getaddrinfo; + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libevent_cv_getaddrinfo=yes +else + libevent_cv_getaddrinfo=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libevent_cv_getaddrinfo" >&5 +$as_echo "$libevent_cv_getaddrinfo" >&6; } +if test "$libevent_cv_getaddrinfo" = "yes" ; then + +$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h + +else + +for ac_func in getservbyname +do : + ac_fn_c_check_func "$LINENO" "getservbyname" "ac_cv_func_getservbyname" +if test "x$ac_cv_func_getservbyname" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETSERVBYNAME 1 +_ACEOF + +fi +done + +# Check for gethostbyname_r in all its glorious incompatible versions. +# (This is cut-and-pasted from Tor, which based its logic on +# Python's configure.in.) + + +ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r" +if test "x$ac_cv_func_gethostbyname_r" = xyes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how many arguments gethostbyname_r() wants" >&5 +$as_echo_n "checking how many arguments gethostbyname_r() wants... " >&6; } + OLD_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $MY_CPPFLAGS $MY_THREAD_CPPFLAGS $MY_CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + + char *cp1, *cp2; + struct hostent *h1, *h2; + int i1, i2; + (void)gethostbyname_r(cp1,h1,cp2,i1,&h2,&i2); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + $as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h + + +$as_echo "#define HAVE_GETHOSTBYNAME_R_6_ARG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: 6" >&5 +$as_echo "6" >&6; } + +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + + char *cp1, *cp2; + struct hostent *h1; + int i1, i2; + (void)gethostbyname_r(cp1,h1,cp2,i1,&i2); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + $as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h + + +$as_echo "#define HAVE_GETHOSTBYNAME_R_5_ARG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: 5" >&5 +$as_echo "5" >&6; } + +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + + char *cp1; + struct hostent *h1; + struct hostent_data hd; + (void) gethostbyname_r(cp1,h1,&hd); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + $as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h + + +$as_echo "#define HAVE_GETHOSTBYNAME_R_3_ARG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: 3" >&5 +$as_echo "3" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: 0" >&5 +$as_echo "0" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$OLD_CFLAGS + +fi + + +fi + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for F_SETFD in fcntl.h" >&5 +$as_echo_n "checking for F_SETFD in fcntl.h... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define _GNU_SOURCE +#include +#ifdef F_SETFD +yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + +$as_echo "#define HAVE_SETFD 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f conftest* + + +needsignal=no +haveselect=no +if test x$bwin32 != xtrue; then + for ac_func in select +do : + ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select" +if test "x$ac_cv_func_select" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SELECT 1 +_ACEOF + haveselect=yes +fi +done + + if test "x$haveselect" = "xyes" ; then + needsignal=yes + fi +fi + if test "x$haveselect" = "xyes"; then + SELECT_BACKEND_TRUE= + SELECT_BACKEND_FALSE='#' +else + SELECT_BACKEND_TRUE='#' + SELECT_BACKEND_FALSE= +fi + + +havepoll=no +for ac_func in poll +do : + ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll" +if test "x$ac_cv_func_poll" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_POLL 1 +_ACEOF + havepoll=yes +fi +done + +if test "x$havepoll" = "xyes" ; then + needsignal=yes +fi + if test "x$havepoll" = "xyes"; then + POLL_BACKEND_TRUE= + POLL_BACKEND_FALSE='#' +else + POLL_BACKEND_TRUE='#' + POLL_BACKEND_FALSE= +fi + + +havedevpoll=no +if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then + +$as_echo "#define HAVE_DEVPOLL 1" >>confdefs.h + +fi + if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then + DEVPOLL_BACKEND_TRUE= + DEVPOLL_BACKEND_FALSE='#' +else + DEVPOLL_BACKEND_TRUE='#' + DEVPOLL_BACKEND_FALSE= +fi + + +havekqueue=no +if test "x$ac_cv_header_sys_event_h" = "xyes"; then + for ac_func in kqueue +do : + ac_fn_c_check_func "$LINENO" "kqueue" "ac_cv_func_kqueue" +if test "x$ac_cv_func_kqueue" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_KQUEUE 1 +_ACEOF + havekqueue=yes +fi +done + + if test "x$havekqueue" = "xyes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working kqueue" >&5 +$as_echo_n "checking for working kqueue... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int kq; + int n; + int fd[2]; + struct kevent ev; + struct timespec ts; + char buf[8000]; + + if (pipe(fd) == -1) + exit(1); + if (fcntl(fd[1], F_SETFL, O_NONBLOCK) == -1) + exit(1); + + while ((n = write(fd[1], buf, sizeof(buf))) == sizeof(buf)) + ; + + if ((kq = kqueue()) == -1) + exit(1); + + memset(&ev, 0, sizeof(ev)); + ev.ident = fd[1]; + ev.filter = EVFILT_WRITE; + ev.flags = EV_ADD | EV_ENABLE; + n = kevent(kq, &ev, 1, NULL, 0, NULL); + if (n == -1) + exit(1); + + read(fd[0], buf, sizeof(buf)); + + ts.tv_sec = 0; + ts.tv_nsec = 0; + n = kevent(kq, NULL, 0, &ev, 1, &ts); + if (n == -1 || n == 0) + exit(1); + + exit(0); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_WORKING_KQUEUE 1" >>confdefs.h + + havekqueue=yes + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi + if test "x$havekqueue" = "xyes"; then + KQUEUE_BACKEND_TRUE= + KQUEUE_BACKEND_FALSE='#' +else + KQUEUE_BACKEND_TRUE='#' + KQUEUE_BACKEND_FALSE= +fi + + +haveepollsyscall=no +haveepoll=no +for ac_func in epoll_ctl +do : + ac_fn_c_check_func "$LINENO" "epoll_ctl" "ac_cv_func_epoll_ctl" +if test "x$ac_cv_func_epoll_ctl" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EPOLL_CTL 1 +_ACEOF + haveepoll=yes +fi +done + +if test "x$haveepoll" = "xyes" ; then + +$as_echo "#define HAVE_EPOLL 1" >>confdefs.h + + needsignal=yes +fi +if test "x$ac_cv_header_sys_epoll_h" = "xyes"; then + if test "x$haveepoll" = "xno" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for epoll system call" >&5 +$as_echo_n "checking for epoll system call... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +#include +#include + +int +epoll_create(int size) +{ + return (syscall(__NR_epoll_create, size)); +} + +int +main(int argc, char **argv) +{ + int epfd; + + epfd = epoll_create(256); + exit (epfd == -1 ? 1 : 0); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_EPOLL 1" >>confdefs.h + + needsignal=yes + have_epoll=yes + case " $LIBOBJS " in + *" epoll_sub.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS epoll_sub.$ac_objext" + ;; +esac + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi + if test "x$haveepoll" = "xyes"; then + EPOLL_BACKEND_TRUE= + EPOLL_BACKEND_FALSE='#' +else + EPOLL_BACKEND_TRUE='#' + EPOLL_BACKEND_FALSE= +fi + + +haveeventports=no +for ac_func in port_create +do : + ac_fn_c_check_func "$LINENO" "port_create" "ac_cv_func_port_create" +if test "x$ac_cv_func_port_create" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PORT_CREATE 1 +_ACEOF + haveeventports=yes +fi +done + +if test "x$haveeventports" = "xyes" ; then + +$as_echo "#define HAVE_EVENT_PORTS 1" >>confdefs.h + + needsignal=yes +fi + if test "x$haveeventports" = "xyes"; then + EVPORT_BACKEND_TRUE= + EVPORT_BACKEND_FALSE='#' +else + EVPORT_BACKEND_TRUE='#' + EVPORT_BACKEND_FALSE= +fi + + +if test "x$bwin32" = "xtrue"; then + needsignal=yes +fi + + if test "x$needsignal" = "xyes"; then + SIGNAL_SUPPORT_TRUE= + SIGNAL_SUPPORT_FALSE='#' +else + SIGNAL_SUPPORT_TRUE='#' + SIGNAL_SUPPORT_FALSE= +fi + + +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + + +ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +" +if test "x$ac_cv_type_uint64_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT64_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +" +if test "x$ac_cv_type_uint32_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT32_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +" +if test "x$ac_cv_type_uint16_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT16_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +" +if test "x$ac_cv_type_uint8_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT8_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +" +if test "x$ac_cv_type_uintptr_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINTPTR_T 1 +_ACEOF + + +fi + + +ac_fn_c_check_type "$LINENO" "fd_mask" "ac_cv_type_fd_mask" "#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +" +if test "x$ac_cv_type_fd_mask" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_FD_MASK 1 +_ACEOF + + +fi + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5 +$as_echo_n "checking size of long long... " >&6; } +if ${ac_cv_sizeof_long_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5 +$as_echo "$ac_cv_sizeof_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if ${ac_cv_sizeof_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 +$as_echo_n "checking size of short... " >&6; } +if ${ac_cv_sizeof_short+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (short) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 +$as_echo "$ac_cv_sizeof_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5 +$as_echo_n "checking size of size_t... " >&6; } +if ${ac_cv_sizeof_size_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_size_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (size_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_size_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5 +$as_echo "$ac_cv_sizeof_size_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 +$as_echo_n "checking size of void *... " >&6; } +if ${ac_cv_sizeof_void_p+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_void_p" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (void *) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_void_p=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 +$as_echo "$ac_cv_sizeof_void_p" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOID_P $ac_cv_sizeof_void_p +_ACEOF + + + +ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#define _GNU_SOURCE +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_type_struct_in6_addr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN6_ADDR 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "#define _GNU_SOURCE +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN6 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "sa_family_t" "ac_cv_type_sa_family_t" "#define _GNU_SOURCE +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_type_sa_family_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_SA_FAMILY_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "#define _GNU_SOURCE +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_type_struct_addrinfo" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_ADDRINFO 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" "#define _GNU_SOURCE +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct in6_addr" "s6_addr32" "ac_cv_member_struct_in6_addr_s6_addr32" "#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_member_struct_in6_addr_s6_addr32" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct in6_addr" "s6_addr16" "ac_cv_member_struct_in6_addr_s6_addr16" "#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_member_struct_in6_addr_s6_addr16" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" "#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_len" "ac_cv_member_struct_sockaddr_in6_sin6_len" "#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_in6_sin6_len" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct sockaddr_storage" "ss_family" "ac_cv_member_struct_sockaddr_storage_ss_family" "#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_storage_ss_family" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct sockaddr_storage" "__ss_family" "ac_cv_member_struct_sockaddr_storage___ss_family" "#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_storage___ss_family" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY 1 +_ACEOF + + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5 +$as_echo_n "checking for socklen_t... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include +int +main () +{ +socklen_t x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define socklen_t unsigned int" >>confdefs.h + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether our compiler supports __func__" >&5 +$as_echo_n "checking whether our compiler supports __func__... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + const char *cp = __func__; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether our compiler supports __FUNCTION__" >&5 +$as_echo_n "checking whether our compiler supports __FUNCTION__... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + const char *cp = __FUNCTION__; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define __func__ __FUNCTION__" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define __func__ __FILE__" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +# check if we can compile with pthreads +have_pthreads=no +if test x$bwin32 != xtrue && test "$enable_thread_support" != "no"; then + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 +$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + acx_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 +$as_echo "$acx_pthread_ok" >&6; } + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 +$as_echo_n "checking whether pthreads work with $flag... " >&6; } + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_acx_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$acx_pthread_config"; then + ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_acx_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" +fi +fi +acx_pthread_config=$ac_cv_prog_acx_pthread_config +if test -n "$acx_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 +$as_echo "$acx_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 +$as_echo_n "checking for the pthreads library -l$flag... " >&6; } + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + acx_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 +$as_echo "$acx_pthread_ok" >&6; } + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr=$attr; return attr; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + attr_name=$attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 +$as_echo "$attr_name" >&6; } + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $attr_name +_ACEOF + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 +$as_echo_n "checking if more special flags are required for pthreads... " >&6; } + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 +$as_echo "${flag}" >&6; } + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + for ac_prog in xlc_r cc_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" + + else + PTHREAD_CC=$CC + fi +else + PTHREAD_CC="$CC" +fi + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + + +$as_echo "#define HAVE_PTHREADS 1" >>confdefs.h + + have_pthreads=yes + : +else + acx_pthread_ok=no + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of pthread_t" >&5 +$as_echo_n "checking size of pthread_t... " >&6; } +if ${ac_cv_sizeof_pthread_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_t))" "ac_cv_sizeof_pthread_t" "$ac_includes_default + #include + +"; then : + +else + if test "$ac_cv_type_pthread_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (pthread_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_pthread_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_pthread_t" >&5 +$as_echo "$ac_cv_sizeof_pthread_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_PTHREAD_T $ac_cv_sizeof_pthread_t +_ACEOF + + +fi + if test "$have_pthreads" != "no" && test "$enable_thread_support" != "no"; then + PTHREADS_TRUE= + PTHREADS_FALSE='#' +else + PTHREADS_TRUE='#' + PTHREADS_FALSE= +fi + + +# check if we should compile locking into the library +if test x$enable_thread_support = xno; then + +$as_echo "#define DISABLE_THREAD_SUPPORT 1" >>confdefs.h + +fi + +# check if we should hard-code the mm functions. +if test x$enable_malloc_replacement = xno; then + +$as_echo "#define DISABLE_MM_REPLACEMENT 1" >>confdefs.h + +fi + +# check if we should hard-code debugging out +if test x$enable_debug_mode = xno; then + +$as_echo "#define DISABLE_DEBUG_MODE 1" >>confdefs.h + +fi + +# check if we have and should use openssl + if test "$enable_openssl" != "no" && test "$have_openssl" = "yes"; then + OPENSSL_TRUE= + OPENSSL_FALSE='#' +else + OPENSSL_TRUE='#' + OPENSSL_FALSE= +fi + + +# Add some more warnings which we use in development but not in the +# released versions. (Some relevant gcc versions can't handle these.) +if test x$enable_gcc_warnings = xyes && test "$GCC" = "yes"; then + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if !defined(__GNUC__) || (__GNUC__ < 4) +#error +#endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + have_gcc4=yes +else + have_gcc4=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) +#error +#endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + have_gcc42=yes +else + have_gcc42=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) +#error +#endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + have_gcc45=yes +else + have_gcc45=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if !defined(__clang__) +#error +#endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + have_clang=yes +else + have_clang=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror" + CFLAGS="$CFLAGS -Wno-unused-parameter -Wstrict-aliasing" + + if test x$have_gcc4 = xyes ; then + # These warnings break gcc 3.3.5 and work on gcc 4.0.2 + CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement" + #CFLAGS="$CFLAGS -Wold-style-definition" + fi + + if test x$have_gcc42 = xyes ; then + # These warnings break gcc 4.0.2 and work on gcc 4.2 + CFLAGS="$CFLAGS -Waddress" + fi + + if test x$have_gcc42 = xyes && test x$have_clang = xno; then + # These warnings break gcc 4.0.2 and clang, but work on gcc 4.2 + CFLAGS="$CFLAGS -Wnormalized=id -Woverride-init" + fi + + if test x$have_gcc45 = xyes ; then + # These warnings work on gcc 4.5 + CFLAGS="$CFLAGS -Wlogical-op" + fi + + if test x$have_clang = xyes; then + # Disable the unused-function warnings, because these trigger + # for minheap-internal.h related code. + CFLAGS="$CFLAGS -Wno-unused-function" + fi + +##This will break the world on some 64-bit architectures +# CFLAGS="$CFLAGS -Winline" + +fi + +LIBEVENT_GC_SECTIONS= +if test "$GCC" = yes && test "$enable_function_sections" = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if linker supports omitting unused code and data" >&5 +$as_echo_n "checking if linker supports omitting unused code and data... " >&6; } +if ${libevent_cv_gc_sections_runs+:} false; then : + $as_echo_n "(cached) " >&6 +else + + origCFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wl,--gc-sections" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + FILE * fpC; + char buf[32]; + size_t cch; + int read_success_once; + + fpC = fopen("conftest.c", "r"); + if (NULL == fpC) + exit(1); + do { + cch = fread(buf, sizeof(buf), 1, fpC); + read_success_once |= (0 != cch); + } while (0 != cch); + if (!read_success_once) + exit(2); + if (!feof(fpC)) + exit(3); + if (0 != fclose(fpC)) + exit(4); + + exit(EXIT_SUCCESS); + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + if test "X$cross_compiling" = "Xyes" || grep gc-sections conftest.err ; then + libevent_cv_gc_sections_runs=no + else + libevent_cv_gc_sections_runs=no + ./conftest >/dev/null 2>&1 && libevent_cv_gc_sections_runs=yes + fi + +else + libevent_cv_gc_sections_runs=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$origCFLAGS" + { origCFLAGS=; unset origCFLAGS;} + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libevent_cv_gc_sections_runs" >&5 +$as_echo "$libevent_cv_gc_sections_runs" >&6; } + case "$libevent_cv_gc_sections_runs" in + yes) + CFLAGS="-ffunction-sections -fdata-sections $CFLAGS" + LIBEVENT_GC_SECTIONS="-Wl,--gc-sections" + ;; + esac +fi + + + if test "$enable_libevent_install" = "yes"; then + INSTALL_LIBEVENT_TRUE= + INSTALL_LIBEVENT_FALSE='#' +else + INSTALL_LIBEVENT_TRUE='#' + INSTALL_LIBEVENT_FALSE= +fi + + +ac_config_files="$ac_config_files libevent.pc libevent_openssl.pc libevent_pthreads.pc" + +ac_config_files="$ac_config_files Makefile include/Makefile test/Makefile sample/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_REGRESS_TRUE}" && test -z "${BUILD_REGRESS_FALSE}"; then + as_fn_error $? "conditional \"BUILD_REGRESS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ZLIB_REGRESS_TRUE}" && test -z "${ZLIB_REGRESS_FALSE}"; then + as_fn_error $? "conditional \"ZLIB_REGRESS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_WIN32_TRUE}" && test -z "${BUILD_WIN32_FALSE}"; then + as_fn_error $? "conditional \"BUILD_WIN32\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CYGWIN_TRUE}" && test -z "${BUILD_CYGWIN_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CYGWIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_WITH_NO_UNDEFINED_TRUE}" && test -z "${BUILD_WITH_NO_UNDEFINED_FALSE}"; then + as_fn_error $? "conditional \"BUILD_WITH_NO_UNDEFINED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SELECT_BACKEND_TRUE}" && test -z "${SELECT_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"SELECT_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${POLL_BACKEND_TRUE}" && test -z "${POLL_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"POLL_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEVPOLL_BACKEND_TRUE}" && test -z "${DEVPOLL_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"DEVPOLL_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${KQUEUE_BACKEND_TRUE}" && test -z "${KQUEUE_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"KQUEUE_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${EPOLL_BACKEND_TRUE}" && test -z "${EPOLL_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"EPOLL_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${EVPORT_BACKEND_TRUE}" && test -z "${EVPORT_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"EVPORT_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SIGNAL_SUPPORT_TRUE}" && test -z "${SIGNAL_SUPPORT_FALSE}"; then + as_fn_error $? "conditional \"SIGNAL_SUPPORT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PTHREADS_TRUE}" && test -z "${PTHREADS_FALSE}"; then + as_fn_error $? "conditional \"PTHREADS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${OPENSSL_TRUE}" && test -z "${OPENSSL_FALSE}"; then + as_fn_error $? "conditional \"OPENSSL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INSTALL_LIBEVENT_TRUE}" && test -z "${INSTALL_LIBEVENT_FALSE}"; then + as_fn_error $? "conditional \"INSTALL_LIBEVENT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "libevent.pc") CONFIG_FILES="$CONFIG_FILES libevent.pc" ;; + "libevent_openssl.pc") CONFIG_FILES="$CONFIG_FILES libevent_openssl.pc" ;; + "libevent_pthreads.pc") CONFIG_FILES="$CONFIG_FILES libevent_pthreads.pc" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; + "sample/Makefile") CONFIG_FILES="$CONFIG_FILES sample/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/libevent/configure.in b/libevent/configure.in new file mode 100644 index 0000000..285637b --- /dev/null +++ b/libevent/configure.in @@ -0,0 +1,796 @@ +dnl configure.in for libevent +dnl Copyright 2000-2007 Niels Provos +dnl Copyright 2007-2012 Niels Provos and Nick Mathewson +dnl +dnl See LICENSE for copying information. +dnl +dnl Original version Dug Song + +AC_PREREQ(2.59c) +AC_INIT(event.c) + +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE(libevent,2.0.18-stable) +dnl Enable silent Automake rules if present +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) +AM_CONFIG_HEADER(config.h) +AC_DEFINE(NUMERIC_VERSION, 0x02001200, [Numeric representation of the version]) + +dnl Initialize prefix. +if test "$prefix" = "NONE"; then + prefix="/usr/local" +fi + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +dnl the 'build' machine is where we run configure and compile +dnl the 'host' machine is where the resulting stuff runs. + +case "$host_os" in + + osf5*) + CFLAGS="$CFLAGS -D_OSF_SOURCE" + ;; +esac + +dnl Checks for programs. +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MKDIR_P + +AC_PROG_GCC_TRADITIONAL + +if test "$GCC" = "yes" ; then + # Enable many gcc warnings by default... + CFLAGS="$CFLAGS -Wall" + # And disable the strict-aliasing optimization, since it breaks + # our sockaddr-handling code in strange ways. + CFLAGS="$CFLAGS -fno-strict-aliasing" +fi + +# OS X Lion started deprecating the system openssl. Let's just disable +# all deprecation warnings on OS X. +case "$host_os" in + + darwin*) + CFLAGS="$CFLAGS -Wno-deprecated-declarations" + ;; +esac + +AC_ARG_ENABLE(gcc-warnings, + AS_HELP_STRING(--enable-gcc-warnings, enable verbose warnings with GCC)) +AC_ARG_ENABLE(thread-support, + AS_HELP_STRING(--disable-thread-support, disable support for threading), + [], [enable_thread_support=yes]) +AC_ARG_ENABLE(malloc-replacement, + AS_HELP_STRING(--disable-malloc-replacement, disable support for replacing the memory mgt functions), + [], [enable_malloc_replacement=yes]) +AC_ARG_ENABLE(openssl, + AS_HELP_STRING(--disable-openssl, disable support for openssl encryption), + [], [enable_openssl=yes]) +AC_ARG_ENABLE(debug-mode, + AS_HELP_STRING(--disable-debug-mode, disable support for running in debug mode), + [], [enable_debug_mode=yes]) +AC_ARG_ENABLE([libevent-install], + AS_HELP_STRING([--disable-libevent-install, disable installation of libevent]), + [], [enable_libevent_install=yes]) +AC_ARG_ENABLE([libevent-regress], + AS_HELP_STRING([--disable-libevent-regress, skip regress in make check]), + [], [enable_libevent_regress=yes]) +AC_ARG_ENABLE([function-sections], + AS_HELP_STRING([--enable-function-sections, make static library allow smaller binaries with --gc-sections]), + [], [enable_function_sections=no]) + + +AC_PROG_LIBTOOL + +dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get +dnl built by default. You can also turn shared libs on and off from +dnl the command line with --enable-shared and --disable-shared. +dnl AC_DISABLE_SHARED +AC_SUBST(LIBTOOL_DEPS) + +AM_CONDITIONAL([BUILD_REGRESS], [test "$enable_libevent_regress" = "yes"]) + +dnl Checks for libraries. +AC_SEARCH_LIBS([inet_ntoa], [nsl]) +AC_SEARCH_LIBS([socket], [socket]) +AC_SEARCH_LIBS([inet_aton], [resolv]) +AC_SEARCH_LIBS([clock_gettime], [rt]) +AC_SEARCH_LIBS([sendfile], [sendfile]) + +dnl - check if the macro WIN32 is defined on this compiler. +dnl - (this is how we check for a windows version of GCC) +AC_MSG_CHECKING(for WIN32) +AC_TRY_COMPILE(, + [ +#ifndef WIN32 +die horribly +#endif + ], + bwin32=true; AC_MSG_RESULT(yes), + bwin32=false; AC_MSG_RESULT(no), +) + +dnl - check if the macro __CYGWIN__ is defined on this compiler. +dnl - (this is how we check for a cygwin version of GCC) +AC_MSG_CHECKING(for CYGWIN) +AC_TRY_COMPILE(, + [ +#ifndef __CYGWIN__ +die horribly +#endif + ], + cygwin=true; AC_MSG_RESULT(yes), + cygwin=false; AC_MSG_RESULT(no), +) + +AC_CHECK_HEADERS([zlib.h]) + +if test "x$ac_cv_header_zlib_h" = "xyes"; then +dnl Determine if we have zlib for regression tests +dnl Don't put this one in LIBS +save_LIBS="$LIBS" +LIBS="" +ZLIB_LIBS="" +have_zlib=no +AC_SEARCH_LIBS([inflateEnd], [z], + [have_zlib=yes + ZLIB_LIBS="$LIBS" + AC_DEFINE(HAVE_LIBZ, 1, [Define if the system has zlib])]) +LIBS="$save_LIBS" +AC_SUBST(ZLIB_LIBS) +fi +AM_CONDITIONAL(ZLIB_REGRESS, [test "$have_zlib" = "yes"]) + +dnl See if we have openssl. This doesn't go in LIBS either. +if test "$bwin32" = true; then + EV_LIB_WS32=-lws2_32 + EV_LIB_GDI=-lgdi32 +else + EV_LIB_WS32= + EV_LIB_GDI= +fi +AC_SUBST(EV_LIB_WS32) +AC_SUBST(EV_LIB_GDI) +AC_SUBST(OPENSSL_LIBADD) + +AC_CHECK_HEADERS([openssl/bio.h]) + +if test "$enable_openssl" = "yes"; then +save_LIBS="$LIBS" +LIBS="" +OPENSSL_LIBS="" +have_openssl=no +AC_SEARCH_LIBS([SSL_new], [ssl], + [have_openssl=yes + OPENSSL_LIBS="$LIBS -lcrypto $EV_LIB_GDI $EV_LIB_WS32 $OPENSSL_LIBADD" + AC_DEFINE(HAVE_OPENSSL, 1, [Define if the system has openssl])], + [have_openssl=no], + [-lcrypto $EV_LIB_GDI $EV_LIB_WS32 $OPENSSL_LIBADD]) +LIBS="$save_LIBS" +AC_SUBST(OPENSSL_LIBS) +fi + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in.h netinet/in6.h sys/socket.h sys/uio.h arpa/inet.h sys/eventfd.h sys/mman.h sys/sendfile.h sys/wait.h netdb.h]) +AC_CHECK_HEADERS(sys/sysctl.h, [], [], [ +#ifdef HAVE_SYS_PARAM_H +#include +#endif +]) +if test "x$ac_cv_header_sys_queue_h" = "xyes"; then + AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h) + AC_EGREP_CPP(yes, +[ +#include +#ifdef TAILQ_FOREACH + yes +#endif +], [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_TAILQFOREACH, 1, + [Define if TAILQ_FOREACH is defined in ])], + AC_MSG_RESULT(no) + ) +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + AC_MSG_CHECKING(for timeradd in sys/time.h) + AC_EGREP_CPP(yes, +[ +#include +#ifdef timeradd + yes +#endif +], [ AC_DEFINE(HAVE_TIMERADD, 1, + [Define if timeradd is defined in ]) + AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) +) +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + AC_MSG_CHECKING(for timercmp in sys/time.h) + AC_EGREP_CPP(yes, +[ +#include +#ifdef timercmp + yes +#endif +], [ AC_DEFINE(HAVE_TIMERCMP, 1, + [Define if timercmp is defined in ]) + AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) +) +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + AC_MSG_CHECKING(for timerclear in sys/time.h) + AC_EGREP_CPP(yes, +[ +#include +#ifdef timerclear + yes +#endif +], [ AC_DEFINE(HAVE_TIMERCLEAR, 1, + [Define if timerclear is defined in ]) + AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) +) +fi + +if test "x$ac_cv_header_sys_time_h" = "xyes"; then + AC_MSG_CHECKING(for timerisset in sys/time.h) + AC_EGREP_CPP(yes, +[ +#include +#ifdef timerisset + yes +#endif +], [ AC_DEFINE(HAVE_TIMERISSET, 1, + [Define if timerisset is defined in ]) + AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) +) +fi + +if test "x$ac_cv_header_sys_sysctl_h" = "xyes"; then + AC_CHECK_DECLS([CTL_KERN, KERN_RANDOM, RANDOM_UUID, KERN_ARND], [], [], + [[#include + #include ]] + ) +fi + +AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue) +AM_CONDITIONAL(BUILD_CYGWIN, test x$cygwin = xtrue) +AM_CONDITIONAL(BUILD_WITH_NO_UNDEFINED, test x$bwin32 = xtrue || test x$cygwin = xtrue) + +if test x$bwin32 = xtrue; then + AC_SEARCH_LIBS([getservbyname],[ws2_32]) +fi + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_HEADER_TIME + +dnl Checks for library functions. +AC_CHECK_FUNCS([gettimeofday vasprintf fcntl clock_gettime strtok_r strsep]) +AC_CHECK_FUNCS([getnameinfo strlcpy inet_ntop inet_pton signal sigaction strtoll inet_aton pipe eventfd sendfile mmap splice arc4random arc4random_buf issetugid geteuid getegid getprotobynumber setenv unsetenv putenv sysctl]) + +AC_CACHE_CHECK( + [for getaddrinfo], + [libevent_cv_getaddrinfo], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ + #ifdef HAVE_NETDB_H + #include + #endif + ]], + [[ + getaddrinfo; + ]] + )], + [libevent_cv_getaddrinfo=yes], + [libevent_cv_getaddrinfo=no] + )] +) +if test "$libevent_cv_getaddrinfo" = "yes" ; then + AC_DEFINE([HAVE_GETADDRINFO], [1], [Do we have getaddrinfo()?]) +else + +AC_CHECK_FUNCS([getservbyname]) +# Check for gethostbyname_r in all its glorious incompatible versions. +# (This is cut-and-pasted from Tor, which based its logic on +# Python's configure.in.) +AH_TEMPLATE(HAVE_GETHOSTBYNAME_R, + [Define this if you have any gethostbyname_r()]) + +AC_CHECK_FUNC(gethostbyname_r, [ + AC_MSG_CHECKING([how many arguments gethostbyname_r() wants]) + OLD_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $MY_CPPFLAGS $MY_THREAD_CPPFLAGS $MY_CFLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#include + ], [[ + char *cp1, *cp2; + struct hostent *h1, *h2; + int i1, i2; + (void)gethostbyname_r(cp1,h1,cp2,i1,&h2,&i2); + ]])],[ + AC_DEFINE(HAVE_GETHOSTBYNAME_R) + AC_DEFINE(HAVE_GETHOSTBYNAME_R_6_ARG, 1, + [Define this if gethostbyname_r takes 6 arguments]) + AC_MSG_RESULT(6) + ], [ + AC_TRY_COMPILE([ +#include + ], [ + char *cp1, *cp2; + struct hostent *h1; + int i1, i2; + (void)gethostbyname_r(cp1,h1,cp2,i1,&i2); + ], [ + AC_DEFINE(HAVE_GETHOSTBYNAME_R) + AC_DEFINE(HAVE_GETHOSTBYNAME_R_5_ARG, 1, + [Define this if gethostbyname_r takes 5 arguments]) + AC_MSG_RESULT(5) + ], [ + AC_TRY_COMPILE([ +#include + ], [ + char *cp1; + struct hostent *h1; + struct hostent_data hd; + (void) gethostbyname_r(cp1,h1,&hd); + ], [ + AC_DEFINE(HAVE_GETHOSTBYNAME_R) + AC_DEFINE(HAVE_GETHOSTBYNAME_R_3_ARG, 1, + [Define this if gethostbyname_r takes 3 arguments]) + AC_MSG_RESULT(3) + ], [ + AC_MSG_RESULT(0) + ]) + ]) + ]) + CFLAGS=$OLD_CFLAGS +]) + +fi + +AC_CHECK_SIZEOF(long) + +AC_MSG_CHECKING(for F_SETFD in fcntl.h) +AC_EGREP_CPP(yes, +[ +#define _GNU_SOURCE +#include +#ifdef F_SETFD +yes +#endif +], [ AC_DEFINE(HAVE_SETFD, 1, + [Define if F_SETFD is defined in ]) + AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no)) + +needsignal=no +haveselect=no +if test x$bwin32 != xtrue; then + AC_CHECK_FUNCS(select, [haveselect=yes], ) + if test "x$haveselect" = "xyes" ; then + needsignal=yes + fi +fi +AM_CONDITIONAL(SELECT_BACKEND, [test "x$haveselect" = "xyes"]) + +havepoll=no +AC_CHECK_FUNCS(poll, [havepoll=yes], ) +if test "x$havepoll" = "xyes" ; then + needsignal=yes +fi +AM_CONDITIONAL(POLL_BACKEND, [test "x$havepoll" = "xyes"]) + +havedevpoll=no +if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then + AC_DEFINE(HAVE_DEVPOLL, 1, + [Define if /dev/poll is available]) +fi +AM_CONDITIONAL(DEVPOLL_BACKEND, [test "x$ac_cv_header_sys_devpoll_h" = "xyes"]) + +havekqueue=no +if test "x$ac_cv_header_sys_event_h" = "xyes"; then + AC_CHECK_FUNCS(kqueue, [havekqueue=yes], ) + if test "x$havekqueue" = "xyes" ; then + AC_MSG_CHECKING(for working kqueue) + AC_TRY_RUN( +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int kq; + int n; + int fd[[2]]; + struct kevent ev; + struct timespec ts; + char buf[[8000]]; + + if (pipe(fd) == -1) + exit(1); + if (fcntl(fd[[1]], F_SETFL, O_NONBLOCK) == -1) + exit(1); + + while ((n = write(fd[[1]], buf, sizeof(buf))) == sizeof(buf)) + ; + + if ((kq = kqueue()) == -1) + exit(1); + + memset(&ev, 0, sizeof(ev)); + ev.ident = fd[[1]]; + ev.filter = EVFILT_WRITE; + ev.flags = EV_ADD | EV_ENABLE; + n = kevent(kq, &ev, 1, NULL, 0, NULL); + if (n == -1) + exit(1); + + read(fd[[0]], buf, sizeof(buf)); + + ts.tv_sec = 0; + ts.tv_nsec = 0; + n = kevent(kq, NULL, 0, &ev, 1, &ts); + if (n == -1 || n == 0) + exit(1); + + exit(0); +}, [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_WORKING_KQUEUE, 1, + [Define if kqueue works correctly with pipes]) + havekqueue=yes + ], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) + fi +fi +AM_CONDITIONAL(KQUEUE_BACKEND, [test "x$havekqueue" = "xyes"]) + +haveepollsyscall=no +haveepoll=no +AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], ) +if test "x$haveepoll" = "xyes" ; then + AC_DEFINE(HAVE_EPOLL, 1, + [Define if your system supports the epoll system calls]) + needsignal=yes +fi +if test "x$ac_cv_header_sys_epoll_h" = "xyes"; then + if test "x$haveepoll" = "xno" ; then + AC_MSG_CHECKING(for epoll system call) + AC_TRY_RUN( +#include +#include +#include +#include +#include +#include + +int +epoll_create(int size) +{ + return (syscall(__NR_epoll_create, size)); +} + +int +main(int argc, char **argv) +{ + int epfd; + + epfd = epoll_create(256); + exit (epfd == -1 ? 1 : 0); +}, [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_EPOLL, 1, + [Define if your system supports the epoll system calls]) + needsignal=yes + have_epoll=yes + AC_LIBOBJ(epoll_sub) + ], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) + fi +fi +AM_CONDITIONAL(EPOLL_BACKEND, [test "x$haveepoll" = "xyes"]) + +haveeventports=no +AC_CHECK_FUNCS(port_create, [haveeventports=yes], ) +if test "x$haveeventports" = "xyes" ; then + AC_DEFINE(HAVE_EVENT_PORTS, 1, + [Define if your system supports event ports]) + needsignal=yes +fi +AM_CONDITIONAL(EVPORT_BACKEND, [test "x$haveeventports" = "xyes"]) + +if test "x$bwin32" = "xtrue"; then + needsignal=yes +fi + +AM_CONDITIONAL(SIGNAL_SUPPORT, [test "x$needsignal" = "xyes"]) + +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + +AC_CHECK_TYPES([uint64_t, uint32_t, uint16_t, uint8_t, uintptr_t], , , +[#ifdef HAVE_STDINT_H +#include +#elif defined(HAVE_INTTYPES_H) +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif]) + +AC_CHECK_TYPES([fd_mask], , , +[#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif]) + +AC_CHECK_SIZEOF(long long) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(size_t) +AC_CHECK_SIZEOF(void *) + +AC_CHECK_TYPES([struct in6_addr, struct sockaddr_in6, sa_family_t, struct addrinfo, struct sockaddr_storage], , , +[#define _GNU_SOURCE +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif +]) +AC_CHECK_MEMBERS([struct in6_addr.s6_addr32, struct in6_addr.s6_addr16, struct sockaddr_in.sin_len, struct sockaddr_in6.sin6_len, struct sockaddr_storage.ss_family, struct sockaddr_storage.__ss_family], , , +[#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#include +#else +#include +#include +#endif +#endif +]) + +AC_MSG_CHECKING([for socklen_t]) +AC_TRY_COMPILE([ + #include + #include ], + [socklen_t x;], + AC_MSG_RESULT([yes]), + [AC_MSG_RESULT([no]) + AC_DEFINE(socklen_t, unsigned int, + [Define to unsigned int if you dont have it])] +) + +AC_MSG_CHECKING([whether our compiler supports __func__]) +AC_TRY_COMPILE([], + [ const char *cp = __func__; ], + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no]) + AC_MSG_CHECKING([whether our compiler supports __FUNCTION__]) + AC_TRY_COMPILE([], + [ const char *cp = __FUNCTION__; ], + AC_MSG_RESULT([yes]) + AC_DEFINE(__func__, __FUNCTION__, + [Define to appropriate substitue if compiler doesnt have __func__]), + AC_MSG_RESULT([no]) + AC_DEFINE(__func__, __FILE__, + [Define to appropriate substitue if compiler doesnt have __func__]))) + + +# check if we can compile with pthreads +have_pthreads=no +if test x$bwin32 != xtrue && test "$enable_thread_support" != "no"; then + ACX_PTHREAD([ + AC_DEFINE(HAVE_PTHREADS, 1, + [Define if we have pthreads on this system]) + have_pthreads=yes]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + AC_CHECK_SIZEOF(pthread_t, , + [AC_INCLUDES_DEFAULT() + #include ] + ) +fi +AM_CONDITIONAL(PTHREADS, [test "$have_pthreads" != "no" && test "$enable_thread_support" != "no"]) + +# check if we should compile locking into the library +if test x$enable_thread_support = xno; then + AC_DEFINE(DISABLE_THREAD_SUPPORT, 1, + [Define if libevent should not be compiled with thread support]) +fi + +# check if we should hard-code the mm functions. +if test x$enable_malloc_replacement = xno; then + AC_DEFINE(DISABLE_MM_REPLACEMENT, 1, + [Define if libevent should not allow replacing the mm functions]) +fi + +# check if we should hard-code debugging out +if test x$enable_debug_mode = xno; then + AC_DEFINE(DISABLE_DEBUG_MODE, 1, + [Define if libevent should build without support for a debug mode]) +fi + +# check if we have and should use openssl +AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"]) + +# Add some more warnings which we use in development but not in the +# released versions. (Some relevant gcc versions can't handle these.) +if test x$enable_gcc_warnings = xyes && test "$GCC" = "yes"; then + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ +#if !defined(__GNUC__) || (__GNUC__ < 4) +#error +#endif])], have_gcc4=yes, have_gcc4=no) + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ +#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) +#error +#endif])], have_gcc42=yes, have_gcc42=no) + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ +#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) +#error +#endif])], have_gcc45=yes, have_gcc45=no) + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ +#if !defined(__clang__) +#error +#endif])], have_clang=yes, have_clang=no) + + CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror" + CFLAGS="$CFLAGS -Wno-unused-parameter -Wstrict-aliasing" + + if test x$have_gcc4 = xyes ; then + # These warnings break gcc 3.3.5 and work on gcc 4.0.2 + CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement" + #CFLAGS="$CFLAGS -Wold-style-definition" + fi + + if test x$have_gcc42 = xyes ; then + # These warnings break gcc 4.0.2 and work on gcc 4.2 + CFLAGS="$CFLAGS -Waddress" + fi + + if test x$have_gcc42 = xyes && test x$have_clang = xno; then + # These warnings break gcc 4.0.2 and clang, but work on gcc 4.2 + CFLAGS="$CFLAGS -Wnormalized=id -Woverride-init" + fi + + if test x$have_gcc45 = xyes ; then + # These warnings work on gcc 4.5 + CFLAGS="$CFLAGS -Wlogical-op" + fi + + if test x$have_clang = xyes; then + # Disable the unused-function warnings, because these trigger + # for minheap-internal.h related code. + CFLAGS="$CFLAGS -Wno-unused-function" + fi + +##This will break the world on some 64-bit architectures +# CFLAGS="$CFLAGS -Winline" + +fi + +LIBEVENT_GC_SECTIONS= +if test "$GCC" = yes && test "$enable_function_sections" = yes ; then + AC_CACHE_CHECK( + [if linker supports omitting unused code and data], + [libevent_cv_gc_sections_runs], + [ + dnl NetBSD will link but likely not run with --gc-sections + dnl http://bugs.ntp.org/1844 + dnl http://gnats.netbsd.org/40401 + dnl --gc-sections causes attempt to load as linux elf, with + dnl wrong syscalls in place. Test a little gauntlet of + dnl simple stdio read code checking for errors, expecting + dnl enough syscall differences that the NetBSD code will + dnl fail even with Linux emulation working as designed. + dnl A shorter test could be refined by someone with access + dnl to a NetBSD host with Linux emulation working. + origCFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wl,--gc-sections" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ + #include + #include + ]], + [[ + FILE * fpC; + char buf[32]; + size_t cch; + int read_success_once; + + fpC = fopen("conftest.c", "r"); + if (NULL == fpC) + exit(1); + do { + cch = fread(buf, sizeof(buf), 1, fpC); + read_success_once |= (0 != cch); + } while (0 != cch); + if (!read_success_once) + exit(2); + if (!feof(fpC)) + exit(3); + if (0 != fclose(fpC)) + exit(4); + + exit(EXIT_SUCCESS); + ]] + )], + [ + dnl We have to do this invocation manually so that we can + dnl get the output of conftest.err to make sure it doesn't + dnl mention gc-sections. + if test "X$cross_compiling" = "Xyes" || grep gc-sections conftest.err ; then + libevent_cv_gc_sections_runs=no + else + libevent_cv_gc_sections_runs=no + ./conftest >/dev/null 2>&1 && libevent_cv_gc_sections_runs=yes + fi + ], + [libevent_cv_gc_sections_runs=no] + ) + CFLAGS="$origCFLAGS" + AS_UNSET([origCFLAGS]) + ] + ) + case "$libevent_cv_gc_sections_runs" in + yes) + CFLAGS="-ffunction-sections -fdata-sections $CFLAGS" + LIBEVENT_GC_SECTIONS="-Wl,--gc-sections" + ;; + esac +fi +AC_SUBST([LIBEVENT_GC_SECTIONS]) + +AM_CONDITIONAL([INSTALL_LIBEVENT], [test "$enable_libevent_install" = "yes"]) + +AC_CONFIG_FILES( [libevent.pc libevent_openssl.pc libevent_pthreads.pc] ) +AC_OUTPUT(Makefile include/Makefile test/Makefile sample/Makefile) diff --git a/libevent/defer-internal.h b/libevent/defer-internal.h new file mode 100644 index 0000000..96a5cac --- /dev/null +++ b/libevent/defer-internal.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _DEFER_INTERNAL_H_ +#define _DEFER_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event2/event-config.h" +#include + +struct deferred_cb; + +typedef void (*deferred_cb_fn)(struct deferred_cb *, void *); + +/** A deferred_cb is a callback that can be scheduled to run as part of + * an event_base's event_loop, rather than running immediately. */ +struct deferred_cb { + /** Links to the adjacent active (pending) deferred_cb objects. */ + TAILQ_ENTRY (deferred_cb) cb_next; + /** True iff this deferred_cb is pending in an event_base. */ + unsigned queued : 1; + /** The function to execute when the callback runs. */ + deferred_cb_fn cb; + /** The function's second argument. */ + void *arg; +}; + +/** A deferred_cb_queue is a list of deferred_cb that we can add to and run. */ +struct deferred_cb_queue { + /** Lock used to protect the queue. */ + void *lock; + + /** How many entries are in the queue? */ + int active_count; + + /** Function called when adding to the queue from another thread. */ + void (*notify_fn)(struct deferred_cb_queue *, void *); + void *notify_arg; + + /** Deferred callback management: a list of deferred callbacks to + * run active the active events. */ + TAILQ_HEAD (deferred_cb_list, deferred_cb) deferred_cb_list; +}; + +/** + Initialize an empty, non-pending deferred_cb. + + @param deferred The deferred_cb structure to initialize. + @param cb The function to run when the deferred_cb executes. + @param arg The function's second argument. + */ +void event_deferred_cb_init(struct deferred_cb *, deferred_cb_fn, void *); +/** + Cancel a deferred_cb if it is currently scheduled in an event_base. + */ +void event_deferred_cb_cancel(struct deferred_cb_queue *, struct deferred_cb *); +/** + Activate a deferred_cb if it is not currently scheduled in an event_base. + */ +void event_deferred_cb_schedule(struct deferred_cb_queue *, struct deferred_cb *); + +#define LOCK_DEFERRED_QUEUE(q) \ + EVLOCK_LOCK((q)->lock, 0) +#define UNLOCK_DEFERRED_QUEUE(q) \ + EVLOCK_UNLOCK((q)->lock, 0) + +#ifdef __cplusplus +} +#endif + +void event_deferred_cb_queue_init(struct deferred_cb_queue *); +struct deferred_cb_queue *event_base_get_deferred_cb_queue(struct event_base *); + +#endif /* _EVENT_INTERNAL_H_ */ + diff --git a/libevent/devpoll.c b/libevent/devpoll.c new file mode 100644 index 0000000..f99cc01 --- /dev/null +++ b/libevent/devpoll.c @@ -0,0 +1,306 @@ +/* + * Copyright 2000-2009 Niels Provos + * Copyright 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/thread.h" +#include "event-internal.h" +#include "evsignal-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "evthread-internal.h" + +struct devpollop { + struct pollfd *events; + int nevents; + int dpfd; + struct pollfd *changes; + int nchanges; +}; + +static void *devpoll_init(struct event_base *); +static int devpoll_add(struct event_base *, int fd, short old, short events, void *); +static int devpoll_del(struct event_base *, int fd, short old, short events, void *); +static int devpoll_dispatch(struct event_base *, struct timeval *); +static void devpoll_dealloc(struct event_base *); + +const struct eventop devpollops = { + "devpoll", + devpoll_init, + devpoll_add, + devpoll_del, + devpoll_dispatch, + devpoll_dealloc, + 1, /* need reinit */ + EV_FEATURE_FDS|EV_FEATURE_O1, + 0 +}; + +#define NEVENT 32000 + +static int +devpoll_commit(struct devpollop *devpollop) +{ + /* + * Due to a bug in Solaris, we have to use pwrite with an offset of 0. + * Write is limited to 2GB of data, until it will fail. + */ + if (pwrite(devpollop->dpfd, devpollop->changes, + sizeof(struct pollfd) * devpollop->nchanges, 0) == -1) + return (-1); + + devpollop->nchanges = 0; + return (0); +} + +static int +devpoll_queue(struct devpollop *devpollop, int fd, int events) { + struct pollfd *pfd; + + if (devpollop->nchanges >= devpollop->nevents) { + /* + * Change buffer is full, must commit it to /dev/poll before + * adding more + */ + if (devpoll_commit(devpollop) != 0) + return (-1); + } + + pfd = &devpollop->changes[devpollop->nchanges++]; + pfd->fd = fd; + pfd->events = events; + pfd->revents = 0; + + return (0); +} + +static void * +devpoll_init(struct event_base *base) +{ + int dpfd, nfiles = NEVENT; + struct rlimit rl; + struct devpollop *devpollop; + + if (!(devpollop = mm_calloc(1, sizeof(struct devpollop)))) + return (NULL); + + if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && + rl.rlim_cur != RLIM_INFINITY) + nfiles = rl.rlim_cur; + + /* Initialize the kernel queue */ + if ((dpfd = evutil_open_closeonexec("/dev/poll", O_RDWR, 0)) == -1) { + event_warn("open: /dev/poll"); + mm_free(devpollop); + return (NULL); + } + + devpollop->dpfd = dpfd; + + /* Initialize fields */ + /* FIXME: allocating 'nfiles' worth of space here can be + * expensive and unnecessary. See how epoll.c does it instead. */ + devpollop->events = mm_calloc(nfiles, sizeof(struct pollfd)); + if (devpollop->events == NULL) { + mm_free(devpollop); + close(dpfd); + return (NULL); + } + devpollop->nevents = nfiles; + + devpollop->changes = mm_calloc(nfiles, sizeof(struct pollfd)); + if (devpollop->changes == NULL) { + mm_free(devpollop->events); + mm_free(devpollop); + close(dpfd); + return (NULL); + } + + evsig_init(base); + + return (devpollop); +} + +static int +devpoll_dispatch(struct event_base *base, struct timeval *tv) +{ + struct devpollop *devpollop = base->evbase; + struct pollfd *events = devpollop->events; + struct dvpoll dvp; + int i, res, timeout = -1; + + if (devpollop->nchanges) + devpoll_commit(devpollop); + + if (tv != NULL) + timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; + + dvp.dp_fds = devpollop->events; + dvp.dp_nfds = devpollop->nevents; + dvp.dp_timeout = timeout; + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = ioctl(devpollop->dpfd, DP_POLL, &dvp); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + if (res == -1) { + if (errno != EINTR) { + event_warn("ioctl: DP_POLL"); + return (-1); + } + + return (0); + } + + event_debug(("%s: devpoll_wait reports %d", __func__, res)); + + for (i = 0; i < res; i++) { + int which = 0; + int what = events[i].revents; + + if (what & POLLHUP) + what |= POLLIN | POLLOUT; + else if (what & POLLERR) + what |= POLLIN | POLLOUT; + + if (what & POLLIN) + which |= EV_READ; + if (what & POLLOUT) + which |= EV_WRITE; + + if (!which) + continue; + + /* XXX(niels): not sure if this works for devpoll */ + evmap_io_active(base, events[i].fd, which); + } + + return (0); +} + + +static int +devpoll_add(struct event_base *base, int fd, short old, short events, void *p) +{ + struct devpollop *devpollop = base->evbase; + int res; + (void)p; + + /* + * It's not necessary to OR the existing read/write events that we + * are currently interested in with the new event we are adding. + * The /dev/poll driver ORs any new events with the existing events + * that it has cached for the fd. + */ + + res = 0; + if (events & EV_READ) + res |= POLLIN; + if (events & EV_WRITE) + res |= POLLOUT; + + if (devpoll_queue(devpollop, fd, res) != 0) + return (-1); + + return (0); +} + +static int +devpoll_del(struct event_base *base, int fd, short old, short events, void *p) +{ + struct devpollop *devpollop = base->evbase; + int res; + (void)p; + + res = 0; + if (events & EV_READ) + res |= POLLIN; + if (events & EV_WRITE) + res |= POLLOUT; + + /* + * The only way to remove an fd from the /dev/poll monitored set is + * to use POLLREMOVE by itself. This removes ALL events for the fd + * provided so if we care about two events and are only removing one + * we must re-add the other event after POLLREMOVE. + */ + + if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0) + return (-1); + + if ((res & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) { + /* + * We're not deleting all events, so we must resubmit the + * event that we are still interested in if one exists. + */ + + if ((res & POLLIN) && (old & EV_WRITE)) { + /* Deleting read, still care about write */ + devpoll_queue(devpollop, fd, POLLOUT); + } else if ((res & POLLOUT) && (old & EV_READ)) { + /* Deleting write, still care about read */ + devpoll_queue(devpollop, fd, POLLIN); + } + } + + return (0); +} + +static void +devpoll_dealloc(struct event_base *base) +{ + struct devpollop *devpollop = base->evbase; + + evsig_dealloc(base); + if (devpollop->events) + mm_free(devpollop->events); + if (devpollop->changes) + mm_free(devpollop->changes); + if (devpollop->dpfd >= 0) + close(devpollop->dpfd); + + memset(devpollop, 0, sizeof(struct devpollop)); + mm_free(devpollop); +} diff --git a/libevent/epoll.c b/libevent/epoll.c new file mode 100644 index 0000000..4c5c3da --- /dev/null +++ b/libevent/epoll.c @@ -0,0 +1,473 @@ +/* + * Copyright 2000-2007 Niels Provos + * Copyright 2007-2012 Niels Provos, Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#include +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _EVENT_HAVE_FCNTL_H +#include +#endif + +#include "event-internal.h" +#include "evsignal-internal.h" +#include "event2/thread.h" +#include "evthread-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "changelist-internal.h" + +struct epollop { + struct epoll_event *events; + int nevents; + int epfd; +}; + +static void *epoll_init(struct event_base *); +static int epoll_dispatch(struct event_base *, struct timeval *); +static void epoll_dealloc(struct event_base *); + +static const struct eventop epollops_changelist = { + "epoll (with changelist)", + epoll_init, + event_changelist_add, + event_changelist_del, + epoll_dispatch, + epoll_dealloc, + 1, /* need reinit */ + EV_FEATURE_ET|EV_FEATURE_O1, + EVENT_CHANGELIST_FDINFO_SIZE +}; + + +static int epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p); +static int epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p); + +const struct eventop epollops = { + "epoll", + epoll_init, + epoll_nochangelist_add, + epoll_nochangelist_del, + epoll_dispatch, + epoll_dealloc, + 1, /* need reinit */ + EV_FEATURE_ET|EV_FEATURE_O1, + 0 +}; + +#define INITIAL_NEVENT 32 +#define MAX_NEVENT 4096 + +/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout + * values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be + * as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the + * largest number of msec we can support here is 2147482. Let's + * round that down by 47 seconds. + */ +#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000) + +static void * +epoll_init(struct event_base *base) +{ + int epfd; + struct epollop *epollop; + + /* Initialize the kernel queue. (The size field is ignored since + * 2.6.8.) */ + if ((epfd = epoll_create(32000)) == -1) { + if (errno != ENOSYS) + event_warn("epoll_create"); + return (NULL); + } + + evutil_make_socket_closeonexec(epfd); + + if (!(epollop = mm_calloc(1, sizeof(struct epollop)))) { + close(epfd); + return (NULL); + } + + epollop->epfd = epfd; + + /* Initialize fields */ + epollop->events = mm_calloc(INITIAL_NEVENT, sizeof(struct epoll_event)); + if (epollop->events == NULL) { + mm_free(epollop); + close(epfd); + return (NULL); + } + epollop->nevents = INITIAL_NEVENT; + + if ((base->flags & EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) != 0 || + ((base->flags & EVENT_BASE_FLAG_IGNORE_ENV) == 0 && + evutil_getenv("EVENT_EPOLL_USE_CHANGELIST") != NULL)) + base->evsel = &epollops_changelist; + + evsig_init(base); + + return (epollop); +} + +static const char * +change_to_string(int change) +{ + change &= (EV_CHANGE_ADD|EV_CHANGE_DEL); + if (change == EV_CHANGE_ADD) { + return "add"; + } else if (change == EV_CHANGE_DEL) { + return "del"; + } else if (change == 0) { + return "none"; + } else { + return "???"; + } +} + +static const char * +epoll_op_to_string(int op) +{ + return op == EPOLL_CTL_ADD?"ADD": + op == EPOLL_CTL_DEL?"DEL": + op == EPOLL_CTL_MOD?"MOD": + "???"; +} + +static int +epoll_apply_one_change(struct event_base *base, + struct epollop *epollop, + const struct event_change *ch) +{ + struct epoll_event epev; + int op, events = 0; + + if (1) { + /* The logic here is a little tricky. If we had no events set + on the fd before, we need to set op="ADD" and set + events=the events we want to add. If we had any events set + on the fd before, and we want any events to remain on the + fd, we need to say op="MOD" and set events=the events we + want to remain. But if we want to delete the last event, + we say op="DEL" and set events=the remaining events. What + fun! + */ + + /* TODO: Turn this into a switch or a table lookup. */ + + if ((ch->read_change & EV_CHANGE_ADD) || + (ch->write_change & EV_CHANGE_ADD)) { + /* If we are adding anything at all, we'll want to do + * either an ADD or a MOD. */ + events = 0; + op = EPOLL_CTL_ADD; + if (ch->read_change & EV_CHANGE_ADD) { + events |= EPOLLIN; + } else if (ch->read_change & EV_CHANGE_DEL) { + ; + } else if (ch->old_events & EV_READ) { + events |= EPOLLIN; + } + if (ch->write_change & EV_CHANGE_ADD) { + events |= EPOLLOUT; + } else if (ch->write_change & EV_CHANGE_DEL) { + ; + } else if (ch->old_events & EV_WRITE) { + events |= EPOLLOUT; + } + if ((ch->read_change|ch->write_change) & EV_ET) + events |= EPOLLET; + + if (ch->old_events) { + /* If MOD fails, we retry as an ADD, and if + * ADD fails we will retry as a MOD. So the + * only hard part here is to guess which one + * will work. As a heuristic, we'll try + * MOD first if we think there were old + * events and ADD if we think there were none. + * + * We can be wrong about the MOD if the file + * has in fact been closed and re-opened. + * + * We can be wrong about the ADD if the + * the fd has been re-created with a dup() + * of the same file that it was before. + */ + op = EPOLL_CTL_MOD; + } + } else if ((ch->read_change & EV_CHANGE_DEL) || + (ch->write_change & EV_CHANGE_DEL)) { + /* If we're deleting anything, we'll want to do a MOD + * or a DEL. */ + op = EPOLL_CTL_DEL; + + if (ch->read_change & EV_CHANGE_DEL) { + if (ch->write_change & EV_CHANGE_DEL) { + events = EPOLLIN|EPOLLOUT; + } else if (ch->old_events & EV_WRITE) { + events = EPOLLOUT; + op = EPOLL_CTL_MOD; + } else { + events = EPOLLIN; + } + } else if (ch->write_change & EV_CHANGE_DEL) { + if (ch->old_events & EV_READ) { + events = EPOLLIN; + op = EPOLL_CTL_MOD; + } else { + events = EPOLLOUT; + } + } + } + + if (!events) + return 0; + + memset(&epev, 0, sizeof(epev)); + epev.data.fd = ch->fd; + epev.events = events; + if (epoll_ctl(epollop->epfd, op, ch->fd, &epev) == -1) { + if (op == EPOLL_CTL_MOD && errno == ENOENT) { + /* If a MOD operation fails with ENOENT, the + * fd was probably closed and re-opened. We + * should retry the operation as an ADD. + */ + if (epoll_ctl(epollop->epfd, EPOLL_CTL_ADD, ch->fd, &epev) == -1) { + event_warn("Epoll MOD(%d) on %d retried as ADD; that failed too", + (int)epev.events, ch->fd); + return -1; + } else { + event_debug(("Epoll MOD(%d) on %d retried as ADD; succeeded.", + (int)epev.events, + ch->fd)); + } + } else if (op == EPOLL_CTL_ADD && errno == EEXIST) { + /* If an ADD operation fails with EEXIST, + * either the operation was redundant (as with a + * precautionary add), or we ran into a fun + * kernel bug where using dup*() to duplicate the + * same file into the same fd gives you the same epitem + * rather than a fresh one. For the second case, + * we must retry with MOD. */ + if (epoll_ctl(epollop->epfd, EPOLL_CTL_MOD, ch->fd, &epev) == -1) { + event_warn("Epoll ADD(%d) on %d retried as MOD; that failed too", + (int)epev.events, ch->fd); + return -1; + } else { + event_debug(("Epoll ADD(%d) on %d retried as MOD; succeeded.", + (int)epev.events, + ch->fd)); + } + } else if (op == EPOLL_CTL_DEL && + (errno == ENOENT || errno == EBADF || + errno == EPERM)) { + /* If a delete fails with one of these errors, + * that's fine too: we closed the fd before we + * got around to calling epoll_dispatch. */ + event_debug(("Epoll DEL(%d) on fd %d gave %s: DEL was unnecessary.", + (int)epev.events, + ch->fd, + strerror(errno))); + } else { + event_warn("Epoll %s(%d) on fd %d failed. Old events were %d; read change was %d (%s); write change was %d (%s)", + epoll_op_to_string(op), + (int)epev.events, + ch->fd, + ch->old_events, + ch->read_change, + change_to_string(ch->read_change), + ch->write_change, + change_to_string(ch->write_change)); + return -1; + } + } else { + event_debug(("Epoll %s(%d) on fd %d okay. [old events were %d; read change was %d; write change was %d]", + epoll_op_to_string(op), + (int)epev.events, + (int)ch->fd, + ch->old_events, + ch->read_change, + ch->write_change)); + } + } + return 0; +} + +static int +epoll_apply_changes(struct event_base *base) +{ + struct event_changelist *changelist = &base->changelist; + struct epollop *epollop = base->evbase; + struct event_change *ch; + + int r = 0; + int i; + + for (i = 0; i < changelist->n_changes; ++i) { + ch = &changelist->changes[i]; + if (epoll_apply_one_change(base, epollop, ch) < 0) + r = -1; + } + + return (r); +} + +static int +epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p) +{ + struct event_change ch; + ch.fd = fd; + ch.old_events = old; + ch.read_change = ch.write_change = 0; + if (events & EV_WRITE) + ch.write_change = EV_CHANGE_ADD | + (events & EV_ET); + if (events & EV_READ) + ch.read_change = EV_CHANGE_ADD | + (events & EV_ET); + + return epoll_apply_one_change(base, base->evbase, &ch); +} + +static int +epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd, + short old, short events, void *p) +{ + struct event_change ch; + ch.fd = fd; + ch.old_events = old; + ch.read_change = ch.write_change = 0; + if (events & EV_WRITE) + ch.write_change = EV_CHANGE_DEL; + if (events & EV_READ) + ch.read_change = EV_CHANGE_DEL; + + return epoll_apply_one_change(base, base->evbase, &ch); +} + +static int +epoll_dispatch(struct event_base *base, struct timeval *tv) +{ + struct epollop *epollop = base->evbase; + struct epoll_event *events = epollop->events; + int i, res; + long timeout = -1; + + if (tv != NULL) { + timeout = evutil_tv_to_msec(tv); + if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) { + /* Linux kernels can wait forever if the timeout is + * too big; see comment on MAX_EPOLL_TIMEOUT_MSEC. */ + timeout = MAX_EPOLL_TIMEOUT_MSEC; + } + } + + epoll_apply_changes(base); + event_changelist_remove_all(&base->changelist, base); + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + if (res == -1) { + if (errno != EINTR) { + event_warn("epoll_wait"); + return (-1); + } + + return (0); + } + + event_debug(("%s: epoll_wait reports %d", __func__, res)); + EVUTIL_ASSERT(res <= epollop->nevents); + + for (i = 0; i < res; i++) { + int what = events[i].events; + short ev = 0; + + if (what & (EPOLLHUP|EPOLLERR)) { + ev = EV_READ | EV_WRITE; + } else { + if (what & EPOLLIN) + ev |= EV_READ; + if (what & EPOLLOUT) + ev |= EV_WRITE; + } + + if (!ev) + continue; + + evmap_io_active(base, events[i].data.fd, ev | EV_ET); + } + + if (res == epollop->nevents && epollop->nevents < MAX_NEVENT) { + /* We used all of the event space this time. We should + be ready for more events next time. */ + int new_nevents = epollop->nevents * 2; + struct epoll_event *new_events; + + new_events = mm_realloc(epollop->events, + new_nevents * sizeof(struct epoll_event)); + if (new_events) { + epollop->events = new_events; + epollop->nevents = new_nevents; + } + } + + return (0); +} + + +static void +epoll_dealloc(struct event_base *base) +{ + struct epollop *epollop = base->evbase; + + evsig_dealloc(base); + if (epollop->events) + mm_free(epollop->events); + if (epollop->epfd >= 0) + close(epollop->epfd); + + memset(epollop, 0, sizeof(struct epollop)); + mm_free(epollop); +} diff --git a/libevent/epoll_sub.c b/libevent/epoll_sub.c new file mode 100644 index 0000000..3738b26 --- /dev/null +++ b/libevent/epoll_sub.c @@ -0,0 +1,52 @@ +/* + * Copyright 2003-2009 Niels Provos + * Copyright 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include + +#include +#include +#include +#include +#include + +int +epoll_create(int size) +{ + return (syscall(__NR_epoll_create, size)); +} + +int +epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) +{ + + return (syscall(__NR_epoll_ctl, epfd, op, fd, event)); +} + +int +epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout)); +} diff --git a/libevent/evbuffer-internal.h b/libevent/evbuffer-internal.h new file mode 100644 index 0000000..e68a59d --- /dev/null +++ b/libevent/evbuffer-internal.h @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVBUFFER_INTERNAL_H_ +#define _EVBUFFER_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event2/event-config.h" +#include "event2/util.h" +#include "util-internal.h" +#include "defer-internal.h" + +/* Experimental cb flag: "never deferred." Implementation note: + * these callbacks may get an inaccurate view of n_del/n_added in their + * arguments. */ +#define EVBUFFER_CB_NODEFER 2 + +#ifdef WIN32 +#include +#endif +#include + +/* Minimum allocation for a chain. We define this so that we're burning no + * more than 5% of each allocation on overhead. It would be nice to lose even + * less space, though. */ +#if _EVENT_SIZEOF_VOID_P < 8 +#define MIN_BUFFER_SIZE 512 +#else +#define MIN_BUFFER_SIZE 1024 +#endif + +/** A single evbuffer callback for an evbuffer. This function will be invoked + * when bytes are added to or removed from the evbuffer. */ +struct evbuffer_cb_entry { + /** Structures to implement a doubly-linked queue of callbacks */ + TAILQ_ENTRY(evbuffer_cb_entry) next; + /** The callback function to invoke when this callback is called. + If EVBUFFER_CB_OBSOLETE is set in flags, the cb_obsolete field is + valid; otherwise, cb_func is valid. */ + union { + evbuffer_cb_func cb_func; + evbuffer_cb cb_obsolete; + } cb; + /** Argument to pass to cb. */ + void *cbarg; + /** Currently set flags on this callback. */ + ev_uint32_t flags; +}; + +struct bufferevent; +struct evbuffer_chain; +struct evbuffer { + /** The first chain in this buffer's linked list of chains. */ + struct evbuffer_chain *first; + /** The last chain in this buffer's linked list of chains. */ + struct evbuffer_chain *last; + + /** Pointer to the next pointer pointing at the 'last_with_data' chain. + * + * To unpack: + * + * The last_with_data chain is the last chain that has any data in it. + * If all chains in the buffer are empty, it is the first chain. + * If the buffer has no chains, it is NULL. + * + * The last_with_datap pointer points at _whatever 'next' pointer_ + * points at the last_with_datap chain. If the last_with_data chain + * is the first chain, or it is NULL, then the last_with_datap pointer + * is &buf->first. + */ + struct evbuffer_chain **last_with_datap; + + /** Total amount of bytes stored in all chains.*/ + size_t total_len; + + /** Number of bytes we have added to the buffer since we last tried to + * invoke callbacks. */ + size_t n_add_for_cb; + /** Number of bytes we have removed from the buffer since we last + * tried to invoke callbacks. */ + size_t n_del_for_cb; + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + /** A lock used to mediate access to this buffer. */ + void *lock; +#endif + /** True iff we should free the lock field when we free this + * evbuffer. */ + unsigned own_lock : 1; + /** True iff we should not allow changes to the front of the buffer + * (drains or prepends). */ + unsigned freeze_start : 1; + /** True iff we should not allow changes to the end of the buffer + * (appends) */ + unsigned freeze_end : 1; + /** True iff this evbuffer's callbacks are not invoked immediately + * upon a change in the buffer, but instead are deferred to be invoked + * from the event_base's loop. Useful for preventing enormous stack + * overflows when we have mutually recursive callbacks, and for + * serializing callbacks in a single thread. */ + unsigned deferred_cbs : 1; +#ifdef WIN32 + /** True iff this buffer is set up for overlapped IO. */ + unsigned is_overlapped : 1; +#endif + /** Zero or more EVBUFFER_FLAG_* bits */ + ev_uint32_t flags; + + /** Used to implement deferred callbacks. */ + struct deferred_cb_queue *cb_queue; + + /** A reference count on this evbuffer. When the reference count + * reaches 0, the buffer is destroyed. Manipulated with + * evbuffer_incref and evbuffer_decref_and_unlock and + * evbuffer_free. */ + int refcnt; + + /** A deferred_cb handle to make all of this buffer's callbacks + * invoked from the event loop. */ + struct deferred_cb deferred; + + /** A doubly-linked-list of callback functions */ + TAILQ_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks; + + /** The parent bufferevent object this evbuffer belongs to. + * NULL if the evbuffer stands alone. */ + struct bufferevent *parent; +}; + +/** A single item in an evbuffer. */ +struct evbuffer_chain { + /** points to next buffer in the chain */ + struct evbuffer_chain *next; + + /** total allocation available in the buffer field. */ + size_t buffer_len; + + /** unused space at the beginning of buffer or an offset into a + * file for sendfile buffers. */ + ev_off_t misalign; + + /** Offset into buffer + misalign at which to start writing. + * In other words, the total number of bytes actually stored + * in buffer. */ + size_t off; + + /** Set if special handling is required for this chain */ + unsigned flags; +#define EVBUFFER_MMAP 0x0001 /**< memory in buffer is mmaped */ +#define EVBUFFER_SENDFILE 0x0002 /**< a chain used for sendfile */ +#define EVBUFFER_REFERENCE 0x0004 /**< a chain with a mem reference */ +#define EVBUFFER_IMMUTABLE 0x0008 /**< read-only chain */ + /** a chain that mustn't be reallocated or freed, or have its contents + * memmoved, until the chain is un-pinned. */ +#define EVBUFFER_MEM_PINNED_R 0x0010 +#define EVBUFFER_MEM_PINNED_W 0x0020 +#define EVBUFFER_MEM_PINNED_ANY (EVBUFFER_MEM_PINNED_R|EVBUFFER_MEM_PINNED_W) + /** a chain that should be freed, but can't be freed until it is + * un-pinned. */ +#define EVBUFFER_DANGLING 0x0040 + + /** Usually points to the read-write memory belonging to this + * buffer allocated as part of the evbuffer_chain allocation. + * For mmap, this can be a read-only buffer and + * EVBUFFER_IMMUTABLE will be set in flags. For sendfile, it + * may point to NULL. + */ + unsigned char *buffer; +}; + +/* this is currently used by both mmap and sendfile */ +/* TODO(niels): something strange needs to happen for Windows here, I am not + * sure what that is, but it needs to get looked into. + */ +struct evbuffer_chain_fd { + int fd; /**< the fd associated with this chain */ +}; + +/** callback for a reference buffer; lets us know what to do with it when + * we're done with it. */ +struct evbuffer_chain_reference { + evbuffer_ref_cleanup_cb cleanupfn; + void *extra; +}; + +#define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain) +/** Return a pointer to extra data allocated along with an evbuffer. */ +#define EVBUFFER_CHAIN_EXTRA(t, c) (t *)((struct evbuffer_chain *)(c) + 1) + +/** Assert that we are holding the lock on an evbuffer */ +#define ASSERT_EVBUFFER_LOCKED(buffer) \ + EVLOCK_ASSERT_LOCKED((buffer)->lock) + +#define EVBUFFER_LOCK(buffer) \ + do { \ + EVLOCK_LOCK((buffer)->lock, 0); \ + } while (0) +#define EVBUFFER_UNLOCK(buffer) \ + do { \ + EVLOCK_UNLOCK((buffer)->lock, 0); \ + } while (0) +#define EVBUFFER_LOCK2(buffer1, buffer2) \ + do { \ + EVLOCK_LOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \ + } while (0) +#define EVBUFFER_UNLOCK2(buffer1, buffer2) \ + do { \ + EVLOCK_UNLOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \ + } while (0) + +/** Increase the reference count of buf by one. */ +void _evbuffer_incref(struct evbuffer *buf); +/** Increase the reference count of buf by one and acquire the lock. */ +void _evbuffer_incref_and_lock(struct evbuffer *buf); +/** Pin a single buffer chain using a given flag. A pinned chunk may not be + * moved or freed until it is unpinned. */ +void _evbuffer_chain_pin(struct evbuffer_chain *chain, unsigned flag); +/** Unpin a single buffer chain using a given flag. */ +void _evbuffer_chain_unpin(struct evbuffer_chain *chain, unsigned flag); +/** As evbuffer_free, but requires that we hold a lock on the buffer, and + * releases the lock before freeing it and the buffer. */ +void _evbuffer_decref_and_unlock(struct evbuffer *buffer); + +/** As evbuffer_expand, but does not guarantee that the newly allocated memory + * is contiguous. Instead, it may be split across two or more chunks. */ +int _evbuffer_expand_fast(struct evbuffer *, size_t, int); + +/** Helper: prepares for a readv/WSARecv call by expanding the buffer to + * hold enough memory to read 'howmuch' bytes in possibly noncontiguous memory. + * Sets up the one or two iovecs in 'vecs' to point to the free memory and its + * extent, and *chainp to point to the first chain that we'll try to read into. + * Returns the number of vecs used. + */ +int _evbuffer_read_setup_vecs(struct evbuffer *buf, ev_ssize_t howmuch, + struct evbuffer_iovec *vecs, int n_vecs, struct evbuffer_chain ***chainp, + int exact); + +/* Helper macro: copies an evbuffer_iovec in ei to a win32 WSABUF in i. */ +#define WSABUF_FROM_EVBUFFER_IOV(i,ei) do { \ + (i)->buf = (ei)->iov_base; \ + (i)->len = (unsigned long)(ei)->iov_len; \ + } while (0) +/* XXXX the cast above is safe for now, but not if we allow mmaps on win64. + * See note in buffer_iocp's launch_write function */ + +/** Set the parent bufferevent object for buf to bev */ +void evbuffer_set_parent(struct evbuffer *buf, struct bufferevent *bev); + +void evbuffer_invoke_callbacks(struct evbuffer *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVBUFFER_INTERNAL_H_ */ diff --git a/libevent/evdns.c b/libevent/evdns.c new file mode 100644 index 0000000..02f5dff --- /dev/null +++ b/libevent/evdns.c @@ -0,0 +1,4620 @@ +/* Copyright 2006-2007 Niels Provos + * Copyright 2007-2012 Nick Mathewson and Niels Provos + * + * 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. + */ + +/* Based on software by Adam Langly. Adam's original message: + * + * Async DNS Library + * Adam Langley + * http://www.imperialviolet.org/eventdns.html + * Public Domain code + * + * This software is Public Domain. To view a copy of the public domain dedication, + * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to + * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. + * + * I ask and expect, but do not require, that all derivative works contain an + * attribution similar to: + * Parts developed by Adam Langley + * + * You may wish to replace the word "Parts" with something else depending on + * the amount of original code. + * + * (Derivative works does not include programs which link against, run or include + * the source verbatim in their source distributions) + * + * Version: 0.1b + */ + +#include +#include "event2/event-config.h" + +#ifndef _FORTIFY_SOURCE +#define _FORTIFY_SOURCE 3 +#endif + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#ifdef _EVENT_HAVE_STDINT_H +#include +#endif +#include +#include +#include +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#ifdef WIN32 +#include +#include +#ifndef _WIN32_IE +#define _WIN32_IE 0x400 +#endif +#include +#endif + +#include "event2/dns.h" +#include "event2/dns_struct.h" +#include "event2/dns_compat.h" +#include "event2/util.h" +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/thread.h" + +#include "event2/bufferevent.h" +#include "event2/bufferevent_struct.h" +#include "bufferevent-internal.h" + +#include "defer-internal.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "strlcpy-internal.h" +#include "ipv6-internal.h" +#include "util-internal.h" +#include "evthread-internal.h" +#ifdef WIN32 +#include +#include +#include +#include +#include +#else +#include +#include +#include +#endif + +#ifdef _EVENT_HAVE_NETINET_IN6_H +#include +#endif + +#define EVDNS_LOG_DEBUG 0 +#define EVDNS_LOG_WARN 1 +#define EVDNS_LOG_MSG 2 + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +#include + +#undef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define ASSERT_VALID_REQUEST(req) \ + EVUTIL_ASSERT((req)->handle && (req)->handle->current_req == (req)) + +#define u64 ev_uint64_t +#define u32 ev_uint32_t +#define u16 ev_uint16_t +#define u8 ev_uint8_t + +/* maximum number of addresses from a single packet */ +/* that we bother recording */ +#define MAX_V4_ADDRS 32 +#define MAX_V6_ADDRS 32 + + +#define TYPE_A EVDNS_TYPE_A +#define TYPE_CNAME 5 +#define TYPE_PTR EVDNS_TYPE_PTR +#define TYPE_SOA EVDNS_TYPE_SOA +#define TYPE_AAAA EVDNS_TYPE_AAAA + +#define CLASS_INET EVDNS_CLASS_INET + +/* Persistent handle. We keep this separate from 'struct request' since we + * need some object to last for as long as an evdns_request is outstanding so + * that it can be canceled, whereas a search request can lead to multiple + * 'struct request' instances being created over its lifetime. */ +struct evdns_request { + struct request *current_req; + struct evdns_base *base; + + int pending_cb; /* Waiting for its callback to be invoked; not + * owned by event base any more. */ + + /* elements used by the searching code */ + int search_index; + struct search_state *search_state; + char *search_origname; /* needs to be free()ed */ + int search_flags; +}; + +struct request { + u8 *request; /* the dns packet data */ + u8 request_type; /* TYPE_PTR or TYPE_A or TYPE_AAAA */ + unsigned int request_len; + int reissue_count; + int tx_count; /* the number of times that this packet has been sent */ + void *user_pointer; /* the pointer given to us for this request */ + evdns_callback_type user_callback; + struct nameserver *ns; /* the server which we last sent it */ + + /* these objects are kept in a circular list */ + /* XXX We could turn this into a CIRCLEQ. */ + struct request *next, *prev; + + struct event timeout_event; + + u16 trans_id; /* the transaction id */ + unsigned request_appended :1; /* true if the request pointer is data which follows this struct */ + unsigned transmit_me :1; /* needs to be transmitted */ + + /* XXXX This is a horrible hack. */ + char **put_cname_in_ptr; /* store the cname here if we get one. */ + + struct evdns_base *base; + + struct evdns_request *handle; +}; + +struct reply { + unsigned int type; + unsigned int have_answer : 1; + union { + struct { + u32 addrcount; + u32 addresses[MAX_V4_ADDRS]; + } a; + struct { + u32 addrcount; + struct in6_addr addresses[MAX_V6_ADDRS]; + } aaaa; + struct { + char name[HOST_NAME_MAX]; + } ptr; + } data; +}; + +struct nameserver { + evutil_socket_t socket; /* a connected UDP socket */ + struct sockaddr_storage address; + ev_socklen_t addrlen; + int failed_times; /* number of times which we have given this server a chance */ + int timedout; /* number of times in a row a request has timed out */ + struct event event; + /* these objects are kept in a circular list */ + struct nameserver *next, *prev; + struct event timeout_event; /* used to keep the timeout for */ + /* when we next probe this server. */ + /* Valid if state == 0 */ + /* Outstanding probe request for this nameserver, if any */ + struct evdns_request *probe_request; + char state; /* zero if we think that this server is down */ + char choked; /* true if we have an EAGAIN from this server's socket */ + char write_waiting; /* true if we are waiting for EV_WRITE events */ + struct evdns_base *base; +}; + + +/* Represents a local port where we're listening for DNS requests. Right now, */ +/* only UDP is supported. */ +struct evdns_server_port { + evutil_socket_t socket; /* socket we use to read queries and write replies. */ + int refcnt; /* reference count. */ + char choked; /* Are we currently blocked from writing? */ + char closing; /* Are we trying to close this port, pending writes? */ + evdns_request_callback_fn_type user_callback; /* Fn to handle requests */ + void *user_data; /* Opaque pointer passed to user_callback */ + struct event event; /* Read/write event */ + /* circular list of replies that we want to write. */ + struct server_request *pending_replies; + struct event_base *event_base; + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + void *lock; +#endif +}; + +/* Represents part of a reply being built. (That is, a single RR.) */ +struct server_reply_item { + struct server_reply_item *next; /* next item in sequence. */ + char *name; /* name part of the RR */ + u16 type; /* The RR type */ + u16 class; /* The RR class (usually CLASS_INET) */ + u32 ttl; /* The RR TTL */ + char is_name; /* True iff data is a label */ + u16 datalen; /* Length of data; -1 if data is a label */ + void *data; /* The contents of the RR */ +}; + +/* Represents a request that we've received as a DNS server, and holds */ +/* the components of the reply as we're constructing it. */ +struct server_request { + /* Pointers to the next and previous entries on the list of replies */ + /* that we're waiting to write. Only set if we have tried to respond */ + /* and gotten EAGAIN. */ + struct server_request *next_pending; + struct server_request *prev_pending; + + u16 trans_id; /* Transaction id. */ + struct evdns_server_port *port; /* Which port received this request on? */ + struct sockaddr_storage addr; /* Where to send the response */ + ev_socklen_t addrlen; /* length of addr */ + + int n_answer; /* how many answer RRs have been set? */ + int n_authority; /* how many authority RRs have been set? */ + int n_additional; /* how many additional RRs have been set? */ + + struct server_reply_item *answer; /* linked list of answer RRs */ + struct server_reply_item *authority; /* linked list of authority RRs */ + struct server_reply_item *additional; /* linked list of additional RRs */ + + /* Constructed response. Only set once we're ready to send a reply. */ + /* Once this is set, the RR fields are cleared, and no more should be set. */ + char *response; + size_t response_len; + + /* Caller-visible fields: flags, questions. */ + struct evdns_server_request base; +}; + +struct evdns_base { + /* An array of n_req_heads circular lists for inflight requests. + * Each inflight request req is in req_heads[req->trans_id % n_req_heads]. + */ + struct request **req_heads; + /* A circular list of requests that we're waiting to send, but haven't + * sent yet because there are too many requests inflight */ + struct request *req_waiting_head; + /* A circular list of nameservers. */ + struct nameserver *server_head; + int n_req_heads; + + struct event_base *event_base; + + /* The number of good nameservers that we have */ + int global_good_nameservers; + + /* inflight requests are contained in the req_head list */ + /* and are actually going out across the network */ + int global_requests_inflight; + /* requests which aren't inflight are in the waiting list */ + /* and are counted here */ + int global_requests_waiting; + + int global_max_requests_inflight; + + struct timeval global_timeout; /* 5 seconds by default */ + int global_max_reissues; /* a reissue occurs when we get some errors from the server */ + int global_max_retransmits; /* number of times we'll retransmit a request which timed out */ + /* number of timeouts in a row before we consider this server to be down */ + int global_max_nameserver_timeout; + /* true iff we will use the 0x20 hack to prevent poisoning attacks. */ + int global_randomize_case; + + /* The first time that a nameserver fails, how long do we wait before + * probing to see if it has returned? */ + struct timeval global_nameserver_probe_initial_timeout; + + /** Port to bind to for outgoing DNS packets. */ + struct sockaddr_storage global_outgoing_address; + /** ev_socklen_t for global_outgoing_address. 0 if it isn't set. */ + ev_socklen_t global_outgoing_addrlen; + + struct timeval global_getaddrinfo_allow_skew; + + int getaddrinfo_ipv4_timeouts; + int getaddrinfo_ipv6_timeouts; + int getaddrinfo_ipv4_answered; + int getaddrinfo_ipv6_answered; + + struct search_state *global_search_state; + + TAILQ_HEAD(hosts_list, hosts_entry) hostsdb; + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + void *lock; +#endif +}; + +struct hosts_entry { + TAILQ_ENTRY(hosts_entry) next; + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } addr; + int addrlen; + char hostname[1]; +}; + +static struct evdns_base *current_base = NULL; + +struct evdns_base * +evdns_get_global_base(void) +{ + return current_base; +} + +/* Given a pointer to an evdns_server_request, get the corresponding */ +/* server_request. */ +#define TO_SERVER_REQUEST(base_ptr) \ + ((struct server_request*) \ + (((char*)(base_ptr) - evutil_offsetof(struct server_request, base)))) + +#define REQ_HEAD(base, id) ((base)->req_heads[id % (base)->n_req_heads]) + +static struct nameserver *nameserver_pick(struct evdns_base *base); +static void evdns_request_insert(struct request *req, struct request **head); +static void evdns_request_remove(struct request *req, struct request **head); +static void nameserver_ready_callback(evutil_socket_t fd, short events, void *arg); +static int evdns_transmit(struct evdns_base *base); +static int evdns_request_transmit(struct request *req); +static void nameserver_send_probe(struct nameserver *const ns); +static void search_request_finished(struct evdns_request *const); +static int search_try_next(struct evdns_request *const req); +static struct request *search_request_new(struct evdns_base *base, struct evdns_request *handle, int type, const char *const name, int flags, evdns_callback_type user_callback, void *user_arg); +static void evdns_requests_pump_waiting_queue(struct evdns_base *base); +static u16 transaction_id_pick(struct evdns_base *base); +static struct request *request_new(struct evdns_base *base, struct evdns_request *handle, int type, const char *name, int flags, evdns_callback_type callback, void *ptr); +static void request_submit(struct request *const req); + +static int server_request_free(struct server_request *req); +static void server_request_free_answers(struct server_request *req); +static void server_port_free(struct evdns_server_port *port); +static void server_port_ready_callback(evutil_socket_t fd, short events, void *arg); +static int evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename); +static int evdns_base_set_option_impl(struct evdns_base *base, + const char *option, const char *val, int flags); +static void evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests); + +static int strtoint(const char *const str); + +#ifdef _EVENT_DISABLE_THREAD_SUPPORT +#define EVDNS_LOCK(base) _EVUTIL_NIL_STMT +#define EVDNS_UNLOCK(base) _EVUTIL_NIL_STMT +#define ASSERT_LOCKED(base) _EVUTIL_NIL_STMT +#else +#define EVDNS_LOCK(base) \ + EVLOCK_LOCK((base)->lock, 0) +#define EVDNS_UNLOCK(base) \ + EVLOCK_UNLOCK((base)->lock, 0) +#define ASSERT_LOCKED(base) \ + EVLOCK_ASSERT_LOCKED((base)->lock) +#endif + +static void +default_evdns_log_fn(int warning, const char *buf) +{ + if (warning == EVDNS_LOG_WARN) + event_warnx("[evdns] %s", buf); + else if (warning == EVDNS_LOG_MSG) + event_msgx("[evdns] %s", buf); + else + event_debug(("[evdns] %s", buf)); +} + +static evdns_debug_log_fn_type evdns_log_fn = NULL; + +void +evdns_set_log_fn(evdns_debug_log_fn_type fn) +{ + evdns_log_fn = fn; +} + +#ifdef __GNUC__ +#define EVDNS_LOG_CHECK __attribute__ ((format(printf, 2, 3))) +#else +#define EVDNS_LOG_CHECK +#endif + +static void _evdns_log(int warn, const char *fmt, ...) EVDNS_LOG_CHECK; +static void +_evdns_log(int warn, const char *fmt, ...) +{ + va_list args; + char buf[512]; + if (!evdns_log_fn) + return; + va_start(args,fmt); + evutil_vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + if (evdns_log_fn) { + if (warn == EVDNS_LOG_MSG) + warn = EVDNS_LOG_WARN; + evdns_log_fn(warn, buf); + } else { + default_evdns_log_fn(warn, buf); + } + +} + +#define log _evdns_log + +/* This walks the list of inflight requests to find the */ +/* one with a matching transaction id. Returns NULL on */ +/* failure */ +static struct request * +request_find_from_trans_id(struct evdns_base *base, u16 trans_id) { + struct request *req = REQ_HEAD(base, trans_id); + struct request *const started_at = req; + + ASSERT_LOCKED(base); + + if (req) { + do { + if (req->trans_id == trans_id) return req; + req = req->next; + } while (req != started_at); + } + + return NULL; +} + +/* a libevent callback function which is called when a nameserver */ +/* has gone down and we want to test if it has came back to life yet */ +static void +nameserver_prod_callback(evutil_socket_t fd, short events, void *arg) { + struct nameserver *const ns = (struct nameserver *) arg; + (void)fd; + (void)events; + + EVDNS_LOCK(ns->base); + nameserver_send_probe(ns); + EVDNS_UNLOCK(ns->base); +} + +/* a libevent callback which is called when a nameserver probe (to see if */ +/* it has come back to life) times out. We increment the count of failed_times */ +/* and wait longer to send the next probe packet. */ +static void +nameserver_probe_failed(struct nameserver *const ns) { + struct timeval timeout; + int i; + + ASSERT_LOCKED(ns->base); + (void) evtimer_del(&ns->timeout_event); + if (ns->state == 1) { + /* This can happen if the nameserver acts in a way which makes us mark */ + /* it as bad and then starts sending good replies. */ + return; + } + +#define MAX_PROBE_TIMEOUT 3600 +#define TIMEOUT_BACKOFF_FACTOR 3 + + memcpy(&timeout, &ns->base->global_nameserver_probe_initial_timeout, + sizeof(struct timeval)); + for (i=ns->failed_times; i > 0 && timeout.tv_sec < MAX_PROBE_TIMEOUT; --i) { + timeout.tv_sec *= TIMEOUT_BACKOFF_FACTOR; + timeout.tv_usec *= TIMEOUT_BACKOFF_FACTOR; + if (timeout.tv_usec > 1000000) { + timeout.tv_sec += timeout.tv_usec / 1000000; + timeout.tv_usec %= 1000000; + } + } + if (timeout.tv_sec > MAX_PROBE_TIMEOUT) { + timeout.tv_sec = MAX_PROBE_TIMEOUT; + timeout.tv_usec = 0; + } + + ns->failed_times++; + + if (evtimer_add(&ns->timeout_event, &timeout) < 0) { + char addrbuf[128]; + log(EVDNS_LOG_WARN, + "Error from libevent when adding timer event for %s", + evutil_format_sockaddr_port( + (struct sockaddr *)&ns->address, + addrbuf, sizeof(addrbuf))); + } +} + +/* called when a nameserver has been deemed to have failed. For example, too */ +/* many packets have timed out etc */ +static void +nameserver_failed(struct nameserver *const ns, const char *msg) { + struct request *req, *started_at; + struct evdns_base *base = ns->base; + int i; + char addrbuf[128]; + + ASSERT_LOCKED(base); + /* if this nameserver has already been marked as failed */ + /* then don't do anything */ + if (!ns->state) return; + + log(EVDNS_LOG_MSG, "Nameserver %s has failed: %s", + evutil_format_sockaddr_port( + (struct sockaddr *)&ns->address, + addrbuf, sizeof(addrbuf)), + msg); + + base->global_good_nameservers--; + EVUTIL_ASSERT(base->global_good_nameservers >= 0); + if (base->global_good_nameservers == 0) { + log(EVDNS_LOG_MSG, "All nameservers have failed"); + } + + ns->state = 0; + ns->failed_times = 1; + + if (evtimer_add(&ns->timeout_event, + &base->global_nameserver_probe_initial_timeout) < 0) { + log(EVDNS_LOG_WARN, + "Error from libevent when adding timer event for %s", + evutil_format_sockaddr_port( + (struct sockaddr *)&ns->address, + addrbuf, sizeof(addrbuf))); + /* ???? Do more? */ + } + + /* walk the list of inflight requests to see if any can be reassigned to */ + /* a different server. Requests in the waiting queue don't have a */ + /* nameserver assigned yet */ + + /* if we don't have *any* good nameservers then there's no point */ + /* trying to reassign requests to one */ + if (!base->global_good_nameservers) return; + + for (i = 0; i < base->n_req_heads; ++i) { + req = started_at = base->req_heads[i]; + if (req) { + do { + if (req->tx_count == 0 && req->ns == ns) { + /* still waiting to go out, can be moved */ + /* to another server */ + req->ns = nameserver_pick(base); + } + req = req->next; + } while (req != started_at); + } + } +} + +static void +nameserver_up(struct nameserver *const ns) +{ + char addrbuf[128]; + ASSERT_LOCKED(ns->base); + if (ns->state) return; + log(EVDNS_LOG_MSG, "Nameserver %s is back up", + evutil_format_sockaddr_port( + (struct sockaddr *)&ns->address, + addrbuf, sizeof(addrbuf))); + evtimer_del(&ns->timeout_event); + if (ns->probe_request) { + evdns_cancel_request(ns->base, ns->probe_request); + ns->probe_request = NULL; + } + ns->state = 1; + ns->failed_times = 0; + ns->timedout = 0; + ns->base->global_good_nameservers++; +} + +static void +request_trans_id_set(struct request *const req, const u16 trans_id) { + req->trans_id = trans_id; + *((u16 *) req->request) = htons(trans_id); +} + +/* Called to remove a request from a list and dealloc it. */ +/* head is a pointer to the head of the list it should be */ +/* removed from or NULL if the request isn't in a list. */ +/* when free_handle is one, free the handle as well. */ +static void +request_finished(struct request *const req, struct request **head, int free_handle) { + struct evdns_base *base = req->base; + int was_inflight = (head != &base->req_waiting_head); + EVDNS_LOCK(base); + ASSERT_VALID_REQUEST(req); + + if (head) + evdns_request_remove(req, head); + + log(EVDNS_LOG_DEBUG, "Removing timeout for request %p", req); + if (was_inflight) { + evtimer_del(&req->timeout_event); + base->global_requests_inflight--; + } else { + base->global_requests_waiting--; + } + /* it was initialized during request_new / evtimer_assign */ + event_debug_unassign(&req->timeout_event); + + if (!req->request_appended) { + /* need to free the request data on it's own */ + mm_free(req->request); + } else { + /* the request data is appended onto the header */ + /* so everything gets free()ed when we: */ + } + + if (req->handle) { + EVUTIL_ASSERT(req->handle->current_req == req); + + if (free_handle) { + search_request_finished(req->handle); + req->handle->current_req = NULL; + if (! req->handle->pending_cb) { + /* If we're planning to run the callback, + * don't free the handle until later. */ + mm_free(req->handle); + } + req->handle = NULL; /* If we have a bug, let's crash + * early */ + } else { + req->handle->current_req = NULL; + } + } + + mm_free(req); + + evdns_requests_pump_waiting_queue(base); + EVDNS_UNLOCK(base); +} + +/* This is called when a server returns a funny error code. */ +/* We try the request again with another server. */ +/* */ +/* return: */ +/* 0 ok */ +/* 1 failed/reissue is pointless */ +static int +request_reissue(struct request *req) { + const struct nameserver *const last_ns = req->ns; + ASSERT_LOCKED(req->base); + ASSERT_VALID_REQUEST(req); + /* the last nameserver should have been marked as failing */ + /* by the caller of this function, therefore pick will try */ + /* not to return it */ + req->ns = nameserver_pick(req->base); + if (req->ns == last_ns) { + /* ... but pick did return it */ + /* not a lot of point in trying again with the */ + /* same server */ + return 1; + } + + req->reissue_count++; + req->tx_count = 0; + req->transmit_me = 1; + + return 0; +} + +/* this function looks for space on the inflight queue and promotes */ +/* requests from the waiting queue if it can. */ +static void +evdns_requests_pump_waiting_queue(struct evdns_base *base) { + ASSERT_LOCKED(base); + while (base->global_requests_inflight < base->global_max_requests_inflight && + base->global_requests_waiting) { + struct request *req; + /* move a request from the waiting queue to the inflight queue */ + EVUTIL_ASSERT(base->req_waiting_head); + req = base->req_waiting_head; + evdns_request_remove(req, &base->req_waiting_head); + + base->global_requests_waiting--; + base->global_requests_inflight++; + + req->ns = nameserver_pick(base); + request_trans_id_set(req, transaction_id_pick(base)); + + evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); + evdns_request_transmit(req); + evdns_transmit(base); + } +} + +/* TODO(nickm) document */ +struct deferred_reply_callback { + struct deferred_cb deferred; + struct evdns_request *handle; + u8 request_type; + u8 have_reply; + u32 ttl; + u32 err; + evdns_callback_type user_callback; + struct reply reply; +}; + +static void +reply_run_callback(struct deferred_cb *d, void *user_pointer) +{ + struct deferred_reply_callback *cb = + EVUTIL_UPCAST(d, struct deferred_reply_callback, deferred); + + switch (cb->request_type) { + case TYPE_A: + if (cb->have_reply) + cb->user_callback(DNS_ERR_NONE, DNS_IPv4_A, + cb->reply.data.a.addrcount, cb->ttl, + cb->reply.data.a.addresses, + user_pointer); + else + cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); + break; + case TYPE_PTR: + if (cb->have_reply) { + char *name = cb->reply.data.ptr.name; + cb->user_callback(DNS_ERR_NONE, DNS_PTR, 1, cb->ttl, + &name, user_pointer); + } else { + cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); + } + break; + case TYPE_AAAA: + if (cb->have_reply) + cb->user_callback(DNS_ERR_NONE, DNS_IPv6_AAAA, + cb->reply.data.aaaa.addrcount, cb->ttl, + cb->reply.data.aaaa.addresses, + user_pointer); + else + cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); + break; + default: + EVUTIL_ASSERT(0); + } + + if (cb->handle && cb->handle->pending_cb) { + mm_free(cb->handle); + } + + mm_free(cb); +} + +static void +reply_schedule_callback(struct request *const req, u32 ttl, u32 err, struct reply *reply) +{ + struct deferred_reply_callback *d = mm_calloc(1, sizeof(*d)); + + if (!d) { + event_warn("%s: Couldn't allocate space for deferred callback.", + __func__); + return; + } + + ASSERT_LOCKED(req->base); + + d->request_type = req->request_type; + d->user_callback = req->user_callback; + d->ttl = ttl; + d->err = err; + if (reply) { + d->have_reply = 1; + memcpy(&d->reply, reply, sizeof(struct reply)); + } + + if (req->handle) { + req->handle->pending_cb = 1; + d->handle = req->handle; + } + + event_deferred_cb_init(&d->deferred, reply_run_callback, + req->user_pointer); + event_deferred_cb_schedule( + event_base_get_deferred_cb_queue(req->base->event_base), + &d->deferred); +} + +/* this processes a parsed reply packet */ +static void +reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) { + int error; + char addrbuf[128]; + static const int error_codes[] = { + DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, + DNS_ERR_NOTIMPL, DNS_ERR_REFUSED + }; + + ASSERT_LOCKED(req->base); + ASSERT_VALID_REQUEST(req); + + if (flags & 0x020f || !reply || !reply->have_answer) { + /* there was an error */ + if (flags & 0x0200) { + error = DNS_ERR_TRUNCATED; + } else if (flags & 0x000f) { + u16 error_code = (flags & 0x000f) - 1; + if (error_code > 4) { + error = DNS_ERR_UNKNOWN; + } else { + error = error_codes[error_code]; + } + } else if (reply && !reply->have_answer) { + error = DNS_ERR_NODATA; + } else { + error = DNS_ERR_UNKNOWN; + } + + switch (error) { + case DNS_ERR_NOTIMPL: + case DNS_ERR_REFUSED: + /* we regard these errors as marking a bad nameserver */ + if (req->reissue_count < req->base->global_max_reissues) { + char msg[64]; + evutil_snprintf(msg, sizeof(msg), "Bad response %d (%s)", + error, evdns_err_to_string(error)); + nameserver_failed(req->ns, msg); + if (!request_reissue(req)) return; + } + break; + case DNS_ERR_SERVERFAILED: + /* rcode 2 (servfailed) sometimes means "we + * are broken" and sometimes (with some binds) + * means "that request was very confusing." + * Treat this as a timeout, not a failure. + */ + log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver" + "at %s; will allow the request to time out.", + evutil_format_sockaddr_port( + (struct sockaddr *)&req->ns->address, + addrbuf, sizeof(addrbuf))); + break; + default: + /* we got a good reply from the nameserver: it is up. */ + if (req->handle == req->ns->probe_request) { + /* Avoid double-free */ + req->ns->probe_request = NULL; + } + + nameserver_up(req->ns); + } + + if (req->handle->search_state && + req->request_type != TYPE_PTR) { + /* if we have a list of domains to search in, + * try the next one */ + if (!search_try_next(req->handle)) { + /* a new request was issued so this + * request is finished and */ + /* the user callback will be made when + * that request (or a */ + /* child of it) finishes. */ + return; + } + } + + /* all else failed. Pass the failure up */ + reply_schedule_callback(req, ttl, error, NULL); + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); + } else { + /* all ok, tell the user */ + reply_schedule_callback(req, ttl, 0, reply); + if (req->handle == req->ns->probe_request) + req->ns->probe_request = NULL; /* Avoid double-free */ + nameserver_up(req->ns); + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); + } +} + +static int +name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) { + int name_end = -1; + int j = *idx; + int ptr_count = 0; +#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while (0) +#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while (0) +#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while (0) + + char *cp = name_out; + const char *const end = name_out + name_out_len; + + /* Normally, names are a series of length prefixed strings terminated */ + /* with a length of 0 (the lengths are u8's < 63). */ + /* However, the length can start with a pair of 1 bits and that */ + /* means that the next 14 bits are a pointer within the current */ + /* packet. */ + + for (;;) { + u8 label_len; + if (j >= length) return -1; + GET8(label_len); + if (!label_len) break; + if (label_len & 0xc0) { + u8 ptr_low; + GET8(ptr_low); + if (name_end < 0) name_end = j; + j = (((int)label_len & 0x3f) << 8) + ptr_low; + /* Make sure that the target offset is in-bounds. */ + if (j < 0 || j >= length) return -1; + /* If we've jumped more times than there are characters in the + * message, we must have a loop. */ + if (++ptr_count > length) return -1; + continue; + } + if (label_len > 63) return -1; + if (cp != name_out) { + if (cp + 1 >= end) return -1; + *cp++ = '.'; + } + if (cp + label_len >= end) return -1; + memcpy(cp, packet + j, label_len); + cp += label_len; + j += label_len; + } + if (cp >= end) return -1; + *cp = '\0'; + if (name_end < 0) + *idx = j; + else + *idx = name_end; + return 0; + err: + return -1; +} + +/* parses a raw request from a nameserver */ +static int +reply_parse(struct evdns_base *base, u8 *packet, int length) { + int j = 0, k = 0; /* index into packet */ + u16 _t; /* used by the macros */ + u32 _t32; /* used by the macros */ + char tmp_name[256], cmp_name[256]; /* used by the macros */ + int name_matches = 0; + + u16 trans_id, questions, answers, authority, additional, datalength; + u16 flags = 0; + u32 ttl, ttl_r = 0xffffffff; + struct reply reply; + struct request *req = NULL; + unsigned int i; + + ASSERT_LOCKED(base); + + GET16(trans_id); + GET16(flags); + GET16(questions); + GET16(answers); + GET16(authority); + GET16(additional); + (void) authority; /* suppress "unused variable" warnings. */ + (void) additional; /* suppress "unused variable" warnings. */ + + req = request_find_from_trans_id(base, trans_id); + if (!req) return -1; + EVUTIL_ASSERT(req->base == base); + + memset(&reply, 0, sizeof(reply)); + + /* If it's not an answer, it doesn't correspond to any request. */ + if (!(flags & 0x8000)) return -1; /* must be an answer */ + if ((flags & 0x020f) && (flags & 0x020f) != DNS_ERR_NOTEXIST) { + /* there was an error and it's not NXDOMAIN */ + goto err; + } + /* if (!answers) return; */ /* must have an answer of some form */ + + /* This macro skips a name in the DNS reply. */ +#define SKIP_NAME \ + do { tmp_name[0] = '\0'; \ + if (name_parse(packet, length, &j, tmp_name, \ + sizeof(tmp_name))<0) \ + goto err; \ + } while (0) +#define TEST_NAME \ + do { tmp_name[0] = '\0'; \ + cmp_name[0] = '\0'; \ + k = j; \ + if (name_parse(packet, length, &j, tmp_name, \ + sizeof(tmp_name))<0) \ + goto err; \ + if (name_parse(req->request, req->request_len, &k, \ + cmp_name, sizeof(cmp_name))<0) \ + goto err; \ + if (base->global_randomize_case) { \ + if (strcmp(tmp_name, cmp_name) == 0) \ + name_matches = 1; \ + } else { \ + if (evutil_ascii_strcasecmp(tmp_name, cmp_name) == 0) \ + name_matches = 1; \ + } \ + } while (0) + + reply.type = req->request_type; + + /* skip over each question in the reply */ + for (i = 0; i < questions; ++i) { + /* the question looks like + * + */ + TEST_NAME; + j += 4; + if (j > length) goto err; + } + + if (!name_matches) + goto err; + + /* now we have the answer section which looks like + * + */ + + for (i = 0; i < answers; ++i) { + u16 type, class; + + SKIP_NAME; + GET16(type); + GET16(class); + GET32(ttl); + GET16(datalength); + + if (type == TYPE_A && class == CLASS_INET) { + int addrcount, addrtocopy; + if (req->request_type != TYPE_A) { + j += datalength; continue; + } + if ((datalength & 3) != 0) /* not an even number of As. */ + goto err; + addrcount = datalength >> 2; + addrtocopy = MIN(MAX_V4_ADDRS - reply.data.a.addrcount, (unsigned)addrcount); + + ttl_r = MIN(ttl_r, ttl); + /* we only bother with the first four addresses. */ + if (j + 4*addrtocopy > length) goto err; + memcpy(&reply.data.a.addresses[reply.data.a.addrcount], + packet + j, 4*addrtocopy); + j += 4*addrtocopy; + reply.data.a.addrcount += addrtocopy; + reply.have_answer = 1; + if (reply.data.a.addrcount == MAX_V4_ADDRS) break; + } else if (type == TYPE_PTR && class == CLASS_INET) { + if (req->request_type != TYPE_PTR) { + j += datalength; continue; + } + if (name_parse(packet, length, &j, reply.data.ptr.name, + sizeof(reply.data.ptr.name))<0) + goto err; + ttl_r = MIN(ttl_r, ttl); + reply.have_answer = 1; + break; + } else if (type == TYPE_CNAME) { + char cname[HOST_NAME_MAX]; + if (!req->put_cname_in_ptr || *req->put_cname_in_ptr) { + j += datalength; continue; + } + if (name_parse(packet, length, &j, cname, + sizeof(cname))<0) + goto err; + *req->put_cname_in_ptr = mm_strdup(cname); + } else if (type == TYPE_AAAA && class == CLASS_INET) { + int addrcount, addrtocopy; + if (req->request_type != TYPE_AAAA) { + j += datalength; continue; + } + if ((datalength & 15) != 0) /* not an even number of AAAAs. */ + goto err; + addrcount = datalength >> 4; /* each address is 16 bytes long */ + addrtocopy = MIN(MAX_V6_ADDRS - reply.data.aaaa.addrcount, (unsigned)addrcount); + ttl_r = MIN(ttl_r, ttl); + + /* we only bother with the first four addresses. */ + if (j + 16*addrtocopy > length) goto err; + memcpy(&reply.data.aaaa.addresses[reply.data.aaaa.addrcount], + packet + j, 16*addrtocopy); + reply.data.aaaa.addrcount += addrtocopy; + j += 16*addrtocopy; + reply.have_answer = 1; + if (reply.data.aaaa.addrcount == MAX_V6_ADDRS) break; + } else { + /* skip over any other type of resource */ + j += datalength; + } + } + + if (!reply.have_answer) { + for (i = 0; i < authority; ++i) { + u16 type, class; + SKIP_NAME; + GET16(type); + GET16(class); + GET32(ttl); + GET16(datalength); + if (type == TYPE_SOA && class == CLASS_INET) { + u32 serial, refresh, retry, expire, minimum; + SKIP_NAME; + SKIP_NAME; + GET32(serial); + GET32(refresh); + GET32(retry); + GET32(expire); + GET32(minimum); + (void)expire; + (void)retry; + (void)refresh; + (void)serial; + ttl_r = MIN(ttl_r, ttl); + ttl_r = MIN(ttl_r, minimum); + } else { + /* skip over any other type of resource */ + j += datalength; + } + } + } + + if (ttl_r == 0xffffffff) + ttl_r = 0; + + reply_handle(req, flags, ttl_r, &reply); + return 0; + err: + if (req) + reply_handle(req, flags, 0, NULL); + return -1; +} + +/* Parse a raw request (packet,length) sent to a nameserver port (port) from */ +/* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */ +/* callback. */ +static int +request_parse(u8 *packet, int length, struct evdns_server_port *port, struct sockaddr *addr, ev_socklen_t addrlen) +{ + int j = 0; /* index into packet */ + u16 _t; /* used by the macros */ + char tmp_name[256]; /* used by the macros */ + + int i; + u16 trans_id, flags, questions, answers, authority, additional; + struct server_request *server_req = NULL; + + ASSERT_LOCKED(port); + + /* Get the header fields */ + GET16(trans_id); + GET16(flags); + GET16(questions); + GET16(answers); + GET16(authority); + GET16(additional); + (void)answers; + (void)additional; + (void)authority; + + if (flags & 0x8000) return -1; /* Must not be an answer. */ + flags &= 0x0110; /* Only RD and CD get preserved. */ + + server_req = mm_malloc(sizeof(struct server_request)); + if (server_req == NULL) return -1; + memset(server_req, 0, sizeof(struct server_request)); + + server_req->trans_id = trans_id; + memcpy(&server_req->addr, addr, addrlen); + server_req->addrlen = addrlen; + + server_req->base.flags = flags; + server_req->base.nquestions = 0; + server_req->base.questions = mm_calloc(sizeof(struct evdns_server_question *), questions); + if (server_req->base.questions == NULL) + goto err; + + for (i = 0; i < questions; ++i) { + u16 type, class; + struct evdns_server_question *q; + int namelen; + if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) + goto err; + GET16(type); + GET16(class); + namelen = (int)strlen(tmp_name); + q = mm_malloc(sizeof(struct evdns_server_question) + namelen); + if (!q) + goto err; + q->type = type; + q->dns_question_class = class; + memcpy(q->name, tmp_name, namelen+1); + server_req->base.questions[server_req->base.nquestions++] = q; + } + + /* Ignore answers, authority, and additional. */ + + server_req->port = port; + port->refcnt++; + + /* Only standard queries are supported. */ + if (flags & 0x7800) { + evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL); + return -1; + } + + port->user_callback(&(server_req->base), port->user_data); + + return 0; +err: + if (server_req) { + if (server_req->base.questions) { + for (i = 0; i < server_req->base.nquestions; ++i) + mm_free(server_req->base.questions[i]); + mm_free(server_req->base.questions); + } + mm_free(server_req); + } + return -1; + +#undef SKIP_NAME +#undef GET32 +#undef GET16 +#undef GET8 +} + + +void +evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void)) +{ +} + +void +evdns_set_random_bytes_fn(void (*fn)(char *, size_t)) +{ +} + +/* Try to choose a strong transaction id which isn't already in flight */ +static u16 +transaction_id_pick(struct evdns_base *base) { + ASSERT_LOCKED(base); + for (;;) { + u16 trans_id; + evutil_secure_rng_get_bytes(&trans_id, sizeof(trans_id)); + + if (trans_id == 0xffff) continue; + /* now check to see if that id is already inflight */ + if (request_find_from_trans_id(base, trans_id) == NULL) + return trans_id; + } +} + +/* choose a namesever to use. This function will try to ignore */ +/* nameservers which we think are down and load balance across the rest */ +/* by updating the server_head global each time. */ +static struct nameserver * +nameserver_pick(struct evdns_base *base) { + struct nameserver *started_at = base->server_head, *picked; + ASSERT_LOCKED(base); + if (!base->server_head) return NULL; + + /* if we don't have any good nameservers then there's no */ + /* point in trying to find one. */ + if (!base->global_good_nameservers) { + base->server_head = base->server_head->next; + return base->server_head; + } + + /* remember that nameservers are in a circular list */ + for (;;) { + if (base->server_head->state) { + /* we think this server is currently good */ + picked = base->server_head; + base->server_head = base->server_head->next; + return picked; + } + + base->server_head = base->server_head->next; + if (base->server_head == started_at) { + /* all the nameservers seem to be down */ + /* so we just return this one and hope for the */ + /* best */ + EVUTIL_ASSERT(base->global_good_nameservers == 0); + picked = base->server_head; + base->server_head = base->server_head->next; + return picked; + } + } +} + +/* this is called when a namesever socket is ready for reading */ +static void +nameserver_read(struct nameserver *ns) { + struct sockaddr_storage ss; + ev_socklen_t addrlen = sizeof(ss); + u8 packet[1500]; + char addrbuf[128]; + ASSERT_LOCKED(ns->base); + + for (;;) { + const int r = recvfrom(ns->socket, (void*)packet, + sizeof(packet), 0, + (struct sockaddr*)&ss, &addrlen); + if (r < 0) { + int err = evutil_socket_geterror(ns->socket); + if (EVUTIL_ERR_RW_RETRIABLE(err)) + return; + nameserver_failed(ns, + evutil_socket_error_to_string(err)); + return; + } + if (evutil_sockaddr_cmp((struct sockaddr*)&ss, + (struct sockaddr*)&ns->address, 0)) { + log(EVDNS_LOG_WARN, "Address mismatch on received " + "DNS packet. Apparent source was %s", + evutil_format_sockaddr_port( + (struct sockaddr *)&ss, + addrbuf, sizeof(addrbuf))); + return; + } + + ns->timedout = 0; + reply_parse(ns->base, packet, r); + } +} + +/* Read a packet from a DNS client on a server port s, parse it, and */ +/* act accordingly. */ +static void +server_port_read(struct evdns_server_port *s) { + u8 packet[1500]; + struct sockaddr_storage addr; + ev_socklen_t addrlen; + int r; + ASSERT_LOCKED(s); + + for (;;) { + addrlen = sizeof(struct sockaddr_storage); + r = recvfrom(s->socket, (void*)packet, sizeof(packet), 0, + (struct sockaddr*) &addr, &addrlen); + if (r < 0) { + int err = evutil_socket_geterror(s->socket); + if (EVUTIL_ERR_RW_RETRIABLE(err)) + return; + log(EVDNS_LOG_WARN, + "Error %s (%d) while reading request.", + evutil_socket_error_to_string(err), err); + return; + } + request_parse(packet, r, s, (struct sockaddr*) &addr, addrlen); + } +} + +/* Try to write all pending replies on a given DNS server port. */ +static void +server_port_flush(struct evdns_server_port *port) +{ + struct server_request *req = port->pending_replies; + ASSERT_LOCKED(port); + while (req) { + int r = sendto(port->socket, req->response, (int)req->response_len, 0, + (struct sockaddr*) &req->addr, (ev_socklen_t)req->addrlen); + if (r < 0) { + int err = evutil_socket_geterror(port->socket); + if (EVUTIL_ERR_RW_RETRIABLE(err)) + return; + log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", evutil_socket_error_to_string(err), err); + } + if (server_request_free(req)) { + /* we released the last reference to req->port. */ + return; + } else { + EVUTIL_ASSERT(req != port->pending_replies); + req = port->pending_replies; + } + } + + /* We have no more pending requests; stop listening for 'writeable' events. */ + (void) event_del(&port->event); + event_assign(&port->event, port->event_base, + port->socket, EV_READ | EV_PERSIST, + server_port_ready_callback, port); + + if (event_add(&port->event, NULL) < 0) { + log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server."); + /* ???? Do more? */ + } +} + +/* set if we are waiting for the ability to write to this server. */ +/* if waiting is true then we ask libevent for EV_WRITE events, otherwise */ +/* we stop these events. */ +static void +nameserver_write_waiting(struct nameserver *ns, char waiting) { + ASSERT_LOCKED(ns->base); + if (ns->write_waiting == waiting) return; + + ns->write_waiting = waiting; + (void) event_del(&ns->event); + event_assign(&ns->event, ns->base->event_base, + ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST, + nameserver_ready_callback, ns); + if (event_add(&ns->event, NULL) < 0) { + char addrbuf[128]; + log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s", + evutil_format_sockaddr_port( + (struct sockaddr *)&ns->address, + addrbuf, sizeof(addrbuf))); + /* ???? Do more? */ + } +} + +/* a callback function. Called by libevent when the kernel says that */ +/* a nameserver socket is ready for writing or reading */ +static void +nameserver_ready_callback(evutil_socket_t fd, short events, void *arg) { + struct nameserver *ns = (struct nameserver *) arg; + (void)fd; + + EVDNS_LOCK(ns->base); + if (events & EV_WRITE) { + ns->choked = 0; + if (!evdns_transmit(ns->base)) { + nameserver_write_waiting(ns, 0); + } + } + if (events & EV_READ) { + nameserver_read(ns); + } + EVDNS_UNLOCK(ns->base); +} + +/* a callback function. Called by libevent when the kernel says that */ +/* a server socket is ready for writing or reading. */ +static void +server_port_ready_callback(evutil_socket_t fd, short events, void *arg) { + struct evdns_server_port *port = (struct evdns_server_port *) arg; + (void) fd; + + EVDNS_LOCK(port); + if (events & EV_WRITE) { + port->choked = 0; + server_port_flush(port); + } + if (events & EV_READ) { + server_port_read(port); + } + EVDNS_UNLOCK(port); +} + +/* This is an inefficient representation; only use it via the dnslabel_table_* + * functions, so that is can be safely replaced with something smarter later. */ +#define MAX_LABELS 128 +/* Structures used to implement name compression */ +struct dnslabel_entry { char *v; off_t pos; }; +struct dnslabel_table { + int n_labels; /* number of current entries */ + /* map from name to position in message */ + struct dnslabel_entry labels[MAX_LABELS]; +}; + +/* Initialize dnslabel_table. */ +static void +dnslabel_table_init(struct dnslabel_table *table) +{ + table->n_labels = 0; +} + +/* Free all storage held by table, but not the table itself. */ +static void +dnslabel_clear(struct dnslabel_table *table) +{ + int i; + for (i = 0; i < table->n_labels; ++i) + mm_free(table->labels[i].v); + table->n_labels = 0; +} + +/* return the position of the label in the current message, or -1 if the label */ +/* hasn't been used yet. */ +static int +dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label) +{ + int i; + for (i = 0; i < table->n_labels; ++i) { + if (!strcmp(label, table->labels[i].v)) + return table->labels[i].pos; + } + return -1; +} + +/* remember that we've used the label at position pos */ +static int +dnslabel_table_add(struct dnslabel_table *table, const char *label, off_t pos) +{ + char *v; + int p; + if (table->n_labels == MAX_LABELS) + return (-1); + v = mm_strdup(label); + if (v == NULL) + return (-1); + p = table->n_labels++; + table->labels[p].v = v; + table->labels[p].pos = pos; + + return (0); +} + +/* Converts a string to a length-prefixed set of DNS labels, starting */ +/* at buf[j]. name and buf must not overlap. name_len should be the length */ +/* of name. table is optional, and is used for compression. */ +/* */ +/* Input: abc.def */ +/* Output: <3>abc<3>def<0> */ +/* */ +/* Returns the first index after the encoded name, or negative on error. */ +/* -1 label was > 63 bytes */ +/* -2 name too long to fit in buffer. */ +/* */ +static off_t +dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j, + const char *name, const size_t name_len, + struct dnslabel_table *table) { + const char *end = name + name_len; + int ref = 0; + u16 _t; + +#define APPEND16(x) do { \ + if (j + 2 > (off_t)buf_len) \ + goto overflow; \ + _t = htons(x); \ + memcpy(buf + j, &_t, 2); \ + j += 2; \ + } while (0) +#define APPEND32(x) do { \ + if (j + 4 > (off_t)buf_len) \ + goto overflow; \ + _t32 = htonl(x); \ + memcpy(buf + j, &_t32, 4); \ + j += 4; \ + } while (0) + + if (name_len > 255) return -2; + + for (;;) { + const char *const start = name; + if (table && (ref = dnslabel_table_get_pos(table, name)) >= 0) { + APPEND16(ref | 0xc000); + return j; + } + name = strchr(name, '.'); + if (!name) { + const size_t label_len = end - start; + if (label_len > 63) return -1; + if ((size_t)(j+label_len+1) > buf_len) return -2; + if (table) dnslabel_table_add(table, start, j); + buf[j++] = (ev_uint8_t)label_len; + + memcpy(buf + j, start, label_len); + j += (int) label_len; + break; + } else { + /* append length of the label. */ + const size_t label_len = name - start; + if (label_len > 63) return -1; + if ((size_t)(j+label_len+1) > buf_len) return -2; + if (table) dnslabel_table_add(table, start, j); + buf[j++] = (ev_uint8_t)label_len; + + memcpy(buf + j, start, label_len); + j += (int) label_len; + /* hop over the '.' */ + name++; + } + } + + /* the labels must be terminated by a 0. */ + /* It's possible that the name ended in a . */ + /* in which case the zero is already there */ + if (!j || buf[j-1]) buf[j++] = 0; + return j; + overflow: + return (-2); +} + +/* Finds the length of a dns request for a DNS name of the given */ +/* length. The actual request may be smaller than the value returned */ +/* here */ +static size_t +evdns_request_len(const size_t name_len) { + return 96 + /* length of the DNS standard header */ + name_len + 2 + + 4; /* space for the resource type */ +} + +/* build a dns request packet into buf. buf should be at least as long */ +/* as evdns_request_len told you it should be. */ +/* */ +/* Returns the amount of space used. Negative on error. */ +static int +evdns_request_data_build(const char *const name, const size_t name_len, + const u16 trans_id, const u16 type, const u16 class, + u8 *const buf, size_t buf_len) { + off_t j = 0; /* current offset into buf */ + u16 _t; /* used by the macros */ + + APPEND16(trans_id); + APPEND16(0x0100); /* standard query, recusion needed */ + APPEND16(1); /* one question */ + APPEND16(0); /* no answers */ + APPEND16(0); /* no authority */ + APPEND16(0); /* no additional */ + + j = dnsname_to_labels(buf, buf_len, j, name, name_len, NULL); + if (j < 0) { + return (int)j; + } + + APPEND16(type); + APPEND16(class); + + return (int)j; + overflow: + return (-1); +} + +/* exported function */ +struct evdns_server_port * +evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type cb, void *user_data) +{ + struct evdns_server_port *port; + if (flags) + return NULL; /* flags not yet implemented */ + if (!(port = mm_malloc(sizeof(struct evdns_server_port)))) + return NULL; + memset(port, 0, sizeof(struct evdns_server_port)); + + + port->socket = socket; + port->refcnt = 1; + port->choked = 0; + port->closing = 0; + port->user_callback = cb; + port->user_data = user_data; + port->pending_replies = NULL; + port->event_base = base; + + event_assign(&port->event, port->event_base, + port->socket, EV_READ | EV_PERSIST, + server_port_ready_callback, port); + if (event_add(&port->event, NULL) < 0) { + mm_free(port); + return NULL; + } + EVTHREAD_ALLOC_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + return port; +} + +struct evdns_server_port * +evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type cb, void *user_data) +{ + return evdns_add_server_port_with_base(NULL, socket, flags, cb, user_data); +} + +/* exported function */ +void +evdns_close_server_port(struct evdns_server_port *port) +{ + EVDNS_LOCK(port); + if (--port->refcnt == 0) { + EVDNS_UNLOCK(port); + server_port_free(port); + } else { + port->closing = 1; + } +} + +/* exported function */ +int +evdns_server_request_add_reply(struct evdns_server_request *_req, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data) +{ + struct server_request *req = TO_SERVER_REQUEST(_req); + struct server_reply_item **itemp, *item; + int *countp; + int result = -1; + + EVDNS_LOCK(req->port); + if (req->response) /* have we already answered? */ + goto done; + + switch (section) { + case EVDNS_ANSWER_SECTION: + itemp = &req->answer; + countp = &req->n_answer; + break; + case EVDNS_AUTHORITY_SECTION: + itemp = &req->authority; + countp = &req->n_authority; + break; + case EVDNS_ADDITIONAL_SECTION: + itemp = &req->additional; + countp = &req->n_additional; + break; + default: + goto done; + } + while (*itemp) { + itemp = &((*itemp)->next); + } + item = mm_malloc(sizeof(struct server_reply_item)); + if (!item) + goto done; + item->next = NULL; + if (!(item->name = mm_strdup(name))) { + mm_free(item); + goto done; + } + item->type = type; + item->dns_question_class = class; + item->ttl = ttl; + item->is_name = is_name != 0; + item->datalen = 0; + item->data = NULL; + if (data) { + if (item->is_name) { + if (!(item->data = mm_strdup(data))) { + mm_free(item->name); + mm_free(item); + goto done; + } + item->datalen = (u16)-1; + } else { + if (!(item->data = mm_malloc(datalen))) { + mm_free(item->name); + mm_free(item); + goto done; + } + item->datalen = datalen; + memcpy(item->data, data, datalen); + } + } + + *itemp = item; + ++(*countp); + result = 0; +done: + EVDNS_UNLOCK(req->port); + return result; +} + +/* exported function */ +int +evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl) +{ + return evdns_server_request_add_reply( + req, EVDNS_ANSWER_SECTION, name, TYPE_A, CLASS_INET, + ttl, n*4, 0, addrs); +} + +/* exported function */ +int +evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl) +{ + return evdns_server_request_add_reply( + req, EVDNS_ANSWER_SECTION, name, TYPE_AAAA, CLASS_INET, + ttl, n*16, 0, addrs); +} + +/* exported function */ +int +evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl) +{ + u32 a; + char buf[32]; + if (in && inaddr_name) + return -1; + else if (!in && !inaddr_name) + return -1; + if (in) { + a = ntohl(in->s_addr); + evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", + (int)(u8)((a )&0xff), + (int)(u8)((a>>8 )&0xff), + (int)(u8)((a>>16)&0xff), + (int)(u8)((a>>24)&0xff)); + inaddr_name = buf; + } + return evdns_server_request_add_reply( + req, EVDNS_ANSWER_SECTION, inaddr_name, TYPE_PTR, CLASS_INET, + ttl, -1, 1, hostname); +} + +/* exported function */ +int +evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl) +{ + return evdns_server_request_add_reply( + req, EVDNS_ANSWER_SECTION, name, TYPE_CNAME, CLASS_INET, + ttl, -1, 1, cname); +} + +/* exported function */ +void +evdns_server_request_set_flags(struct evdns_server_request *exreq, int flags) +{ + struct server_request *req = TO_SERVER_REQUEST(exreq); + req->base.flags &= ~(EVDNS_FLAGS_AA|EVDNS_FLAGS_RD); + req->base.flags |= flags; +} + +static int +evdns_server_request_format_response(struct server_request *req, int err) +{ + unsigned char buf[1500]; + size_t buf_len = sizeof(buf); + off_t j = 0, r; + u16 _t; + u32 _t32; + int i; + u16 flags; + struct dnslabel_table table; + + if (err < 0 || err > 15) return -1; + + /* Set response bit and error code; copy OPCODE and RD fields from + * question; copy RA and AA if set by caller. */ + flags = req->base.flags; + flags |= (0x8000 | err); + + dnslabel_table_init(&table); + APPEND16(req->trans_id); + APPEND16(flags); + APPEND16(req->base.nquestions); + APPEND16(req->n_answer); + APPEND16(req->n_authority); + APPEND16(req->n_additional); + + /* Add questions. */ + for (i=0; i < req->base.nquestions; ++i) { + const char *s = req->base.questions[i]->name; + j = dnsname_to_labels(buf, buf_len, j, s, strlen(s), &table); + if (j < 0) { + dnslabel_clear(&table); + return (int) j; + } + APPEND16(req->base.questions[i]->type); + APPEND16(req->base.questions[i]->dns_question_class); + } + + /* Add answer, authority, and additional sections. */ + for (i=0; i<3; ++i) { + struct server_reply_item *item; + if (i==0) + item = req->answer; + else if (i==1) + item = req->authority; + else + item = req->additional; + while (item) { + r = dnsname_to_labels(buf, buf_len, j, item->name, strlen(item->name), &table); + if (r < 0) + goto overflow; + j = r; + + APPEND16(item->type); + APPEND16(item->dns_question_class); + APPEND32(item->ttl); + if (item->is_name) { + off_t len_idx = j, name_start; + j += 2; + name_start = j; + r = dnsname_to_labels(buf, buf_len, j, item->data, strlen(item->data), &table); + if (r < 0) + goto overflow; + j = r; + _t = htons( (short) (j-name_start) ); + memcpy(buf+len_idx, &_t, 2); + } else { + APPEND16(item->datalen); + if (j+item->datalen > (off_t)buf_len) + goto overflow; + memcpy(buf+j, item->data, item->datalen); + j += item->datalen; + } + item = item->next; + } + } + + if (j > 512) { +overflow: + j = 512; + buf[2] |= 0x02; /* set the truncated bit. */ + } + + req->response_len = j; + + if (!(req->response = mm_malloc(req->response_len))) { + server_request_free_answers(req); + dnslabel_clear(&table); + return (-1); + } + memcpy(req->response, buf, req->response_len); + server_request_free_answers(req); + dnslabel_clear(&table); + return (0); +} + +/* exported function */ +int +evdns_server_request_respond(struct evdns_server_request *_req, int err) +{ + struct server_request *req = TO_SERVER_REQUEST(_req); + struct evdns_server_port *port = req->port; + int r = -1; + + EVDNS_LOCK(port); + if (!req->response) { + if ((r = evdns_server_request_format_response(req, err))<0) + goto done; + } + + r = sendto(port->socket, req->response, (int)req->response_len, 0, + (struct sockaddr*) &req->addr, (ev_socklen_t)req->addrlen); + if (r<0) { + int sock_err = evutil_socket_geterror(port->socket); + if (EVUTIL_ERR_RW_RETRIABLE(sock_err)) + goto done; + + if (port->pending_replies) { + req->prev_pending = port->pending_replies->prev_pending; + req->next_pending = port->pending_replies; + req->prev_pending->next_pending = + req->next_pending->prev_pending = req; + } else { + req->prev_pending = req->next_pending = req; + port->pending_replies = req; + port->choked = 1; + + (void) event_del(&port->event); + event_assign(&port->event, port->event_base, port->socket, (port->closing?0:EV_READ) | EV_WRITE | EV_PERSIST, server_port_ready_callback, port); + + if (event_add(&port->event, NULL) < 0) { + log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server"); + } + + } + + r = 1; + goto done; + } + if (server_request_free(req)) { + r = 0; + goto done; + } + + if (port->pending_replies) + server_port_flush(port); + + r = 0; +done: + EVDNS_UNLOCK(port); + return r; +} + +/* Free all storage held by RRs in req. */ +static void +server_request_free_answers(struct server_request *req) +{ + struct server_reply_item *victim, *next, **list; + int i; + for (i = 0; i < 3; ++i) { + if (i==0) + list = &req->answer; + else if (i==1) + list = &req->authority; + else + list = &req->additional; + + victim = *list; + while (victim) { + next = victim->next; + mm_free(victim->name); + if (victim->data) + mm_free(victim->data); + mm_free(victim); + victim = next; + } + *list = NULL; + } +} + +/* Free all storage held by req, and remove links to it. */ +/* return true iff we just wound up freeing the server_port. */ +static int +server_request_free(struct server_request *req) +{ + int i, rc=1, lock=0; + if (req->base.questions) { + for (i = 0; i < req->base.nquestions; ++i) + mm_free(req->base.questions[i]); + mm_free(req->base.questions); + } + + if (req->port) { + EVDNS_LOCK(req->port); + lock=1; + if (req->port->pending_replies == req) { + if (req->next_pending && req->next_pending != req) + req->port->pending_replies = req->next_pending; + else + req->port->pending_replies = NULL; + } + rc = --req->port->refcnt; + } + + if (req->response) { + mm_free(req->response); + } + + server_request_free_answers(req); + + if (req->next_pending && req->next_pending != req) { + req->next_pending->prev_pending = req->prev_pending; + req->prev_pending->next_pending = req->next_pending; + } + + if (rc == 0) { + EVDNS_UNLOCK(req->port); /* ????? nickm */ + server_port_free(req->port); + mm_free(req); + return (1); + } + if (lock) + EVDNS_UNLOCK(req->port); + mm_free(req); + return (0); +} + +/* Free all storage held by an evdns_server_port. Only called when */ +static void +server_port_free(struct evdns_server_port *port) +{ + EVUTIL_ASSERT(port); + EVUTIL_ASSERT(!port->refcnt); + EVUTIL_ASSERT(!port->pending_replies); + if (port->socket > 0) { + evutil_closesocket(port->socket); + port->socket = -1; + } + (void) event_del(&port->event); + event_debug_unassign(&port->event); + EVTHREAD_FREE_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + mm_free(port); +} + +/* exported function */ +int +evdns_server_request_drop(struct evdns_server_request *_req) +{ + struct server_request *req = TO_SERVER_REQUEST(_req); + server_request_free(req); + return 0; +} + +/* exported function */ +int +evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len) +{ + struct server_request *req = TO_SERVER_REQUEST(_req); + if (addr_len < (int)req->addrlen) + return -1; + memcpy(sa, &(req->addr), req->addrlen); + return req->addrlen; +} + +#undef APPEND16 +#undef APPEND32 + +/* this is a libevent callback function which is called when a request */ +/* has timed out. */ +static void +evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg) { + struct request *const req = (struct request *) arg; +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + struct evdns_base *base = req->base; +#endif + (void) fd; + (void) events; + + log(EVDNS_LOG_DEBUG, "Request %p timed out", arg); + EVDNS_LOCK(base); + + req->ns->timedout++; + if (req->ns->timedout > req->base->global_max_nameserver_timeout) { + req->ns->timedout = 0; + nameserver_failed(req->ns, "request timed out."); + } + + if (req->tx_count >= req->base->global_max_retransmits) { + /* this request has failed */ + reply_schedule_callback(req, 0, DNS_ERR_TIMEOUT, NULL); + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); + } else { + /* retransmit it */ + (void) evtimer_del(&req->timeout_event); + evdns_request_transmit(req); + } + EVDNS_UNLOCK(base); +} + +/* try to send a request to a given server. */ +/* */ +/* return: */ +/* 0 ok */ +/* 1 temporary failure */ +/* 2 other failure */ +static int +evdns_request_transmit_to(struct request *req, struct nameserver *server) { + int r; + ASSERT_LOCKED(req->base); + ASSERT_VALID_REQUEST(req); + r = sendto(server->socket, (void*)req->request, req->request_len, 0, + (struct sockaddr *)&server->address, server->addrlen); + if (r < 0) { + int err = evutil_socket_geterror(server->socket); + if (EVUTIL_ERR_RW_RETRIABLE(err)) + return 1; + nameserver_failed(req->ns, evutil_socket_error_to_string(err)); + return 2; + } else if (r != (int)req->request_len) { + return 1; /* short write */ + } else { + return 0; + } +} + +/* try to send a request, updating the fields of the request */ +/* as needed */ +/* */ +/* return: */ +/* 0 ok */ +/* 1 failed */ +static int +evdns_request_transmit(struct request *req) { + int retcode = 0, r; + + ASSERT_LOCKED(req->base); + ASSERT_VALID_REQUEST(req); + /* if we fail to send this packet then this flag marks it */ + /* for evdns_transmit */ + req->transmit_me = 1; + EVUTIL_ASSERT(req->trans_id != 0xffff); + + if (req->ns->choked) { + /* don't bother trying to write to a socket */ + /* which we have had EAGAIN from */ + return 1; + } + + r = evdns_request_transmit_to(req, req->ns); + switch (r) { + case 1: + /* temp failure */ + req->ns->choked = 1; + nameserver_write_waiting(req->ns, 1); + return 1; + case 2: + /* failed to transmit the request entirely. */ + retcode = 1; + /* fall through: we'll set a timeout, which will time out, + * and make us retransmit the request anyway. */ + default: + /* all ok */ + log(EVDNS_LOG_DEBUG, + "Setting timeout for request %p", req); + if (evtimer_add(&req->timeout_event, &req->base->global_timeout) < 0) { + log(EVDNS_LOG_WARN, + "Error from libevent when adding timer for request %p", + req); + /* ???? Do more? */ + } + req->tx_count++; + req->transmit_me = 0; + return retcode; + } +} + +static void +nameserver_probe_callback(int result, char type, int count, int ttl, void *addresses, void *arg) { + struct nameserver *const ns = (struct nameserver *) arg; + (void) type; + (void) count; + (void) ttl; + (void) addresses; + + EVDNS_LOCK(ns->base); + ns->probe_request = NULL; + if (result == DNS_ERR_CANCEL) { + /* We canceled this request because the nameserver came up + * for some other reason. Do not change our opinion about + * the nameserver. */ + } else if (result == DNS_ERR_NONE || result == DNS_ERR_NOTEXIST) { + /* this is a good reply */ + nameserver_up(ns); + } else { + nameserver_probe_failed(ns); + } + EVDNS_UNLOCK(ns->base); +} + +static void +nameserver_send_probe(struct nameserver *const ns) { + struct evdns_request *handle; + struct request *req; + char addrbuf[128]; + /* here we need to send a probe to a given nameserver */ + /* in the hope that it is up now. */ + + ASSERT_LOCKED(ns->base); + log(EVDNS_LOG_DEBUG, "Sending probe to %s", + evutil_format_sockaddr_port( + (struct sockaddr *)&ns->address, + addrbuf, sizeof(addrbuf))); + handle = mm_calloc(1, sizeof(*handle)); + if (!handle) return; + req = request_new(ns->base, handle, TYPE_A, "google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_callback, ns); + if (!req) return; + ns->probe_request = handle; + /* we force this into the inflight queue no matter what */ + request_trans_id_set(req, transaction_id_pick(ns->base)); + req->ns = ns; + request_submit(req); +} + +/* returns: */ +/* 0 didn't try to transmit anything */ +/* 1 tried to transmit something */ +static int +evdns_transmit(struct evdns_base *base) { + char did_try_to_transmit = 0; + int i; + + ASSERT_LOCKED(base); + for (i = 0; i < base->n_req_heads; ++i) { + if (base->req_heads[i]) { + struct request *const started_at = base->req_heads[i], *req = started_at; + /* first transmit all the requests which are currently waiting */ + do { + if (req->transmit_me) { + did_try_to_transmit = 1; + evdns_request_transmit(req); + } + + req = req->next; + } while (req != started_at); + } + } + + return did_try_to_transmit; +} + +/* exported function */ +int +evdns_base_count_nameservers(struct evdns_base *base) +{ + const struct nameserver *server; + int n = 0; + + EVDNS_LOCK(base); + server = base->server_head; + if (!server) + goto done; + do { + ++n; + server = server->next; + } while (server != base->server_head); +done: + EVDNS_UNLOCK(base); + return n; +} + +int +evdns_count_nameservers(void) +{ + return evdns_base_count_nameservers(current_base); +} + +/* exported function */ +int +evdns_base_clear_nameservers_and_suspend(struct evdns_base *base) +{ + struct nameserver *server, *started_at; + int i; + + EVDNS_LOCK(base); + server = base->server_head; + started_at = base->server_head; + if (!server) { + EVDNS_UNLOCK(base); + return 0; + } + while (1) { + struct nameserver *next = server->next; + (void) event_del(&server->event); + if (evtimer_initialized(&server->timeout_event)) + (void) evtimer_del(&server->timeout_event); + if (server->socket >= 0) + evutil_closesocket(server->socket); + mm_free(server); + if (next == started_at) + break; + server = next; + } + base->server_head = NULL; + base->global_good_nameservers = 0; + + for (i = 0; i < base->n_req_heads; ++i) { + struct request *req, *req_started_at; + req = req_started_at = base->req_heads[i]; + while (req) { + struct request *next = req->next; + req->tx_count = req->reissue_count = 0; + req->ns = NULL; + /* ???? What to do about searches? */ + (void) evtimer_del(&req->timeout_event); + req->trans_id = 0; + req->transmit_me = 0; + + base->global_requests_waiting++; + evdns_request_insert(req, &base->req_waiting_head); + /* We want to insert these suspended elements at the front of + * the waiting queue, since they were pending before any of + * the waiting entries were added. This is a circular list, + * so we can just shift the start back by one.*/ + base->req_waiting_head = base->req_waiting_head->prev; + + if (next == req_started_at) + break; + req = next; + } + base->req_heads[i] = NULL; + } + + base->global_requests_inflight = 0; + + EVDNS_UNLOCK(base); + return 0; +} + +int +evdns_clear_nameservers_and_suspend(void) +{ + return evdns_base_clear_nameservers_and_suspend(current_base); +} + + +/* exported function */ +int +evdns_base_resume(struct evdns_base *base) +{ + EVDNS_LOCK(base); + evdns_requests_pump_waiting_queue(base); + EVDNS_UNLOCK(base); + return 0; +} + +int +evdns_resume(void) +{ + return evdns_base_resume(current_base); +} + +static int +_evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *address, int addrlen) { + /* first check to see if we already have this nameserver */ + + const struct nameserver *server = base->server_head, *const started_at = base->server_head; + struct nameserver *ns; + int err = 0; + char addrbuf[128]; + + ASSERT_LOCKED(base); + if (server) { + do { + if (!evutil_sockaddr_cmp((struct sockaddr*)&server->address, address, 1)) return 3; + server = server->next; + } while (server != started_at); + } + if (addrlen > (int)sizeof(ns->address)) { + log(EVDNS_LOG_DEBUG, "Addrlen %d too long.", (int)addrlen); + return 2; + } + + ns = (struct nameserver *) mm_malloc(sizeof(struct nameserver)); + if (!ns) return -1; + + memset(ns, 0, sizeof(struct nameserver)); + ns->base = base; + + evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns); + + ns->socket = socket(address->sa_family, SOCK_DGRAM, 0); + if (ns->socket < 0) { err = 1; goto out1; } + evutil_make_socket_closeonexec(ns->socket); + evutil_make_socket_nonblocking(ns->socket); + + if (base->global_outgoing_addrlen && + !evutil_sockaddr_is_loopback(address)) { + if (bind(ns->socket, + (struct sockaddr*)&base->global_outgoing_address, + base->global_outgoing_addrlen) < 0) { + log(EVDNS_LOG_WARN,"Couldn't bind to outgoing address"); + err = 2; + goto out2; + } + } + + memcpy(&ns->address, address, addrlen); + ns->addrlen = addrlen; + ns->state = 1; + event_assign(&ns->event, ns->base->event_base, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns); + if (event_add(&ns->event, NULL) < 0) { + err = 2; + goto out2; + } + + log(EVDNS_LOG_DEBUG, "Added nameserver %s", + evutil_format_sockaddr_port(address, addrbuf, sizeof(addrbuf))); + + /* insert this nameserver into the list of them */ + if (!base->server_head) { + ns->next = ns->prev = ns; + base->server_head = ns; + } else { + ns->next = base->server_head->next; + ns->prev = base->server_head; + base->server_head->next = ns; + ns->next->prev = ns; + } + + base->global_good_nameservers++; + + return 0; + +out2: + evutil_closesocket(ns->socket); +out1: + event_debug_unassign(&ns->event); + mm_free(ns); + log(EVDNS_LOG_WARN, "Unable to add nameserver %s: error %d", + evutil_format_sockaddr_port(address, addrbuf, sizeof(addrbuf)), err); + return err; +} + +/* exported function */ +int +evdns_base_nameserver_add(struct evdns_base *base, unsigned long int address) +{ + struct sockaddr_in sin; + int res; + sin.sin_addr.s_addr = address; + sin.sin_port = htons(53); + sin.sin_family = AF_INET; + EVDNS_LOCK(base); + res = _evdns_nameserver_add_impl(base, (struct sockaddr*)&sin, sizeof(sin)); + EVDNS_UNLOCK(base); + return res; +} + +int +evdns_nameserver_add(unsigned long int address) { + if (!current_base) + current_base = evdns_base_new(NULL, 0); + return evdns_base_nameserver_add(current_base, address); +} + +static void +sockaddr_setport(struct sockaddr *sa, ev_uint16_t port) +{ + if (sa->sa_family == AF_INET) { + ((struct sockaddr_in *)sa)->sin_port = htons(port); + } else if (sa->sa_family == AF_INET6) { + ((struct sockaddr_in6 *)sa)->sin6_port = htons(port); + } +} + +static ev_uint16_t +sockaddr_getport(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { + return ntohs(((struct sockaddr_in *)sa)->sin_port); + } else if (sa->sa_family == AF_INET6) { + return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); + } else { + return 0; + } +} + +/* exported function */ +int +evdns_base_nameserver_ip_add(struct evdns_base *base, const char *ip_as_string) { + struct sockaddr_storage ss; + struct sockaddr *sa; + int len = sizeof(ss); + int res; + if (evutil_parse_sockaddr_port(ip_as_string, (struct sockaddr *)&ss, + &len)) { + log(EVDNS_LOG_WARN, "Unable to parse nameserver address %s", + ip_as_string); + return 4; + } + sa = (struct sockaddr *) &ss; + if (sockaddr_getport(sa) == 0) + sockaddr_setport(sa, 53); + + EVDNS_LOCK(base); + res = _evdns_nameserver_add_impl(base, sa, len); + EVDNS_UNLOCK(base); + return res; +} + +int +evdns_nameserver_ip_add(const char *ip_as_string) { + if (!current_base) + current_base = evdns_base_new(NULL, 0); + return evdns_base_nameserver_ip_add(current_base, ip_as_string); +} + +int +evdns_base_nameserver_sockaddr_add(struct evdns_base *base, + const struct sockaddr *sa, ev_socklen_t len, unsigned flags) +{ + int res; + EVUTIL_ASSERT(base); + EVDNS_LOCK(base); + res = _evdns_nameserver_add_impl(base, sa, len); + EVDNS_UNLOCK(base); + return res; +} + +/* remove from the queue */ +static void +evdns_request_remove(struct request *req, struct request **head) +{ + ASSERT_LOCKED(req->base); + ASSERT_VALID_REQUEST(req); + +#if 0 + { + struct request *ptr; + int found = 0; + EVUTIL_ASSERT(*head != NULL); + + ptr = *head; + do { + if (ptr == req) { + found = 1; + break; + } + ptr = ptr->next; + } while (ptr != *head); + EVUTIL_ASSERT(found); + + EVUTIL_ASSERT(req->next); + } +#endif + + if (req->next == req) { + /* only item in the list */ + *head = NULL; + } else { + req->next->prev = req->prev; + req->prev->next = req->next; + if (*head == req) *head = req->next; + } + req->next = req->prev = NULL; +} + +/* insert into the tail of the queue */ +static void +evdns_request_insert(struct request *req, struct request **head) { + ASSERT_LOCKED(req->base); + ASSERT_VALID_REQUEST(req); + if (!*head) { + *head = req; + req->next = req->prev = req; + return; + } + + req->prev = (*head)->prev; + req->prev->next = req; + req->next = *head; + (*head)->prev = req; +} + +static int +string_num_dots(const char *s) { + int count = 0; + while ((s = strchr(s, '.'))) { + s++; + count++; + } + return count; +} + +static struct request * +request_new(struct evdns_base *base, struct evdns_request *handle, int type, + const char *name, int flags, evdns_callback_type callback, + void *user_ptr) { + + const char issuing_now = + (base->global_requests_inflight < base->global_max_requests_inflight) ? 1 : 0; + + const size_t name_len = strlen(name); + const size_t request_max_len = evdns_request_len(name_len); + const u16 trans_id = issuing_now ? transaction_id_pick(base) : 0xffff; + /* the request data is alloced in a single block with the header */ + struct request *const req = + mm_malloc(sizeof(struct request) + request_max_len); + int rlen; + char namebuf[256]; + (void) flags; + + ASSERT_LOCKED(base); + + if (!req) return NULL; + + if (name_len >= sizeof(namebuf)) { + mm_free(req); + return NULL; + } + + memset(req, 0, sizeof(struct request)); + req->base = base; + + evtimer_assign(&req->timeout_event, req->base->event_base, evdns_request_timeout_callback, req); + + if (base->global_randomize_case) { + unsigned i; + char randbits[(sizeof(namebuf)+7)/8]; + strlcpy(namebuf, name, sizeof(namebuf)); + evutil_secure_rng_get_bytes(randbits, (name_len+7)/8); + for (i = 0; i < name_len; ++i) { + if (EVUTIL_ISALPHA(namebuf[i])) { + if ((randbits[i >> 3] & (1<<(i & 7)))) + namebuf[i] |= 0x20; + else + namebuf[i] &= ~0x20; + } + } + name = namebuf; + } + + /* request data lives just after the header */ + req->request = ((u8 *) req) + sizeof(struct request); + /* denotes that the request data shouldn't be free()ed */ + req->request_appended = 1; + rlen = evdns_request_data_build(name, name_len, trans_id, + type, CLASS_INET, req->request, request_max_len); + if (rlen < 0) + goto err1; + + req->request_len = rlen; + req->trans_id = trans_id; + req->tx_count = 0; + req->request_type = type; + req->user_pointer = user_ptr; + req->user_callback = callback; + req->ns = issuing_now ? nameserver_pick(base) : NULL; + req->next = req->prev = NULL; + req->handle = handle; + if (handle) { + handle->current_req = req; + handle->base = base; + } + + return req; +err1: + mm_free(req); + return NULL; +} + +static void +request_submit(struct request *const req) { + struct evdns_base *base = req->base; + ASSERT_LOCKED(base); + ASSERT_VALID_REQUEST(req); + if (req->ns) { + /* if it has a nameserver assigned then this is going */ + /* straight into the inflight queue */ + evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); + base->global_requests_inflight++; + evdns_request_transmit(req); + } else { + evdns_request_insert(req, &base->req_waiting_head); + base->global_requests_waiting++; + } +} + +/* exported function */ +void +evdns_cancel_request(struct evdns_base *base, struct evdns_request *handle) +{ + struct request *req; + + if (!handle->current_req) + return; + + if (!base) { + /* This redundancy is silly; can we fix it? (Not for 2.0) XXXX */ + base = handle->base; + if (!base) + base = handle->current_req->base; + } + + EVDNS_LOCK(base); + if (handle->pending_cb) { + EVDNS_UNLOCK(base); + return; + } + + req = handle->current_req; + ASSERT_VALID_REQUEST(req); + + reply_schedule_callback(req, 0, DNS_ERR_CANCEL, NULL); + if (req->ns) { + /* remove from inflight queue */ + request_finished(req, &REQ_HEAD(base, req->trans_id), 1); + } else { + /* remove from global_waiting head */ + request_finished(req, &base->req_waiting_head, 1); + } + EVDNS_UNLOCK(base); +} + +/* exported function */ +struct evdns_request * +evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, + evdns_callback_type callback, void *ptr) { + struct evdns_request *handle; + struct request *req; + log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); + handle = mm_calloc(1, sizeof(*handle)); + if (handle == NULL) + return NULL; + EVDNS_LOCK(base); + if (flags & DNS_QUERY_NO_SEARCH) { + req = + request_new(base, handle, TYPE_A, name, flags, + callback, ptr); + if (req) + request_submit(req); + } else { + search_request_new(base, handle, TYPE_A, name, flags, + callback, ptr); + } + if (handle->current_req == NULL) { + mm_free(handle); + handle = NULL; + } + EVDNS_UNLOCK(base); + return handle; +} + +int evdns_resolve_ipv4(const char *name, int flags, + evdns_callback_type callback, void *ptr) +{ + return evdns_base_resolve_ipv4(current_base, name, flags, callback, ptr) + ? 0 : -1; +} + + +/* exported function */ +struct evdns_request * +evdns_base_resolve_ipv6(struct evdns_base *base, + const char *name, int flags, + evdns_callback_type callback, void *ptr) +{ + struct evdns_request *handle; + struct request *req; + log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); + handle = mm_calloc(1, sizeof(*handle)); + if (handle == NULL) + return NULL; + EVDNS_LOCK(base); + if (flags & DNS_QUERY_NO_SEARCH) { + req = request_new(base, handle, TYPE_AAAA, name, flags, + callback, ptr); + if (req) + request_submit(req); + } else { + search_request_new(base, handle, TYPE_AAAA, name, flags, + callback, ptr); + } + if (handle->current_req == NULL) { + mm_free(handle); + handle = NULL; + } + EVDNS_UNLOCK(base); + return handle; +} + +int evdns_resolve_ipv6(const char *name, int flags, + evdns_callback_type callback, void *ptr) { + return evdns_base_resolve_ipv6(current_base, name, flags, callback, ptr) + ? 0 : -1; +} + +struct evdns_request * +evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) { + char buf[32]; + struct evdns_request *handle; + struct request *req; + u32 a; + EVUTIL_ASSERT(in); + a = ntohl(in->s_addr); + evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", + (int)(u8)((a )&0xff), + (int)(u8)((a>>8 )&0xff), + (int)(u8)((a>>16)&0xff), + (int)(u8)((a>>24)&0xff)); + handle = mm_calloc(1, sizeof(*handle)); + if (handle == NULL) + return NULL; + log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); + EVDNS_LOCK(base); + req = request_new(base, handle, TYPE_PTR, buf, flags, callback, ptr); + if (req) + request_submit(req); + if (handle->current_req == NULL) { + mm_free(handle); + handle = NULL; + } + EVDNS_UNLOCK(base); + return (handle); +} + +int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) { + return evdns_base_resolve_reverse(current_base, in, flags, callback, ptr) + ? 0 : -1; +} + +struct evdns_request * +evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) { + /* 32 nybbles, 32 periods, "ip6.arpa", NUL. */ + char buf[73]; + char *cp; + struct evdns_request *handle; + struct request *req; + int i; + EVUTIL_ASSERT(in); + cp = buf; + for (i=15; i >= 0; --i) { + u8 byte = in->s6_addr[i]; + *cp++ = "0123456789abcdef"[byte & 0x0f]; + *cp++ = '.'; + *cp++ = "0123456789abcdef"[byte >> 4]; + *cp++ = '.'; + } + EVUTIL_ASSERT(cp + strlen("ip6.arpa") < buf+sizeof(buf)); + memcpy(cp, "ip6.arpa", strlen("ip6.arpa")+1); + handle = mm_calloc(1, sizeof(*handle)); + if (handle == NULL) + return NULL; + log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); + EVDNS_LOCK(base); + req = request_new(base, handle, TYPE_PTR, buf, flags, callback, ptr); + if (req) + request_submit(req); + if (handle->current_req == NULL) { + mm_free(handle); + handle = NULL; + } + EVDNS_UNLOCK(base); + return (handle); +} + +int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) { + return evdns_base_resolve_reverse_ipv6(current_base, in, flags, callback, ptr) + ? 0 : -1; +} + +/* ================================================================= */ +/* Search support */ +/* */ +/* the libc resolver has support for searching a number of domains */ +/* to find a name. If nothing else then it takes the single domain */ +/* from the gethostname() call. */ +/* */ +/* It can also be configured via the domain and search options in a */ +/* resolv.conf. */ +/* */ +/* The ndots option controls how many dots it takes for the resolver */ +/* to decide that a name is non-local and so try a raw lookup first. */ + +struct search_domain { + int len; + struct search_domain *next; + /* the text string is appended to this structure */ +}; + +struct search_state { + int refcount; + int ndots; + int num_domains; + struct search_domain *head; +}; + +static void +search_state_decref(struct search_state *const state) { + if (!state) return; + state->refcount--; + if (!state->refcount) { + struct search_domain *next, *dom; + for (dom = state->head; dom; dom = next) { + next = dom->next; + mm_free(dom); + } + mm_free(state); + } +} + +static struct search_state * +search_state_new(void) { + struct search_state *state = (struct search_state *) mm_malloc(sizeof(struct search_state)); + if (!state) return NULL; + memset(state, 0, sizeof(struct search_state)); + state->refcount = 1; + state->ndots = 1; + + return state; +} + +static void +search_postfix_clear(struct evdns_base *base) { + search_state_decref(base->global_search_state); + + base->global_search_state = search_state_new(); +} + +/* exported function */ +void +evdns_base_search_clear(struct evdns_base *base) +{ + EVDNS_LOCK(base); + search_postfix_clear(base); + EVDNS_UNLOCK(base); +} + +void +evdns_search_clear(void) { + evdns_base_search_clear(current_base); +} + +static void +search_postfix_add(struct evdns_base *base, const char *domain) { + size_t domain_len; + struct search_domain *sdomain; + while (domain[0] == '.') domain++; + domain_len = strlen(domain); + + ASSERT_LOCKED(base); + if (!base->global_search_state) base->global_search_state = search_state_new(); + if (!base->global_search_state) return; + base->global_search_state->num_domains++; + + sdomain = (struct search_domain *) mm_malloc(sizeof(struct search_domain) + domain_len); + if (!sdomain) return; + memcpy( ((u8 *) sdomain) + sizeof(struct search_domain), domain, domain_len); + sdomain->next = base->global_search_state->head; + sdomain->len = (int) domain_len; + + base->global_search_state->head = sdomain; +} + +/* reverse the order of members in the postfix list. This is needed because, */ +/* when parsing resolv.conf we push elements in the wrong order */ +static void +search_reverse(struct evdns_base *base) { + struct search_domain *cur, *prev = NULL, *next; + ASSERT_LOCKED(base); + cur = base->global_search_state->head; + while (cur) { + next = cur->next; + cur->next = prev; + prev = cur; + cur = next; + } + + base->global_search_state->head = prev; +} + +/* exported function */ +void +evdns_base_search_add(struct evdns_base *base, const char *domain) { + EVDNS_LOCK(base); + search_postfix_add(base, domain); + EVDNS_UNLOCK(base); +} +void +evdns_search_add(const char *domain) { + evdns_base_search_add(current_base, domain); +} + +/* exported function */ +void +evdns_base_search_ndots_set(struct evdns_base *base, const int ndots) { + EVDNS_LOCK(base); + if (!base->global_search_state) base->global_search_state = search_state_new(); + if (base->global_search_state) + base->global_search_state->ndots = ndots; + EVDNS_UNLOCK(base); +} +void +evdns_search_ndots_set(const int ndots) { + evdns_base_search_ndots_set(current_base, ndots); +} + +static void +search_set_from_hostname(struct evdns_base *base) { + char hostname[HOST_NAME_MAX + 1], *domainname; + + ASSERT_LOCKED(base); + search_postfix_clear(base); + if (gethostname(hostname, sizeof(hostname))) return; + domainname = strchr(hostname, '.'); + if (!domainname) return; + search_postfix_add(base, domainname); +} + +/* warning: returns malloced string */ +static char * +search_make_new(const struct search_state *const state, int n, const char *const base_name) { + const size_t base_len = strlen(base_name); + const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; + struct search_domain *dom; + + for (dom = state->head; dom; dom = dom->next) { + if (!n--) { + /* this is the postfix we want */ + /* the actual postfix string is kept at the end of the structure */ + const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain); + const int postfix_len = dom->len; + char *const newname = (char *) mm_malloc(base_len + need_to_append_dot + postfix_len + 1); + if (!newname) return NULL; + memcpy(newname, base_name, base_len); + if (need_to_append_dot) newname[base_len] = '.'; + memcpy(newname + base_len + need_to_append_dot, postfix, postfix_len); + newname[base_len + need_to_append_dot + postfix_len] = 0; + return newname; + } + } + + /* we ran off the end of the list and still didn't find the requested string */ + EVUTIL_ASSERT(0); + return NULL; /* unreachable; stops warnings in some compilers. */ +} + +static struct request * +search_request_new(struct evdns_base *base, struct evdns_request *handle, + int type, const char *const name, int flags, + evdns_callback_type user_callback, void *user_arg) { + ASSERT_LOCKED(base); + EVUTIL_ASSERT(type == TYPE_A || type == TYPE_AAAA); + EVUTIL_ASSERT(handle->current_req == NULL); + if ( ((flags & DNS_QUERY_NO_SEARCH) == 0) && + base->global_search_state && + base->global_search_state->num_domains) { + /* we have some domains to search */ + struct request *req; + if (string_num_dots(name) >= base->global_search_state->ndots) { + req = request_new(base, handle, type, name, flags, user_callback, user_arg); + if (!req) return NULL; + handle->search_index = -1; + } else { + char *const new_name = search_make_new(base->global_search_state, 0, name); + if (!new_name) return NULL; + req = request_new(base, handle, type, new_name, flags, user_callback, user_arg); + mm_free(new_name); + if (!req) return NULL; + handle->search_index = 0; + } + EVUTIL_ASSERT(handle->search_origname == NULL); + handle->search_origname = mm_strdup(name); + if (handle->search_origname == NULL) { + /* XXX Should we dealloc req? If yes, how? */ + return NULL; + } + handle->search_state = base->global_search_state; + handle->search_flags = flags; + base->global_search_state->refcount++; + request_submit(req); + return req; + } else { + struct request *const req = request_new(base, handle, type, name, flags, user_callback, user_arg); + if (!req) return NULL; + request_submit(req); + return req; + } +} + +/* this is called when a request has failed to find a name. We need to check */ +/* if it is part of a search and, if so, try the next name in the list */ +/* returns: */ +/* 0 another request has been submitted */ +/* 1 no more requests needed */ +static int +search_try_next(struct evdns_request *const handle) { + struct request *req = handle->current_req; + struct evdns_base *base = req->base; + struct request *newreq; + ASSERT_LOCKED(base); + if (handle->search_state) { + /* it is part of a search */ + char *new_name; + handle->search_index++; + if (handle->search_index >= handle->search_state->num_domains) { + /* no more postfixes to try, however we may need to try */ + /* this name without a postfix */ + if (string_num_dots(handle->search_origname) < handle->search_state->ndots) { + /* yep, we need to try it raw */ + newreq = request_new(base, NULL, req->request_type, handle->search_origname, handle->search_flags, req->user_callback, req->user_pointer); + log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", handle->search_origname); + if (newreq) { + search_request_finished(handle); + goto submit_next; + } + } + return 1; + } + + new_name = search_make_new(handle->search_state, handle->search_index, handle->search_origname); + if (!new_name) return 1; + log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, handle->search_index); + newreq = request_new(base, NULL, req->request_type, new_name, handle->search_flags, req->user_callback, req->user_pointer); + mm_free(new_name); + if (!newreq) return 1; + goto submit_next; + } + return 1; + +submit_next: + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 0); + handle->current_req = newreq; + newreq->handle = handle; + request_submit(newreq); + return 0; +} + +static void +search_request_finished(struct evdns_request *const handle) { + ASSERT_LOCKED(handle->current_req->base); + if (handle->search_state) { + search_state_decref(handle->search_state); + handle->search_state = NULL; + } + if (handle->search_origname) { + mm_free(handle->search_origname); + handle->search_origname = NULL; + } +} + +/* ================================================================= */ +/* Parsing resolv.conf files */ + +static void +evdns_resolv_set_defaults(struct evdns_base *base, int flags) { + /* if the file isn't found then we assume a local resolver */ + ASSERT_LOCKED(base); + if (flags & DNS_OPTION_SEARCH) search_set_from_hostname(base); + if (flags & DNS_OPTION_NAMESERVERS) evdns_base_nameserver_ip_add(base,"127.0.0.1"); +} + +#ifndef _EVENT_HAVE_STRTOK_R +static char * +strtok_r(char *s, const char *delim, char **state) { + char *cp, *start; + start = cp = s ? s : *state; + if (!cp) + return NULL; + while (*cp && !strchr(delim, *cp)) + ++cp; + if (!*cp) { + if (cp == start) + return NULL; + *state = NULL; + return start; + } else { + *cp++ = '\0'; + *state = cp; + return start; + } +} +#endif + +/* helper version of atoi which returns -1 on error */ +static int +strtoint(const char *const str) +{ + char *endptr; + const int r = strtol(str, &endptr, 10); + if (*endptr) return -1; + return r; +} + +/* Parse a number of seconds into a timeval; return -1 on error. */ +static int +strtotimeval(const char *const str, struct timeval *out) +{ + double d; + char *endptr; + d = strtod(str, &endptr); + if (*endptr) return -1; + if (d < 0) return -1; + out->tv_sec = (int) d; + out->tv_usec = (int) ((d - (int) d)*1000000); + if (out->tv_sec == 0 && out->tv_usec < 1000) /* less than 1 msec */ + return -1; + return 0; +} + +/* helper version of atoi that returns -1 on error and clips to bounds. */ +static int +strtoint_clipped(const char *const str, int min, int max) +{ + int r = strtoint(str); + if (r == -1) + return r; + else if (rmax) + return max; + else + return r; +} + +static int +evdns_base_set_max_requests_inflight(struct evdns_base *base, int maxinflight) +{ + int old_n_heads = base->n_req_heads, n_heads; + struct request **old_heads = base->req_heads, **new_heads, *req; + int i; + + ASSERT_LOCKED(base); + if (maxinflight < 1) + maxinflight = 1; + n_heads = (maxinflight+4) / 5; + EVUTIL_ASSERT(n_heads > 0); + new_heads = mm_calloc(n_heads, sizeof(struct request*)); + if (!new_heads) + return (-1); + if (old_heads) { + for (i = 0; i < old_n_heads; ++i) { + while (old_heads[i]) { + req = old_heads[i]; + evdns_request_remove(req, &old_heads[i]); + evdns_request_insert(req, &new_heads[req->trans_id % n_heads]); + } + } + mm_free(old_heads); + } + base->req_heads = new_heads; + base->n_req_heads = n_heads; + base->global_max_requests_inflight = maxinflight; + return (0); +} + +/* exported function */ +int +evdns_base_set_option(struct evdns_base *base, + const char *option, const char *val) +{ + int res; + EVDNS_LOCK(base); + res = evdns_base_set_option_impl(base, option, val, DNS_OPTIONS_ALL); + EVDNS_UNLOCK(base); + return res; +} + +static inline int +str_matches_option(const char *s1, const char *optionname) +{ + /* Option names are given as "option:" We accept either 'option' in + * s1, or 'option:randomjunk'. The latter form is to implement the + * resolv.conf parser. */ + size_t optlen = strlen(optionname); + size_t slen = strlen(s1); + if (slen == optlen || slen == optlen - 1) + return !strncmp(s1, optionname, slen); + else if (slen > optlen) + return !strncmp(s1, optionname, optlen); + else + return 0; +} + +static int +evdns_base_set_option_impl(struct evdns_base *base, + const char *option, const char *val, int flags) +{ + ASSERT_LOCKED(base); + if (str_matches_option(option, "ndots:")) { + const int ndots = strtoint(val); + if (ndots == -1) return -1; + if (!(flags & DNS_OPTION_SEARCH)) return 0; + log(EVDNS_LOG_DEBUG, "Setting ndots to %d", ndots); + if (!base->global_search_state) base->global_search_state = search_state_new(); + if (!base->global_search_state) return -1; + base->global_search_state->ndots = ndots; + } else if (str_matches_option(option, "timeout:")) { + struct timeval tv; + if (strtotimeval(val, &tv) == -1) return -1; + if (!(flags & DNS_OPTION_MISC)) return 0; + log(EVDNS_LOG_DEBUG, "Setting timeout to %s", val); + memcpy(&base->global_timeout, &tv, sizeof(struct timeval)); + } else if (str_matches_option(option, "getaddrinfo-allow-skew:")) { + struct timeval tv; + if (strtotimeval(val, &tv) == -1) return -1; + if (!(flags & DNS_OPTION_MISC)) return 0; + log(EVDNS_LOG_DEBUG, "Setting getaddrinfo-allow-skew to %s", + val); + memcpy(&base->global_getaddrinfo_allow_skew, &tv, + sizeof(struct timeval)); + } else if (str_matches_option(option, "max-timeouts:")) { + const int maxtimeout = strtoint_clipped(val, 1, 255); + if (maxtimeout == -1) return -1; + if (!(flags & DNS_OPTION_MISC)) return 0; + log(EVDNS_LOG_DEBUG, "Setting maximum allowed timeouts to %d", + maxtimeout); + base->global_max_nameserver_timeout = maxtimeout; + } else if (str_matches_option(option, "max-inflight:")) { + const int maxinflight = strtoint_clipped(val, 1, 65000); + if (maxinflight == -1) return -1; + if (!(flags & DNS_OPTION_MISC)) return 0; + log(EVDNS_LOG_DEBUG, "Setting maximum inflight requests to %d", + maxinflight); + evdns_base_set_max_requests_inflight(base, maxinflight); + } else if (str_matches_option(option, "attempts:")) { + int retries = strtoint(val); + if (retries == -1) return -1; + if (retries > 255) retries = 255; + if (!(flags & DNS_OPTION_MISC)) return 0; + log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries); + base->global_max_retransmits = retries; + } else if (str_matches_option(option, "randomize-case:")) { + int randcase = strtoint(val); + if (!(flags & DNS_OPTION_MISC)) return 0; + base->global_randomize_case = randcase; + } else if (str_matches_option(option, "bind-to:")) { + /* XXX This only applies to successive nameservers, not + * to already-configured ones. We might want to fix that. */ + int len = sizeof(base->global_outgoing_address); + if (!(flags & DNS_OPTION_NAMESERVERS)) return 0; + if (evutil_parse_sockaddr_port(val, + (struct sockaddr*)&base->global_outgoing_address, &len)) + return -1; + base->global_outgoing_addrlen = len; + } else if (str_matches_option(option, "initial-probe-timeout:")) { + struct timeval tv; + if (strtotimeval(val, &tv) == -1) return -1; + if (tv.tv_sec > 3600) + tv.tv_sec = 3600; + if (!(flags & DNS_OPTION_MISC)) return 0; + log(EVDNS_LOG_DEBUG, "Setting initial probe timeout to %s", + val); + memcpy(&base->global_nameserver_probe_initial_timeout, &tv, + sizeof(tv)); + } + return 0; +} + +int +evdns_set_option(const char *option, const char *val, int flags) +{ + if (!current_base) + current_base = evdns_base_new(NULL, 0); + return evdns_base_set_option(current_base, option, val); +} + +static void +resolv_conf_parse_line(struct evdns_base *base, char *const start, int flags) { + char *strtok_state; + static const char *const delims = " \t"; +#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) + + + char *const first_token = strtok_r(start, delims, &strtok_state); + ASSERT_LOCKED(base); + if (!first_token) return; + + if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) { + const char *const nameserver = NEXT_TOKEN; + + if (nameserver) + evdns_base_nameserver_ip_add(base, nameserver); + } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) { + const char *const domain = NEXT_TOKEN; + if (domain) { + search_postfix_clear(base); + search_postfix_add(base, domain); + } + } else if (!strcmp(first_token, "search") && (flags & DNS_OPTION_SEARCH)) { + const char *domain; + search_postfix_clear(base); + + while ((domain = NEXT_TOKEN)) { + search_postfix_add(base, domain); + } + search_reverse(base); + } else if (!strcmp(first_token, "options")) { + const char *option; + while ((option = NEXT_TOKEN)) { + const char *val = strchr(option, ':'); + evdns_base_set_option_impl(base, option, val ? val+1 : "", flags); + } + } +#undef NEXT_TOKEN +} + +/* exported function */ +/* returns: */ +/* 0 no errors */ +/* 1 failed to open file */ +/* 2 failed to stat file */ +/* 3 file too large */ +/* 4 out of memory */ +/* 5 short read from file */ +int +evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename) { + int res; + EVDNS_LOCK(base); + res = evdns_base_resolv_conf_parse_impl(base, flags, filename); + EVDNS_UNLOCK(base); + return res; +} + +static char * +evdns_get_default_hosts_filename(void) +{ +#ifdef WIN32 + /* Windows is a little coy about where it puts its configuration + * files. Sure, they're _usually_ in C:\windows\system32, but + * there's no reason in principle they couldn't be in + * W:\hoboken chicken emergency\ + */ + char path[MAX_PATH+1]; + static const char hostfile[] = "\\drivers\\etc\\hosts"; + char *path_out; + size_t len_out; + + if (! SHGetSpecialFolderPathA(NULL, path, CSIDL_SYSTEM, 0)) + return NULL; + len_out = strlen(path)+strlen(hostfile); + path_out = mm_malloc(len_out+1); + evutil_snprintf(path_out, len_out, "%s%s", path, hostfile); + return path_out; +#else + return mm_strdup("/etc/hosts"); +#endif +} + +static int +evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename) { + size_t n; + char *resolv; + char *start; + int err = 0; + + log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename); + + if (flags & DNS_OPTION_HOSTSFILE) { + char *fname = evdns_get_default_hosts_filename(); + evdns_base_load_hosts(base, fname); + if (fname) + mm_free(fname); + } + + if ((err = evutil_read_file(filename, &resolv, &n, 0)) < 0) { + if (err == -1) { + /* No file. */ + evdns_resolv_set_defaults(base, flags); + return 1; + } else { + return 2; + } + } + + start = resolv; + for (;;) { + char *const newline = strchr(start, '\n'); + if (!newline) { + resolv_conf_parse_line(base, start, flags); + break; + } else { + *newline = 0; + resolv_conf_parse_line(base, start, flags); + start = newline + 1; + } + } + + if (!base->server_head && (flags & DNS_OPTION_NAMESERVERS)) { + /* no nameservers were configured. */ + evdns_base_nameserver_ip_add(base, "127.0.0.1"); + err = 6; + } + if (flags & DNS_OPTION_SEARCH && (!base->global_search_state || base->global_search_state->num_domains == 0)) { + search_set_from_hostname(base); + } + + mm_free(resolv); + return err; +} + +int +evdns_resolv_conf_parse(int flags, const char *const filename) { + if (!current_base) + current_base = evdns_base_new(NULL, 0); + return evdns_base_resolv_conf_parse(current_base, flags, filename); +} + + +#ifdef WIN32 +/* Add multiple nameservers from a space-or-comma-separated list. */ +static int +evdns_nameserver_ip_add_line(struct evdns_base *base, const char *ips) { + const char *addr; + char *buf; + int r; + ASSERT_LOCKED(base); + while (*ips) { + while (isspace(*ips) || *ips == ',' || *ips == '\t') + ++ips; + addr = ips; + while (isdigit(*ips) || *ips == '.' || *ips == ':' || + *ips=='[' || *ips==']') + ++ips; + buf = mm_malloc(ips-addr+1); + if (!buf) return 4; + memcpy(buf, addr, ips-addr); + buf[ips-addr] = '\0'; + r = evdns_base_nameserver_ip_add(base, buf); + mm_free(buf); + if (r) return r; + } + return 0; +} + +typedef DWORD(WINAPI *GetNetworkParams_fn_t)(FIXED_INFO *, DWORD*); + +/* Use the windows GetNetworkParams interface in iphlpapi.dll to */ +/* figure out what our nameservers are. */ +static int +load_nameservers_with_getnetworkparams(struct evdns_base *base) +{ + /* Based on MSDN examples and inspection of c-ares code. */ + FIXED_INFO *fixed; + HMODULE handle = 0; + ULONG size = sizeof(FIXED_INFO); + void *buf = NULL; + int status = 0, r, added_any; + IP_ADDR_STRING *ns; + GetNetworkParams_fn_t fn; + + ASSERT_LOCKED(base); + if (!(handle = evutil_load_windows_system_library( + TEXT("iphlpapi.dll")))) { + log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll"); + status = -1; + goto done; + } + if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, "GetNetworkParams"))) { + log(EVDNS_LOG_WARN, "Could not get address of function."); + status = -1; + goto done; + } + + buf = mm_malloc(size); + if (!buf) { status = 4; goto done; } + fixed = buf; + r = fn(fixed, &size); + if (r != ERROR_SUCCESS && r != ERROR_BUFFER_OVERFLOW) { + status = -1; + goto done; + } + if (r != ERROR_SUCCESS) { + mm_free(buf); + buf = mm_malloc(size); + if (!buf) { status = 4; goto done; } + fixed = buf; + r = fn(fixed, &size); + if (r != ERROR_SUCCESS) { + log(EVDNS_LOG_DEBUG, "fn() failed."); + status = -1; + goto done; + } + } + + EVUTIL_ASSERT(fixed); + added_any = 0; + ns = &(fixed->DnsServerList); + while (ns) { + r = evdns_nameserver_ip_add_line(base, ns->IpAddress.String); + if (r) { + log(EVDNS_LOG_DEBUG,"Could not add nameserver %s to list,error: %d", + (ns->IpAddress.String),(int)GetLastError()); + status = r; + } else { + ++added_any; + log(EVDNS_LOG_DEBUG,"Successfully added %s as nameserver",ns->IpAddress.String); + } + + ns = ns->Next; + } + + if (!added_any) { + log(EVDNS_LOG_DEBUG, "No nameservers added."); + if (status == 0) + status = -1; + } else { + status = 0; + } + + done: + if (buf) + mm_free(buf); + if (handle) + FreeLibrary(handle); + return status; +} + +static int +config_nameserver_from_reg_key(struct evdns_base *base, HKEY key, const TCHAR *subkey) +{ + char *buf; + DWORD bufsz = 0, type = 0; + int status = 0; + + ASSERT_LOCKED(base); + if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz) + != ERROR_MORE_DATA) + return -1; + if (!(buf = mm_malloc(bufsz))) + return -1; + + if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz) + == ERROR_SUCCESS && bufsz > 1) { + status = evdns_nameserver_ip_add_line(base,buf); + } + + mm_free(buf); + return status; +} + +#define SERVICES_KEY TEXT("System\\CurrentControlSet\\Services\\") +#define WIN_NS_9X_KEY SERVICES_KEY TEXT("VxD\\MSTCP") +#define WIN_NS_NT_KEY SERVICES_KEY TEXT("Tcpip\\Parameters") + +static int +load_nameservers_from_registry(struct evdns_base *base) +{ + int found = 0; + int r; +#define TRY(k, name) \ + if (!found && config_nameserver_from_reg_key(base,k,TEXT(name)) == 0) { \ + log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ + found = 1; \ + } else if (!found) { \ + log(EVDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \ + #k,#name); \ + } + + ASSERT_LOCKED(base); + + if (((int)GetVersion()) > 0) { /* NT */ + HKEY nt_key = 0, interfaces_key = 0; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, + KEY_READ, &nt_key) != ERROR_SUCCESS) { + log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError()); + return -1; + } + r = RegOpenKeyEx(nt_key, TEXT("Interfaces"), 0, + KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, + &interfaces_key); + if (r != ERROR_SUCCESS) { + log(EVDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError()); + return -1; + } + TRY(nt_key, "NameServer"); + TRY(nt_key, "DhcpNameServer"); + TRY(interfaces_key, "NameServer"); + TRY(interfaces_key, "DhcpNameServer"); + RegCloseKey(interfaces_key); + RegCloseKey(nt_key); + } else { + HKEY win_key = 0; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0, + KEY_READ, &win_key) != ERROR_SUCCESS) { + log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError()); + return -1; + } + TRY(win_key, "NameServer"); + RegCloseKey(win_key); + } + + if (found == 0) { + log(EVDNS_LOG_WARN,"Didn't find any nameservers."); + } + + return found ? 0 : -1; +#undef TRY +} + +int +evdns_base_config_windows_nameservers(struct evdns_base *base) +{ + int r; + char *fname; + if (base == NULL) + base = current_base; + if (base == NULL) + return -1; + EVDNS_LOCK(base); + if (load_nameservers_with_getnetworkparams(base) == 0) { + EVDNS_UNLOCK(base); + return 0; + } + r = load_nameservers_from_registry(base); + + fname = evdns_get_default_hosts_filename(); + evdns_base_load_hosts(base, fname); + if (fname) + mm_free(fname); + + EVDNS_UNLOCK(base); + return r; +} + +int +evdns_config_windows_nameservers(void) +{ + if (!current_base) { + current_base = evdns_base_new(NULL, 1); + return current_base == NULL ? -1 : 0; + } else { + return evdns_base_config_windows_nameservers(current_base); + } +} +#endif + +struct evdns_base * +evdns_base_new(struct event_base *event_base, int initialize_nameservers) +{ + struct evdns_base *base; + + if (evutil_secure_rng_init() < 0) { + log(EVDNS_LOG_WARN, "Unable to seed random number generator; " + "DNS can't run."); + return NULL; + } + + /* Give the evutil library a hook into its evdns-enabled + * functionality. We can't just call evdns_getaddrinfo directly or + * else libevent-core will depend on libevent-extras. */ + evutil_set_evdns_getaddrinfo_fn(evdns_getaddrinfo); + + base = mm_malloc(sizeof(struct evdns_base)); + if (base == NULL) + return (NULL); + memset(base, 0, sizeof(struct evdns_base)); + base->req_waiting_head = NULL; + + EVTHREAD_ALLOC_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + EVDNS_LOCK(base); + + /* Set max requests inflight and allocate req_heads. */ + base->req_heads = NULL; + + evdns_base_set_max_requests_inflight(base, 64); + + base->server_head = NULL; + base->event_base = event_base; + base->global_good_nameservers = base->global_requests_inflight = + base->global_requests_waiting = 0; + + base->global_timeout.tv_sec = 5; + base->global_timeout.tv_usec = 0; + base->global_max_reissues = 1; + base->global_max_retransmits = 3; + base->global_max_nameserver_timeout = 3; + base->global_search_state = NULL; + base->global_randomize_case = 1; + base->global_getaddrinfo_allow_skew.tv_sec = 3; + base->global_getaddrinfo_allow_skew.tv_usec = 0; + base->global_nameserver_probe_initial_timeout.tv_sec = 10; + base->global_nameserver_probe_initial_timeout.tv_usec = 0; + + TAILQ_INIT(&base->hostsdb); + + if (initialize_nameservers) { + int r; +#ifdef WIN32 + r = evdns_base_config_windows_nameservers(base); +#else + r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf"); +#endif + if (r == -1) { + evdns_base_free_and_unlock(base, 0); + return NULL; + } + } + EVDNS_UNLOCK(base); + return base; +} + +int +evdns_init(void) +{ + struct evdns_base *base = evdns_base_new(NULL, 1); + if (base) { + current_base = base; + return 0; + } else { + return -1; + } +} + +const char * +evdns_err_to_string(int err) +{ + switch (err) { + case DNS_ERR_NONE: return "no error"; + case DNS_ERR_FORMAT: return "misformatted query"; + case DNS_ERR_SERVERFAILED: return "server failed"; + case DNS_ERR_NOTEXIST: return "name does not exist"; + case DNS_ERR_NOTIMPL: return "query not implemented"; + case DNS_ERR_REFUSED: return "refused"; + + case DNS_ERR_TRUNCATED: return "reply truncated or ill-formed"; + case DNS_ERR_UNKNOWN: return "unknown"; + case DNS_ERR_TIMEOUT: return "request timed out"; + case DNS_ERR_SHUTDOWN: return "dns subsystem shut down"; + case DNS_ERR_CANCEL: return "dns request canceled"; + case DNS_ERR_NODATA: return "no records in the reply"; + default: return "[Unknown error code]"; + } +} + +static void +evdns_nameserver_free(struct nameserver *server) +{ + if (server->socket >= 0) + evutil_closesocket(server->socket); + (void) event_del(&server->event); + event_debug_unassign(&server->event); + if (server->state == 0) + (void) event_del(&server->timeout_event); + event_debug_unassign(&server->timeout_event); + mm_free(server); +} + +static void +evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests) +{ + struct nameserver *server, *server_next; + struct search_domain *dom, *dom_next; + int i; + + /* Requires that we hold the lock. */ + + /* TODO(nickm) we might need to refcount here. */ + + for (i = 0; i < base->n_req_heads; ++i) { + while (base->req_heads[i]) { + if (fail_requests) + reply_schedule_callback(base->req_heads[i], 0, DNS_ERR_SHUTDOWN, NULL); + request_finished(base->req_heads[i], &REQ_HEAD(base, base->req_heads[i]->trans_id), 1); + } + } + while (base->req_waiting_head) { + if (fail_requests) + reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL); + request_finished(base->req_waiting_head, &base->req_waiting_head, 1); + } + base->global_requests_inflight = base->global_requests_waiting = 0; + + for (server = base->server_head; server; server = server_next) { + server_next = server->next; + evdns_nameserver_free(server); + if (server_next == base->server_head) + break; + } + base->server_head = NULL; + base->global_good_nameservers = 0; + + if (base->global_search_state) { + for (dom = base->global_search_state->head; dom; dom = dom_next) { + dom_next = dom->next; + mm_free(dom); + } + mm_free(base->global_search_state); + base->global_search_state = NULL; + } + + { + struct hosts_entry *victim; + while ((victim = TAILQ_FIRST(&base->hostsdb))) { + TAILQ_REMOVE(&base->hostsdb, victim, next); + mm_free(victim); + } + } + + mm_free(base->req_heads); + + EVDNS_UNLOCK(base); + EVTHREAD_FREE_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + + mm_free(base); +} + +void +evdns_base_free(struct evdns_base *base, int fail_requests) +{ + EVDNS_LOCK(base); + evdns_base_free_and_unlock(base, fail_requests); +} + +void +evdns_shutdown(int fail_requests) +{ + if (current_base) { + struct evdns_base *b = current_base; + current_base = NULL; + evdns_base_free(b, fail_requests); + } + evdns_log_fn = NULL; +} + +static int +evdns_base_parse_hosts_line(struct evdns_base *base, char *line) +{ + char *strtok_state; + static const char *const delims = " \t"; + char *const addr = strtok_r(line, delims, &strtok_state); + char *hostname, *hash; + struct sockaddr_storage ss; + int socklen = sizeof(ss); + ASSERT_LOCKED(base); + +#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) + + if (!addr || *addr == '#') + return 0; + + memset(&ss, 0, sizeof(ss)); + if (evutil_parse_sockaddr_port(addr, (struct sockaddr*)&ss, &socklen)<0) + return -1; + if (socklen > (int)sizeof(struct sockaddr_in6)) + return -1; + + if (sockaddr_getport((struct sockaddr*)&ss)) + return -1; + + while ((hostname = NEXT_TOKEN)) { + struct hosts_entry *he; + size_t namelen; + if ((hash = strchr(hostname, '#'))) { + if (hash == hostname) + return 0; + *hash = '\0'; + } + + namelen = strlen(hostname); + + he = mm_calloc(1, sizeof(struct hosts_entry)+namelen); + if (!he) + return -1; + EVUTIL_ASSERT(socklen <= (int)sizeof(he->addr)); + memcpy(&he->addr, &ss, socklen); + memcpy(he->hostname, hostname, namelen+1); + he->addrlen = socklen; + + TAILQ_INSERT_TAIL(&base->hostsdb, he, next); + + if (hash) + return 0; + } + + return 0; +#undef NEXT_TOKEN +} + +static int +evdns_base_load_hosts_impl(struct evdns_base *base, const char *hosts_fname) +{ + char *str=NULL, *cp, *eol; + size_t len; + int err=0; + + ASSERT_LOCKED(base); + + if (hosts_fname == NULL || + (err = evutil_read_file(hosts_fname, &str, &len, 0)) < 0) { + char tmp[64]; + strlcpy(tmp, "127.0.0.1 localhost", sizeof(tmp)); + evdns_base_parse_hosts_line(base, tmp); + strlcpy(tmp, "::1 localhost", sizeof(tmp)); + evdns_base_parse_hosts_line(base, tmp); + return err ? -1 : 0; + } + + /* This will break early if there is a NUL in the hosts file. + * Probably not a problem.*/ + cp = str; + for (;;) { + eol = strchr(cp, '\n'); + + if (eol) { + *eol = '\0'; + evdns_base_parse_hosts_line(base, cp); + cp = eol+1; + } else { + evdns_base_parse_hosts_line(base, cp); + break; + } + } + + mm_free(str); + return 0; +} + +int +evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname) +{ + int res; + if (!base) + base = current_base; + EVDNS_LOCK(base); + res = evdns_base_load_hosts_impl(base, hosts_fname); + EVDNS_UNLOCK(base); + return res; +} + +/* A single request for a getaddrinfo, either v4 or v6. */ +struct getaddrinfo_subrequest { + struct evdns_request *r; + ev_uint32_t type; +}; + +/* State data used to implement an in-progress getaddrinfo. */ +struct evdns_getaddrinfo_request { + struct evdns_base *evdns_base; + /* Copy of the modified 'hints' data that we'll use to build + * answers. */ + struct evutil_addrinfo hints; + /* The callback to invoke when we're done */ + evdns_getaddrinfo_cb user_cb; + /* User-supplied data to give to the callback. */ + void *user_data; + /* The port to use when building sockaddrs. */ + ev_uint16_t port; + /* The sub_request for an A record (if any) */ + struct getaddrinfo_subrequest ipv4_request; + /* The sub_request for an AAAA record (if any) */ + struct getaddrinfo_subrequest ipv6_request; + + /* The cname result that we were told (if any) */ + char *cname_result; + + /* If we have one request answered and one request still inflight, + * then this field holds the answer from the first request... */ + struct evutil_addrinfo *pending_result; + /* And this event is a timeout that will tell us to cancel the second + * request if it's taking a long time. */ + struct event timeout; + + /* And this field holds the error code from the first request... */ + int pending_error; + /* If this is set, the user canceled this request. */ + unsigned user_canceled : 1; + /* If this is set, the user can no longer cancel this request; we're + * just waiting for the free. */ + unsigned request_done : 1; +}; + +/* Convert an evdns errors to the equivalent getaddrinfo error. */ +static int +evdns_err_to_getaddrinfo_err(int e1) +{ + /* XXX Do this better! */ + if (e1 == DNS_ERR_NONE) + return 0; + else if (e1 == DNS_ERR_NOTEXIST) + return EVUTIL_EAI_NONAME; + else + return EVUTIL_EAI_FAIL; +} + +/* Return the more informative of two getaddrinfo errors. */ +static int +getaddrinfo_merge_err(int e1, int e2) +{ + /* XXXX be cleverer here. */ + if (e1 == 0) + return e2; + else + return e1; +} + +static void +free_getaddrinfo_request(struct evdns_getaddrinfo_request *data) +{ + /* DO NOT CALL this if either of the requests is pending. Only once + * both callbacks have been invoked is it safe to free the request */ + if (data->pending_result) + evutil_freeaddrinfo(data->pending_result); + if (data->cname_result) + mm_free(data->cname_result); + event_del(&data->timeout); + mm_free(data); + return; +} + +static void +add_cname_to_reply(struct evdns_getaddrinfo_request *data, + struct evutil_addrinfo *ai) +{ + if (data->cname_result && ai) { + ai->ai_canonname = data->cname_result; + data->cname_result = NULL; + } +} + +/* Callback: invoked when one request in a mixed-format A/AAAA getaddrinfo + * request has finished, but the other one took too long to answer. Pass + * along the answer we got, and cancel the other request. + */ +static void +evdns_getaddrinfo_timeout_cb(evutil_socket_t fd, short what, void *ptr) +{ + int v4_timedout = 0, v6_timedout = 0; + struct evdns_getaddrinfo_request *data = ptr; + + /* Cancel any pending requests, and note which one */ + if (data->ipv4_request.r) { + evdns_cancel_request(NULL, data->ipv4_request.r); + v4_timedout = 1; + EVDNS_LOCK(data->evdns_base); + ++data->evdns_base->getaddrinfo_ipv4_timeouts; + EVDNS_UNLOCK(data->evdns_base); + } + if (data->ipv6_request.r) { + evdns_cancel_request(NULL, data->ipv6_request.r); + v6_timedout = 1; + EVDNS_LOCK(data->evdns_base); + ++data->evdns_base->getaddrinfo_ipv6_timeouts; + EVDNS_UNLOCK(data->evdns_base); + } + + /* We only use this timeout callback when we have an answer for + * one address. */ + EVUTIL_ASSERT(!v4_timedout || !v6_timedout); + + /* Report the outcome of the other request that didn't time out. */ + if (data->pending_result) { + add_cname_to_reply(data, data->pending_result); + data->user_cb(0, data->pending_result, data->user_data); + data->pending_result = NULL; + } else { + int e = data->pending_error; + if (!e) + e = EVUTIL_EAI_AGAIN; + data->user_cb(e, NULL, data->user_data); + } + + if (!v4_timedout && !v6_timedout) { + /* should be impossible? XXXX */ + free_getaddrinfo_request(data); + } +} + +static int +evdns_getaddrinfo_set_timeout(struct evdns_base *evdns_base, + struct evdns_getaddrinfo_request *data) +{ + return event_add(&data->timeout, &evdns_base->global_getaddrinfo_allow_skew); +} + +static inline int +evdns_result_is_answer(int result) +{ + return (result != DNS_ERR_NOTIMPL && result != DNS_ERR_REFUSED && + result != DNS_ERR_SERVERFAILED && result != DNS_ERR_CANCEL); +} + +static void +evdns_getaddrinfo_gotresolve(int result, char type, int count, + int ttl, void *addresses, void *arg) +{ + int i; + struct getaddrinfo_subrequest *req = arg; + struct getaddrinfo_subrequest *other_req; + struct evdns_getaddrinfo_request *data; + + struct evutil_addrinfo *res; + + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr *sa; + int socklen, addrlen; + void *addrp; + int err; + int user_canceled; + + EVUTIL_ASSERT(req->type == DNS_IPv4_A || req->type == DNS_IPv6_AAAA); + if (req->type == DNS_IPv4_A) { + data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv4_request); + other_req = &data->ipv6_request; + } else { + data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv6_request); + other_req = &data->ipv4_request; + } + + EVDNS_LOCK(data->evdns_base); + if (evdns_result_is_answer(result)) { + if (req->type == DNS_IPv4_A) + ++data->evdns_base->getaddrinfo_ipv4_answered; + else + ++data->evdns_base->getaddrinfo_ipv6_answered; + } + user_canceled = data->user_canceled; + if (other_req->r == NULL) + data->request_done = 1; + EVDNS_UNLOCK(data->evdns_base); + + req->r = NULL; + + if (result == DNS_ERR_CANCEL && ! user_canceled) { + /* Internal cancel request from timeout or internal error. + * we already answered the user. */ + if (other_req->r == NULL) + free_getaddrinfo_request(data); + return; + } + + if (result == DNS_ERR_NONE) { + if (count == 0) + err = EVUTIL_EAI_NODATA; + else + err = 0; + } else { + err = evdns_err_to_getaddrinfo_err(result); + } + + if (err) { + /* Looks like we got an error. */ + if (other_req->r) { + /* The other request is still working; maybe it will + * succeed. */ + /* XXXX handle failure from set_timeout */ + evdns_getaddrinfo_set_timeout(data->evdns_base, data); + data->pending_error = err; + return; + } + + if (user_canceled) { + data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); + } else if (data->pending_result) { + /* If we have an answer waiting, and we weren't + * canceled, ignore this error. */ + add_cname_to_reply(data, data->pending_result); + data->user_cb(0, data->pending_result, data->user_data); + data->pending_result = NULL; + } else { + if (data->pending_error) + err = getaddrinfo_merge_err(err, + data->pending_error); + data->user_cb(err, NULL, data->user_data); + } + free_getaddrinfo_request(data); + return; + } else if (user_canceled) { + if (other_req->r) { + /* The other request is still working; let it hit this + * callback with EVUTIL_EAI_CANCEL callback and report + * the failure. */ + return; + } + data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); + free_getaddrinfo_request(data); + return; + } + + /* Looks like we got some answers. We should turn them into addrinfos + * and then either queue those or return them all. */ + EVUTIL_ASSERT(type == DNS_IPv4_A || type == DNS_IPv6_AAAA); + + if (type == DNS_IPv4_A) { + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(data->port); + + sa = (struct sockaddr *)&sin; + socklen = sizeof(sin); + addrlen = 4; + addrp = &sin.sin_addr.s_addr; + } else { + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(data->port); + + sa = (struct sockaddr *)&sin6; + socklen = sizeof(sin6); + addrlen = 16; + addrp = &sin6.sin6_addr.s6_addr; + } + + res = NULL; + for (i=0; i < count; ++i) { + struct evutil_addrinfo *ai; + memcpy(addrp, ((char*)addresses)+i*addrlen, addrlen); + ai = evutil_new_addrinfo(sa, socklen, &data->hints); + if (!ai) { + if (other_req->r) { + evdns_cancel_request(NULL, other_req->r); + } + data->user_cb(EVUTIL_EAI_MEMORY, NULL, data->user_data); + if (res) + evutil_freeaddrinfo(res); + + if (other_req->r == NULL) + free_getaddrinfo_request(data); + return; + } + res = evutil_addrinfo_append(res, ai); + } + + if (other_req->r) { + /* The other request is still in progress; wait for it */ + /* XXXX handle failure from set_timeout */ + evdns_getaddrinfo_set_timeout(data->evdns_base, data); + data->pending_result = res; + return; + } else { + /* The other request is done or never started; append its + * results (if any) and return them. */ + if (data->pending_result) { + if (req->type == DNS_IPv4_A) + res = evutil_addrinfo_append(res, + data->pending_result); + else + res = evutil_addrinfo_append( + data->pending_result, res); + data->pending_result = NULL; + } + + /* Call the user callback. */ + add_cname_to_reply(data, res); + data->user_cb(0, res, data->user_data); + + /* Free data. */ + free_getaddrinfo_request(data); + } +} + +static struct hosts_entry * +find_hosts_entry(struct evdns_base *base, const char *hostname, + struct hosts_entry *find_after) +{ + struct hosts_entry *e; + + if (find_after) + e = TAILQ_NEXT(find_after, next); + else + e = TAILQ_FIRST(&base->hostsdb); + + for (; e; e = TAILQ_NEXT(e, next)) { + if (!evutil_ascii_strcasecmp(e->hostname, hostname)) + return e; + } + return NULL; +} + +static int +evdns_getaddrinfo_fromhosts(struct evdns_base *base, + const char *nodename, struct evutil_addrinfo *hints, ev_uint16_t port, + struct evutil_addrinfo **res) +{ + int n_found = 0; + struct hosts_entry *e; + struct evutil_addrinfo *ai=NULL; + int f = hints->ai_family; + + EVDNS_LOCK(base); + for (e = find_hosts_entry(base, nodename, NULL); e; + e = find_hosts_entry(base, nodename, e)) { + struct evutil_addrinfo *ai_new; + ++n_found; + if ((e->addr.sa.sa_family == AF_INET && f == PF_INET6) || + (e->addr.sa.sa_family == AF_INET6 && f == PF_INET)) + continue; + ai_new = evutil_new_addrinfo(&e->addr.sa, e->addrlen, hints); + if (!ai_new) { + n_found = 0; + goto out; + } + sockaddr_setport(ai_new->ai_addr, port); + ai = evutil_addrinfo_append(ai, ai_new); + } + EVDNS_UNLOCK(base); +out: + if (n_found) { + /* Note that we return an empty answer if we found entries for + * this hostname but none were of the right address type. */ + *res = ai; + return 0; + } else { + if (ai) + evutil_freeaddrinfo(ai); + return -1; + } +} + +struct evdns_getaddrinfo_request * +evdns_getaddrinfo(struct evdns_base *dns_base, + const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, + evdns_getaddrinfo_cb cb, void *arg) +{ + struct evdns_getaddrinfo_request *data; + struct evutil_addrinfo hints; + struct evutil_addrinfo *res = NULL; + int err; + int port = 0; + int want_cname = 0; + + if (!dns_base) { + dns_base = current_base; + if (!dns_base) { + log(EVDNS_LOG_WARN, + "Call to getaddrinfo_async with no " + "evdns_base configured."); + cb(EVUTIL_EAI_FAIL, NULL, arg); /* ??? better error? */ + return NULL; + } + } + + /* If we _must_ answer this immediately, do so. */ + if ((hints_in && (hints_in->ai_flags & EVUTIL_AI_NUMERICHOST))) { + res = NULL; + err = evutil_getaddrinfo(nodename, servname, hints_in, &res); + cb(err, res, arg); + return NULL; + } + + if (hints_in) { + memcpy(&hints, hints_in, sizeof(hints)); + } else { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + } + + evutil_adjust_hints_for_addrconfig(&hints); + + /* Now try to see if we _can_ answer immediately. */ + /* (It would be nice to do this by calling getaddrinfo directly, with + * AI_NUMERICHOST, on plaforms that have it, but we can't: there isn't + * a reliable way to distinguish the "that wasn't a numeric host!" case + * from any other EAI_NONAME cases.) */ + err = evutil_getaddrinfo_common(nodename, servname, &hints, &res, &port); + if (err != EVUTIL_EAI_NEED_RESOLVE) { + cb(err, res, arg); + return NULL; + } + + /* If there is an entry in the hosts file, we should give it now. */ + if (!evdns_getaddrinfo_fromhosts(dns_base, nodename, &hints, port, &res)) { + cb(0, res, arg); + return NULL; + } + + /* Okay, things are serious now. We're going to need to actually + * launch a request. + */ + data = mm_calloc(1,sizeof(struct evdns_getaddrinfo_request)); + if (!data) { + cb(EVUTIL_EAI_MEMORY, NULL, arg); + return NULL; + } + + memcpy(&data->hints, &hints, sizeof(data->hints)); + data->port = (ev_uint16_t)port; + data->ipv4_request.type = DNS_IPv4_A; + data->ipv6_request.type = DNS_IPv6_AAAA; + data->user_cb = cb; + data->user_data = arg; + data->evdns_base = dns_base; + + want_cname = (hints.ai_flags & EVUTIL_AI_CANONNAME); + + /* If we are asked for a PF_UNSPEC address, we launch two requests in + * parallel: one for an A address and one for an AAAA address. We + * can't send just one request, since many servers only answer one + * question per DNS request. + * + * Once we have the answer to one request, we allow for a short + * timeout before we report it, to see if the other one arrives. If + * they both show up in time, then we report both the answers. + * + * If too many addresses of one type time out or fail, we should stop + * launching those requests. (XXX we don't do that yet.) + */ + + if (hints.ai_family != PF_INET6) { + log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p", + nodename, &data->ipv4_request); + + data->ipv4_request.r = evdns_base_resolve_ipv4(dns_base, + nodename, 0, evdns_getaddrinfo_gotresolve, + &data->ipv4_request); + if (want_cname) + data->ipv4_request.r->current_req->put_cname_in_ptr = + &data->cname_result; + } + if (hints.ai_family != PF_INET) { + log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv6 as %p", + nodename, &data->ipv6_request); + + data->ipv6_request.r = evdns_base_resolve_ipv6(dns_base, + nodename, 0, evdns_getaddrinfo_gotresolve, + &data->ipv6_request); + if (want_cname) + data->ipv6_request.r->current_req->put_cname_in_ptr = + &data->cname_result; + } + + evtimer_assign(&data->timeout, dns_base->event_base, + evdns_getaddrinfo_timeout_cb, data); + + if (data->ipv4_request.r || data->ipv6_request.r) { + return data; + } else { + mm_free(data); + cb(EVUTIL_EAI_FAIL, NULL, arg); + return NULL; + } +} + +void +evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *data) +{ + EVDNS_LOCK(data->evdns_base); + if (data->request_done) { + EVDNS_UNLOCK(data->evdns_base); + return; + } + event_del(&data->timeout); + data->user_canceled = 1; + if (data->ipv4_request.r) + evdns_cancel_request(data->evdns_base, data->ipv4_request.r); + if (data->ipv6_request.r) + evdns_cancel_request(data->evdns_base, data->ipv6_request.r); + EVDNS_UNLOCK(data->evdns_base); +} diff --git a/libevent/evdns.h b/libevent/evdns.h new file mode 100644 index 0000000..513f9b7 --- /dev/null +++ b/libevent/evdns.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVDNS_H_ +#define _EVDNS_H_ + +/** @file evdns.h + + A dns subsystem for Libevent. + + The header is deprecated in Libevent 2.0 and later; please + use instead. Depending on what functionality you + need, you may also want to include more of the other + headers. + */ + +#include +#include +#include +#include + +#endif /* _EVDNS_H_ */ diff --git a/libevent/event-internal.h b/libevent/event-internal.h new file mode 100644 index 0000000..1798b70 --- /dev/null +++ b/libevent/event-internal.h @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT_INTERNAL_H_ +#define _EVENT_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event2/event-config.h" +#include +#include +#include "event2/event_struct.h" +#include "minheap-internal.h" +#include "evsignal-internal.h" +#include "mm-internal.h" +#include "defer-internal.h" + +/* map union members back */ + +/* mutually exclusive */ +#define ev_signal_next _ev.ev_signal.ev_signal_next +#define ev_io_next _ev.ev_io.ev_io_next +#define ev_io_timeout _ev.ev_io.ev_timeout + +/* used only by signals */ +#define ev_ncalls _ev.ev_signal.ev_ncalls +#define ev_pncalls _ev.ev_signal.ev_pncalls + +/* Possible values for ev_closure in struct event. */ +#define EV_CLOSURE_NONE 0 +#define EV_CLOSURE_SIGNAL 1 +#define EV_CLOSURE_PERSIST 2 + +/** Structure to define the backend of a given event_base. */ +struct eventop { + /** The name of this backend. */ + const char *name; + /** Function to set up an event_base to use this backend. It should + * create a new structure holding whatever information is needed to + * run the backend, and return it. The returned pointer will get + * stored by event_init into the event_base.evbase field. On failure, + * this function should return NULL. */ + void *(*init)(struct event_base *); + /** Enable reading/writing on a given fd or signal. 'events' will be + * the events that we're trying to enable: one or more of EV_READ, + * EV_WRITE, EV_SIGNAL, and EV_ET. 'old' will be those events that + * were enabled on this fd previously. 'fdinfo' will be a structure + * associated with the fd by the evmap; its size is defined by the + * fdinfo field below. It will be set to 0 the first time the fd is + * added. The function should return 0 on success and -1 on error. + */ + int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo); + /** As "add", except 'events' contains the events we mean to disable. */ + int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo); + /** Function to implement the core of an event loop. It must see which + added events are ready, and cause event_active to be called for each + active event (usually via event_io_active or such). It should + return 0 on success and -1 on error. + */ + int (*dispatch)(struct event_base *, struct timeval *); + /** Function to clean up and free our data from the event_base. */ + void (*dealloc)(struct event_base *); + /** Flag: set if we need to reinitialize the event base after we fork. + */ + int need_reinit; + /** Bit-array of supported event_method_features that this backend can + * provide. */ + enum event_method_feature features; + /** Length of the extra information we should record for each fd that + has one or more active events. This information is recorded + as part of the evmap entry for each fd, and passed as an argument + to the add and del functions above. + */ + size_t fdinfo_len; +}; + +#ifdef WIN32 +/* If we're on win32, then file descriptors are not nice low densely packed + integers. Instead, they are pointer-like windows handles, and we want to + use a hashtable instead of an array to map fds to events. +*/ +#define EVMAP_USE_HT +#endif + +/* #define HT_CACHE_HASH_VALS */ + +#ifdef EVMAP_USE_HT +#include "ht-internal.h" +struct event_map_entry; +HT_HEAD(event_io_map, event_map_entry); +#else +#define event_io_map event_signal_map +#endif + +/* Used to map signal numbers to a list of events. If EVMAP_USE_HT is not + defined, this structure is also used as event_io_map, which maps fds to a + list of events. +*/ +struct event_signal_map { + /* An array of evmap_io * or of evmap_signal *; empty entries are + * set to NULL. */ + void **entries; + /* The number of entries available in entries */ + int nentries; +}; + +/* A list of events waiting on a given 'common' timeout value. Ordinarily, + * events waiting for a timeout wait on a minheap. Sometimes, however, a + * queue can be faster. + **/ +struct common_timeout_list { + /* List of events currently waiting in the queue. */ + struct event_list events; + /* 'magic' timeval used to indicate the duration of events in this + * queue. */ + struct timeval duration; + /* Event that triggers whenever one of the events in the queue is + * ready to activate */ + struct event timeout_event; + /* The event_base that this timeout list is part of */ + struct event_base *base; +}; + +/** Mask used to get the real tv_usec value from a common timeout. */ +#define COMMON_TIMEOUT_MICROSECONDS_MASK 0x000fffff + +struct event_change; + +/* List of 'changes' since the last call to eventop.dispatch. Only maintained + * if the backend is using changesets. */ +struct event_changelist { + struct event_change *changes; + int n_changes; + int changes_size; +}; + +#ifndef _EVENT_DISABLE_DEBUG_MODE +/* Global internal flag: set to one if debug mode is on. */ +extern int _event_debug_mode_on; +#define EVENT_DEBUG_MODE_IS_ON() (_event_debug_mode_on) +#else +#define EVENT_DEBUG_MODE_IS_ON() (0) +#endif + +struct event_base { + /** Function pointers and other data to describe this event_base's + * backend. */ + const struct eventop *evsel; + /** Pointer to backend-specific data. */ + void *evbase; + + /** List of changes to tell backend about at next dispatch. Only used + * by the O(1) backends. */ + struct event_changelist changelist; + + /** Function pointers used to describe the backend that this event_base + * uses for signals */ + const struct eventop *evsigsel; + /** Data to implement the common signal handelr code. */ + struct evsig_info sig; + + /** Number of virtual events */ + int virtual_event_count; + /** Number of total events added to this event_base */ + int event_count; + /** Number of total events active in this event_base */ + int event_count_active; + + /** Set if we should terminate the loop once we're done processing + * events. */ + int event_gotterm; + /** Set if we should terminate the loop immediately */ + int event_break; + + /** Set if we're running the event_base_loop function, to prevent + * reentrant invocation. */ + int running_loop; + + /* Active event management. */ + /** An array of nactivequeues queues for active events (ones that + * have triggered, and whose callbacks need to be called). Low + * priority numbers are more important, and stall higher ones. + */ + struct event_list *activequeues; + /** The length of the activequeues array */ + int nactivequeues; + + /* common timeout logic */ + + /** An array of common_timeout_list* for all of the common timeout + * values we know. */ + struct common_timeout_list **common_timeout_queues; + /** The number of entries used in common_timeout_queues */ + int n_common_timeouts; + /** The total size of common_timeout_queues. */ + int n_common_timeouts_allocated; + + /** List of defered_cb that are active. We run these after the active + * events. */ + struct deferred_cb_queue defer_queue; + + /** Mapping from file descriptors to enabled (added) events */ + struct event_io_map io; + + /** Mapping from signal numbers to enabled (added) events. */ + struct event_signal_map sigmap; + + /** All events that have been enabled (added) in this event_base */ + struct event_list eventqueue; + + /** Stored timeval; used to detect when time is running backwards. */ + struct timeval event_tv; + + /** Priority queue of events with timeouts. */ + struct min_heap timeheap; + + /** Stored timeval: used to avoid calling gettimeofday/clock_gettime + * too often. */ + struct timeval tv_cache; + +#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + /** Difference between internal time (maybe from clock_gettime) and + * gettimeofday. */ + struct timeval tv_clock_diff; + /** Second in which we last updated tv_clock_diff, in monotonic time. */ + time_t last_updated_clock_diff; +#endif + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + /* threading support */ + /** The thread currently running the event_loop for this base */ + unsigned long th_owner_id; + /** A lock to prevent conflicting accesses to this event_base */ + void *th_base_lock; + /** The event whose callback is executing right now */ + struct event *current_event; + /** A condition that gets signalled when we're done processing an + * event with waiters on it. */ + void *current_event_cond; + /** Number of threads blocking on current_event_cond. */ + int current_event_waiters; +#endif + +#ifdef WIN32 + /** IOCP support structure, if IOCP is enabled. */ + struct event_iocp_port *iocp; +#endif + + /** Flags that this base was configured with */ + enum event_base_config_flag flags; + + /* Notify main thread to wake up break, etc. */ + /** True if the base already has a pending notify, and we don't need + * to add any more. */ + int is_notify_pending; + /** A socketpair used by some th_notify functions to wake up the main + * thread. */ + evutil_socket_t th_notify_fd[2]; + /** An event used by some th_notify functions to wake up the main + * thread. */ + struct event th_notify; + /** A function used to wake up the main thread from another thread. */ + int (*th_notify_fn)(struct event_base *base); +}; + +struct event_config_entry { + TAILQ_ENTRY(event_config_entry) next; + + const char *avoid_method; +}; + +/** Internal structure: describes the configuration we want for an event_base + * that we're about to allocate. */ +struct event_config { + TAILQ_HEAD(event_configq, event_config_entry) entries; + + int n_cpus_hint; + enum event_method_feature require_features; + enum event_base_config_flag flags; +}; + +/* Internal use only: Functions that might be missing from */ +#if defined(_EVENT_HAVE_SYS_QUEUE_H) && !defined(_EVENT_HAVE_TAILQFOREACH) +#ifndef TAILQ_FIRST +#define TAILQ_FIRST(head) ((head)->tqh_first) +#endif +#ifndef TAILQ_END +#define TAILQ_END(head) NULL +#endif +#ifndef TAILQ_NEXT +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#endif + +#ifndef TAILQ_FOREACH +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) +#endif + +#ifndef TAILQ_INSERT_BEFORE +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) +#endif +#endif /* TAILQ_FOREACH */ + +#define N_ACTIVE_CALLBACKS(base) \ + ((base)->event_count_active + (base)->defer_queue.active_count) + +int _evsig_set_handler(struct event_base *base, int evsignal, + void (*fn)(int)); +int _evsig_restore_handler(struct event_base *base, int evsignal); + + +void event_active_nolock(struct event *ev, int res, short count); + +/* FIXME document. */ +void event_base_add_virtual(struct event_base *base); +void event_base_del_virtual(struct event_base *base); + +/** For debugging: unless assertions are disabled, verify the referential + integrity of the internal data structures of 'base'. This operation can + be expensive. + + Returns on success; aborts on failure. +*/ +void event_base_assert_ok(struct event_base *base); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT_INTERNAL_H_ */ + diff --git a/libevent/event.c b/libevent/event.c new file mode 100644 index 0000000..f13cdcf --- /dev/null +++ b/libevent/event.c @@ -0,0 +1,2897 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#ifdef WIN32 +#include +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#endif +#include +#if !defined(WIN32) && defined(_EVENT_HAVE_SYS_TIME_H) +#include +#endif +#include +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_EVENTFD_H +#include +#endif +#include +#include +#include +#include +#include + +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/event_compat.h" +#include "event-internal.h" +#include "defer-internal.h" +#include "evthread-internal.h" +#include "event2/thread.h" +#include "event2/util.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "iocp-internal.h" +#include "changelist-internal.h" +#include "ht-internal.h" +#include "util-internal.h" + +#ifdef _EVENT_HAVE_EVENT_PORTS +extern const struct eventop evportops; +#endif +#ifdef _EVENT_HAVE_SELECT +extern const struct eventop selectops; +#endif +#ifdef _EVENT_HAVE_POLL +extern const struct eventop pollops; +#endif +#ifdef _EVENT_HAVE_EPOLL +extern const struct eventop epollops; +#endif +#ifdef _EVENT_HAVE_WORKING_KQUEUE +extern const struct eventop kqops; +#endif +#ifdef _EVENT_HAVE_DEVPOLL +extern const struct eventop devpollops; +#endif +#ifdef WIN32 +extern const struct eventop win32ops; +#endif + +/* Array of backends in order of preference. */ +static const struct eventop *eventops[] = { +#ifdef _EVENT_HAVE_EVENT_PORTS + &evportops, +#endif +#ifdef _EVENT_HAVE_WORKING_KQUEUE + &kqops, +#endif +#ifdef _EVENT_HAVE_EPOLL + &epollops, +#endif +#ifdef _EVENT_HAVE_DEVPOLL + &devpollops, +#endif +#ifdef _EVENT_HAVE_POLL + &pollops, +#endif +#ifdef _EVENT_HAVE_SELECT + &selectops, +#endif +#ifdef WIN32 + &win32ops, +#endif + NULL +}; + +/* Global state; deprecated */ +struct event_base *event_global_current_base_ = NULL; +#define current_base event_global_current_base_ + +/* Global state */ + +static int use_monotonic; + +/* Prototypes */ +static inline int event_add_internal(struct event *ev, + const struct timeval *tv, int tv_is_absolute); +static inline int event_del_internal(struct event *ev); + +static void event_queue_insert(struct event_base *, struct event *, int); +static void event_queue_remove(struct event_base *, struct event *, int); +static int event_haveevents(struct event_base *); + +static int event_process_active(struct event_base *); + +static int timeout_next(struct event_base *, struct timeval **); +static void timeout_process(struct event_base *); +static void timeout_correct(struct event_base *, struct timeval *); + +static inline void event_signal_closure(struct event_base *, struct event *ev); +static inline void event_persist_closure(struct event_base *, struct event *ev); + +static int evthread_notify_base(struct event_base *base); + +#ifndef _EVENT_DISABLE_DEBUG_MODE +/* These functions implement a hashtable of which 'struct event *' structures + * have been setup or added. We don't want to trust the content of the struct + * event itself, since we're trying to work through cases where an event gets + * clobbered or freed. Instead, we keep a hashtable indexed by the pointer. + */ + +struct event_debug_entry { + HT_ENTRY(event_debug_entry) node; + const struct event *ptr; + unsigned added : 1; +}; + +static inline unsigned +hash_debug_entry(const struct event_debug_entry *e) +{ + /* We need to do this silliness to convince compilers that we + * honestly mean to cast e->ptr to an integer, and discard any + * part of it that doesn't fit in an unsigned. + */ + unsigned u = (unsigned) ((ev_uintptr_t) e->ptr); + /* Our hashtable implementation is pretty sensitive to low bits, + * and every struct event is over 64 bytes in size, so we can + * just say >>6. */ + return (u >> 6); +} + +static inline int +eq_debug_entry(const struct event_debug_entry *a, + const struct event_debug_entry *b) +{ + return a->ptr == b->ptr; +} + +int _event_debug_mode_on = 0; +/* Set if it's too late to enable event_debug_mode. */ +static int event_debug_mode_too_late = 0; +#ifndef _EVENT_DISABLE_THREAD_SUPPORT +static void *_event_debug_map_lock = NULL; +#endif +static HT_HEAD(event_debug_map, event_debug_entry) global_debug_map = + HT_INITIALIZER(); + +HT_PROTOTYPE(event_debug_map, event_debug_entry, node, hash_debug_entry, + eq_debug_entry) +HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry, + eq_debug_entry, 0.5, mm_malloc, mm_realloc, mm_free) + +/* Macro: record that ev is now setup (that is, ready for an add) */ +#define _event_debug_note_setup(ev) do { \ + if (_event_debug_mode_on) { \ + struct event_debug_entry *dent,find; \ + find.ptr = (ev); \ + EVLOCK_LOCK(_event_debug_map_lock, 0); \ + dent = HT_FIND(event_debug_map, &global_debug_map, &find); \ + if (dent) { \ + dent->added = 0; \ + } else { \ + dent = mm_malloc(sizeof(*dent)); \ + if (!dent) \ + event_err(1, \ + "Out of memory in debugging code"); \ + dent->ptr = (ev); \ + dent->added = 0; \ + HT_INSERT(event_debug_map, &global_debug_map, dent); \ + } \ + EVLOCK_UNLOCK(_event_debug_map_lock, 0); \ + } \ + event_debug_mode_too_late = 1; \ + } while (0) +/* Macro: record that ev is no longer setup */ +#define _event_debug_note_teardown(ev) do { \ + if (_event_debug_mode_on) { \ + struct event_debug_entry *dent,find; \ + find.ptr = (ev); \ + EVLOCK_LOCK(_event_debug_map_lock, 0); \ + dent = HT_REMOVE(event_debug_map, &global_debug_map, &find); \ + if (dent) \ + mm_free(dent); \ + EVLOCK_UNLOCK(_event_debug_map_lock, 0); \ + } \ + event_debug_mode_too_late = 1; \ + } while (0) +/* Macro: record that ev is now added */ +#define _event_debug_note_add(ev) do { \ + if (_event_debug_mode_on) { \ + struct event_debug_entry *dent,find; \ + find.ptr = (ev); \ + EVLOCK_LOCK(_event_debug_map_lock, 0); \ + dent = HT_FIND(event_debug_map, &global_debug_map, &find); \ + if (dent) { \ + dent->added = 1; \ + } else { \ + event_errx(_EVENT_ERR_ABORT, \ + "%s: noting an add on a non-setup event %p" \ + " (events: 0x%x, fd: %d, flags: 0x%x)", \ + __func__, (ev), (ev)->ev_events, \ + (ev)->ev_fd, (ev)->ev_flags); \ + } \ + EVLOCK_UNLOCK(_event_debug_map_lock, 0); \ + } \ + event_debug_mode_too_late = 1; \ + } while (0) +/* Macro: record that ev is no longer added */ +#define _event_debug_note_del(ev) do { \ + if (_event_debug_mode_on) { \ + struct event_debug_entry *dent,find; \ + find.ptr = (ev); \ + EVLOCK_LOCK(_event_debug_map_lock, 0); \ + dent = HT_FIND(event_debug_map, &global_debug_map, &find); \ + if (dent) { \ + dent->added = 0; \ + } else { \ + event_errx(_EVENT_ERR_ABORT, \ + "%s: noting a del on a non-setup event %p" \ + " (events: 0x%x, fd: %d, flags: 0x%x)", \ + __func__, (ev), (ev)->ev_events, \ + (ev)->ev_fd, (ev)->ev_flags); \ + } \ + EVLOCK_UNLOCK(_event_debug_map_lock, 0); \ + } \ + event_debug_mode_too_late = 1; \ + } while (0) +/* Macro: assert that ev is setup (i.e., okay to add or inspect) */ +#define _event_debug_assert_is_setup(ev) do { \ + if (_event_debug_mode_on) { \ + struct event_debug_entry *dent,find; \ + find.ptr = (ev); \ + EVLOCK_LOCK(_event_debug_map_lock, 0); \ + dent = HT_FIND(event_debug_map, &global_debug_map, &find); \ + if (!dent) { \ + event_errx(_EVENT_ERR_ABORT, \ + "%s called on a non-initialized event %p" \ + " (events: 0x%x, fd: %d, flags: 0x%x)", \ + __func__, (ev), (ev)->ev_events, \ + (ev)->ev_fd, (ev)->ev_flags); \ + } \ + EVLOCK_UNLOCK(_event_debug_map_lock, 0); \ + } \ + } while (0) +/* Macro: assert that ev is not added (i.e., okay to tear down or set + * up again) */ +#define _event_debug_assert_not_added(ev) do { \ + if (_event_debug_mode_on) { \ + struct event_debug_entry *dent,find; \ + find.ptr = (ev); \ + EVLOCK_LOCK(_event_debug_map_lock, 0); \ + dent = HT_FIND(event_debug_map, &global_debug_map, &find); \ + if (dent && dent->added) { \ + event_errx(_EVENT_ERR_ABORT, \ + "%s called on an already added event %p" \ + " (events: 0x%x, fd: %d, flags: 0x%x)", \ + __func__, (ev), (ev)->ev_events, \ + (ev)->ev_fd, (ev)->ev_flags); \ + } \ + EVLOCK_UNLOCK(_event_debug_map_lock, 0); \ + } \ + } while (0) +#else +#define _event_debug_note_setup(ev) \ + ((void)0) +#define _event_debug_note_teardown(ev) \ + ((void)0) +#define _event_debug_note_add(ev) \ + ((void)0) +#define _event_debug_note_del(ev) \ + ((void)0) +#define _event_debug_assert_is_setup(ev) \ + ((void)0) +#define _event_debug_assert_not_added(ev) \ + ((void)0) +#endif + +#define EVENT_BASE_ASSERT_LOCKED(base) \ + EVLOCK_ASSERT_LOCKED((base)->th_base_lock) + +/* The first time this function is called, it sets use_monotonic to 1 + * if we have a clock function that supports monotonic time */ +static void +detect_monotonic(void) +{ +#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + struct timespec ts; + static int use_monotonic_initialized = 0; + + if (use_monotonic_initialized) + return; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + use_monotonic = 1; + + use_monotonic_initialized = 1; +#endif +} + +/* How often (in seconds) do we check for changes in wall clock time relative + * to monotonic time? Set this to -1 for 'never.' */ +#define CLOCK_SYNC_INTERVAL -1 + +/** Set 'tp' to the current time according to 'base'. We must hold the lock + * on 'base'. If there is a cached time, return it. Otherwise, use + * clock_gettime or gettimeofday as appropriate to find out the right time. + * Return 0 on success, -1 on failure. + */ +static int +gettime(struct event_base *base, struct timeval *tp) +{ + EVENT_BASE_ASSERT_LOCKED(base); + + if (base->tv_cache.tv_sec) { + *tp = base->tv_cache; + return (0); + } + +#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + if (use_monotonic) { + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + return (-1); + + tp->tv_sec = ts.tv_sec; + tp->tv_usec = ts.tv_nsec / 1000; + if (base->last_updated_clock_diff + CLOCK_SYNC_INTERVAL + < ts.tv_sec) { + struct timeval tv; + evutil_gettimeofday(&tv,NULL); + evutil_timersub(&tv, tp, &base->tv_clock_diff); + base->last_updated_clock_diff = ts.tv_sec; + } + + return (0); + } +#endif + + return (evutil_gettimeofday(tp, NULL)); +} + +int +event_base_gettimeofday_cached(struct event_base *base, struct timeval *tv) +{ + int r; + if (!base) { + base = current_base; + if (!current_base) + return evutil_gettimeofday(tv, NULL); + } + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + if (base->tv_cache.tv_sec == 0) { + r = evutil_gettimeofday(tv, NULL); + } else { +#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + evutil_timeradd(&base->tv_cache, &base->tv_clock_diff, tv); +#else + *tv = base->tv_cache; +#endif + r = 0; + } + EVBASE_RELEASE_LOCK(base, th_base_lock); + return r; +} + +/** Make 'base' have no current cached time. */ +static inline void +clear_time_cache(struct event_base *base) +{ + base->tv_cache.tv_sec = 0; +} + +/** Replace the cached time in 'base' with the current time. */ +static inline void +update_time_cache(struct event_base *base) +{ + base->tv_cache.tv_sec = 0; + if (!(base->flags & EVENT_BASE_FLAG_NO_CACHE_TIME)) + gettime(base, &base->tv_cache); +} + +struct event_base * +event_init(void) +{ + struct event_base *base = event_base_new_with_config(NULL); + + if (base == NULL) { + event_errx(1, "%s: Unable to construct event_base", __func__); + return NULL; + } + + current_base = base; + + return (base); +} + +struct event_base * +event_base_new(void) +{ + struct event_base *base = NULL; + struct event_config *cfg = event_config_new(); + if (cfg) { + base = event_base_new_with_config(cfg); + event_config_free(cfg); + } + return base; +} + +/** Return true iff 'method' is the name of a method that 'cfg' tells us to + * avoid. */ +static int +event_config_is_avoided_method(const struct event_config *cfg, + const char *method) +{ + struct event_config_entry *entry; + + TAILQ_FOREACH(entry, &cfg->entries, next) { + if (entry->avoid_method != NULL && + strcmp(entry->avoid_method, method) == 0) + return (1); + } + + return (0); +} + +/** Return true iff 'method' is disabled according to the environment. */ +static int +event_is_method_disabled(const char *name) +{ + char environment[64]; + int i; + + evutil_snprintf(environment, sizeof(environment), "EVENT_NO%s", name); + for (i = 8; environment[i] != '\0'; ++i) + environment[i] = EVUTIL_TOUPPER(environment[i]); + /* Note that evutil_getenv() ignores the environment entirely if + * we're setuid */ + return (evutil_getenv(environment) != NULL); +} + +int +event_base_get_features(const struct event_base *base) +{ + return base->evsel->features; +} + +void +event_deferred_cb_queue_init(struct deferred_cb_queue *cb) +{ + memset(cb, 0, sizeof(struct deferred_cb_queue)); + TAILQ_INIT(&cb->deferred_cb_list); +} + +/** Helper for the deferred_cb queue: wake up the event base. */ +static void +notify_base_cbq_callback(struct deferred_cb_queue *cb, void *baseptr) +{ + struct event_base *base = baseptr; + if (EVBASE_NEED_NOTIFY(base)) + evthread_notify_base(base); +} + +struct deferred_cb_queue * +event_base_get_deferred_cb_queue(struct event_base *base) +{ + return base ? &base->defer_queue : NULL; +} + +void +event_enable_debug_mode(void) +{ +#ifndef _EVENT_DISABLE_DEBUG_MODE + if (_event_debug_mode_on) + event_errx(1, "%s was called twice!", __func__); + if (event_debug_mode_too_late) + event_errx(1, "%s must be called *before* creating any events " + "or event_bases",__func__); + + _event_debug_mode_on = 1; + + HT_INIT(event_debug_map, &global_debug_map); +#endif +} + +#if 0 +void +event_disable_debug_mode(void) +{ + struct event_debug_entry **ent, *victim; + + EVLOCK_LOCK(_event_debug_map_lock, 0); + for (ent = HT_START(event_debug_map, &global_debug_map); ent; ) { + victim = *ent; + ent = HT_NEXT_RMV(event_debug_map,&global_debug_map, ent); + mm_free(victim); + } + HT_CLEAR(event_debug_map, &global_debug_map); + EVLOCK_UNLOCK(_event_debug_map_lock , 0); +} +#endif + +struct event_base * +event_base_new_with_config(const struct event_config *cfg) +{ + int i; + struct event_base *base; + int should_check_environment; + +#ifndef _EVENT_DISABLE_DEBUG_MODE + event_debug_mode_too_late = 1; +#endif + + if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL) { + event_warn("%s: calloc", __func__); + return NULL; + } + detect_monotonic(); + gettime(base, &base->event_tv); + + min_heap_ctor(&base->timeheap); + TAILQ_INIT(&base->eventqueue); + base->sig.ev_signal_pair[0] = -1; + base->sig.ev_signal_pair[1] = -1; + base->th_notify_fd[0] = -1; + base->th_notify_fd[1] = -1; + + event_deferred_cb_queue_init(&base->defer_queue); + base->defer_queue.notify_fn = notify_base_cbq_callback; + base->defer_queue.notify_arg = base; + if (cfg) + base->flags = cfg->flags; + + evmap_io_initmap(&base->io); + evmap_signal_initmap(&base->sigmap); + event_changelist_init(&base->changelist); + + base->evbase = NULL; + + should_check_environment = + !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV)); + + for (i = 0; eventops[i] && !base->evbase; i++) { + if (cfg != NULL) { + /* determine if this backend should be avoided */ + if (event_config_is_avoided_method(cfg, + eventops[i]->name)) + continue; + if ((eventops[i]->features & cfg->require_features) + != cfg->require_features) + continue; + } + + /* also obey the environment variables */ + if (should_check_environment && + event_is_method_disabled(eventops[i]->name)) + continue; + + base->evsel = eventops[i]; + + base->evbase = base->evsel->init(base); + } + + if (base->evbase == NULL) { + event_warnx("%s: no event mechanism available", + __func__); + base->evsel = NULL; + event_base_free(base); + return NULL; + } + + if (evutil_getenv("EVENT_SHOW_METHOD")) + event_msgx("libevent using: %s", base->evsel->name); + + /* allocate a single active event queue */ + if (event_base_priority_init(base, 1) < 0) { + event_base_free(base); + return NULL; + } + + /* prepare for threading */ + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + if (EVTHREAD_LOCKING_ENABLED() && + (!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) { + int r; + EVTHREAD_ALLOC_LOCK(base->th_base_lock, + EVTHREAD_LOCKTYPE_RECURSIVE); + base->defer_queue.lock = base->th_base_lock; + EVTHREAD_ALLOC_COND(base->current_event_cond); + r = evthread_make_base_notifiable(base); + if (r<0) { + event_warnx("%s: Unable to make base notifiable.", __func__); + event_base_free(base); + return NULL; + } + } +#endif + +#ifdef WIN32 + if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP)) + event_base_start_iocp(base, cfg->n_cpus_hint); +#endif + + return (base); +} + +int +event_base_start_iocp(struct event_base *base, int n_cpus) +{ +#ifdef WIN32 + if (base->iocp) + return 0; + base->iocp = event_iocp_port_launch(n_cpus); + if (!base->iocp) { + event_warnx("%s: Couldn't launch IOCP", __func__); + return -1; + } + return 0; +#else + return -1; +#endif +} + +void +event_base_stop_iocp(struct event_base *base) +{ +#ifdef WIN32 + int rv; + + if (!base->iocp) + return; + rv = event_iocp_shutdown(base->iocp, -1); + EVUTIL_ASSERT(rv >= 0); + base->iocp = NULL; +#endif +} + +void +event_base_free(struct event_base *base) +{ + int i, n_deleted=0; + struct event *ev; + /* XXXX grab the lock? If there is contention when one thread frees + * the base, then the contending thread will be very sad soon. */ + + /* event_base_free(NULL) is how to free the current_base if we + * made it with event_init and forgot to hold a reference to it. */ + if (base == NULL && current_base) + base = current_base; + /* If we're freeing current_base, there won't be a current_base. */ + if (base == current_base) + current_base = NULL; + /* Don't actually free NULL. */ + if (base == NULL) { + event_warnx("%s: no base to free", __func__); + return; + } + /* XXX(niels) - check for internal events first */ + +#ifdef WIN32 + event_base_stop_iocp(base); +#endif + + /* threading fds if we have them */ + if (base->th_notify_fd[0] != -1) { + event_del(&base->th_notify); + EVUTIL_CLOSESOCKET(base->th_notify_fd[0]); + if (base->th_notify_fd[1] != -1) + EVUTIL_CLOSESOCKET(base->th_notify_fd[1]); + base->th_notify_fd[0] = -1; + base->th_notify_fd[1] = -1; + event_debug_unassign(&base->th_notify); + } + + /* Delete all non-internal events. */ + for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) { + struct event *next = TAILQ_NEXT(ev, ev_next); + if (!(ev->ev_flags & EVLIST_INTERNAL)) { + event_del(ev); + ++n_deleted; + } + ev = next; + } + while ((ev = min_heap_top(&base->timeheap)) != NULL) { + event_del(ev); + ++n_deleted; + } + for (i = 0; i < base->n_common_timeouts; ++i) { + struct common_timeout_list *ctl = + base->common_timeout_queues[i]; + event_del(&ctl->timeout_event); /* Internal; doesn't count */ + event_debug_unassign(&ctl->timeout_event); + for (ev = TAILQ_FIRST(&ctl->events); ev; ) { + struct event *next = TAILQ_NEXT(ev, + ev_timeout_pos.ev_next_with_common_timeout); + if (!(ev->ev_flags & EVLIST_INTERNAL)) { + event_del(ev); + ++n_deleted; + } + ev = next; + } + mm_free(ctl); + } + if (base->common_timeout_queues) + mm_free(base->common_timeout_queues); + + for (i = 0; i < base->nactivequeues; ++i) { + for (ev = TAILQ_FIRST(&base->activequeues[i]); ev; ) { + struct event *next = TAILQ_NEXT(ev, ev_active_next); + if (!(ev->ev_flags & EVLIST_INTERNAL)) { + event_del(ev); + ++n_deleted; + } + ev = next; + } + } + + if (n_deleted) + event_debug(("%s: %d events were still set in base", + __func__, n_deleted)); + + if (base->evsel != NULL && base->evsel->dealloc != NULL) + base->evsel->dealloc(base); + + for (i = 0; i < base->nactivequeues; ++i) + EVUTIL_ASSERT(TAILQ_EMPTY(&base->activequeues[i])); + + EVUTIL_ASSERT(min_heap_empty(&base->timeheap)); + min_heap_dtor(&base->timeheap); + + mm_free(base->activequeues); + + EVUTIL_ASSERT(TAILQ_EMPTY(&base->eventqueue)); + + evmap_io_clear(&base->io); + evmap_signal_clear(&base->sigmap); + event_changelist_freemem(&base->changelist); + + EVTHREAD_FREE_LOCK(base->th_base_lock, EVTHREAD_LOCKTYPE_RECURSIVE); + EVTHREAD_FREE_COND(base->current_event_cond); + + mm_free(base); +} + +/* reinitialize the event base after a fork */ +int +event_reinit(struct event_base *base) +{ + const struct eventop *evsel; + int res = 0; + struct event *ev; + int was_notifiable = 0; + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + evsel = base->evsel; + +#if 0 + /* Right now, reinit always takes effect, since even if the + backend doesn't require it, the signal socketpair code does. + + XXX + */ + /* check if this event mechanism requires reinit */ + if (!evsel->need_reinit) + goto done; +#endif + + /* prevent internal delete */ + if (base->sig.ev_signal_added) { + /* we cannot call event_del here because the base has + * not been reinitialized yet. */ + event_queue_remove(base, &base->sig.ev_signal, + EVLIST_INSERTED); + if (base->sig.ev_signal.ev_flags & EVLIST_ACTIVE) + event_queue_remove(base, &base->sig.ev_signal, + EVLIST_ACTIVE); + if (base->sig.ev_signal_pair[0] != -1) + EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]); + if (base->sig.ev_signal_pair[1] != -1) + EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]); + base->sig.ev_signal_added = 0; + } + if (base->th_notify_fd[0] != -1) { + /* we cannot call event_del here because the base has + * not been reinitialized yet. */ + was_notifiable = 1; + event_queue_remove(base, &base->th_notify, + EVLIST_INSERTED); + if (base->th_notify.ev_flags & EVLIST_ACTIVE) + event_queue_remove(base, &base->th_notify, + EVLIST_ACTIVE); + base->sig.ev_signal_added = 0; + EVUTIL_CLOSESOCKET(base->th_notify_fd[0]); + if (base->th_notify_fd[1] != -1) + EVUTIL_CLOSESOCKET(base->th_notify_fd[1]); + base->th_notify_fd[0] = -1; + base->th_notify_fd[1] = -1; + event_debug_unassign(&base->th_notify); + } + + if (base->evsel->dealloc != NULL) + base->evsel->dealloc(base); + base->evbase = evsel->init(base); + if (base->evbase == NULL) { + event_errx(1, "%s: could not reinitialize event mechanism", + __func__); + res = -1; + goto done; + } + + event_changelist_freemem(&base->changelist); /* XXX */ + evmap_io_clear(&base->io); + evmap_signal_clear(&base->sigmap); + + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { + if (ev->ev_events & (EV_READ|EV_WRITE)) { + if (ev == &base->sig.ev_signal) { + /* If we run into the ev_signal event, it's only + * in eventqueue because some signal event was + * added, which made evsig_add re-add ev_signal. + * So don't double-add it. */ + continue; + } + if (evmap_io_add(base, ev->ev_fd, ev) == -1) + res = -1; + } else if (ev->ev_events & EV_SIGNAL) { + if (evmap_signal_add(base, (int)ev->ev_fd, ev) == -1) + res = -1; + } + } + + if (was_notifiable && res == 0) + res = evthread_make_base_notifiable(base); + +done: + EVBASE_RELEASE_LOCK(base, th_base_lock); + return (res); +} + +const char ** +event_get_supported_methods(void) +{ + static const char **methods = NULL; + const struct eventop **method; + const char **tmp; + int i = 0, k; + + /* count all methods */ + for (method = &eventops[0]; *method != NULL; ++method) { + ++i; + } + + /* allocate one more than we need for the NULL pointer */ + tmp = mm_calloc((i + 1), sizeof(char *)); + if (tmp == NULL) + return (NULL); + + /* populate the array with the supported methods */ + for (k = 0, i = 0; eventops[k] != NULL; ++k) { + tmp[i++] = eventops[k]->name; + } + tmp[i] = NULL; + + if (methods != NULL) + mm_free((char**)methods); + + methods = tmp; + + return (methods); +} + +struct event_config * +event_config_new(void) +{ + struct event_config *cfg = mm_calloc(1, sizeof(*cfg)); + + if (cfg == NULL) + return (NULL); + + TAILQ_INIT(&cfg->entries); + + return (cfg); +} + +static void +event_config_entry_free(struct event_config_entry *entry) +{ + if (entry->avoid_method != NULL) + mm_free((char *)entry->avoid_method); + mm_free(entry); +} + +void +event_config_free(struct event_config *cfg) +{ + struct event_config_entry *entry; + + while ((entry = TAILQ_FIRST(&cfg->entries)) != NULL) { + TAILQ_REMOVE(&cfg->entries, entry, next); + event_config_entry_free(entry); + } + mm_free(cfg); +} + +int +event_config_set_flag(struct event_config *cfg, int flag) +{ + if (!cfg) + return -1; + cfg->flags |= flag; + return 0; +} + +int +event_config_avoid_method(struct event_config *cfg, const char *method) +{ + struct event_config_entry *entry = mm_malloc(sizeof(*entry)); + if (entry == NULL) + return (-1); + + if ((entry->avoid_method = mm_strdup(method)) == NULL) { + mm_free(entry); + return (-1); + } + + TAILQ_INSERT_TAIL(&cfg->entries, entry, next); + + return (0); +} + +int +event_config_require_features(struct event_config *cfg, + int features) +{ + if (!cfg) + return (-1); + cfg->require_features = features; + return (0); +} + +int +event_config_set_num_cpus_hint(struct event_config *cfg, int cpus) +{ + if (!cfg) + return (-1); + cfg->n_cpus_hint = cpus; + return (0); +} + +int +event_priority_init(int npriorities) +{ + return event_base_priority_init(current_base, npriorities); +} + +int +event_base_priority_init(struct event_base *base, int npriorities) +{ + int i; + + if (N_ACTIVE_CALLBACKS(base) || npriorities < 1 + || npriorities >= EVENT_MAX_PRIORITIES) + return (-1); + + if (npriorities == base->nactivequeues) + return (0); + + if (base->nactivequeues) { + mm_free(base->activequeues); + base->nactivequeues = 0; + } + + /* Allocate our priority queues */ + base->activequeues = (struct event_list *) + mm_calloc(npriorities, sizeof(struct event_list)); + if (base->activequeues == NULL) { + event_warn("%s: calloc", __func__); + return (-1); + } + base->nactivequeues = npriorities; + + for (i = 0; i < base->nactivequeues; ++i) { + TAILQ_INIT(&base->activequeues[i]); + } + + return (0); +} + +/* Returns true iff we're currently watching any events. */ +static int +event_haveevents(struct event_base *base) +{ + /* Caller must hold th_base_lock */ + return (base->virtual_event_count > 0 || base->event_count > 0); +} + +/* "closure" function called when processing active signal events */ +static inline void +event_signal_closure(struct event_base *base, struct event *ev) +{ + short ncalls; + int should_break; + + /* Allows deletes to work */ + ncalls = ev->ev_ncalls; + if (ncalls != 0) + ev->ev_pncalls = &ncalls; + EVBASE_RELEASE_LOCK(base, th_base_lock); + while (ncalls) { + ncalls--; + ev->ev_ncalls = ncalls; + if (ncalls == 0) + ev->ev_pncalls = NULL; + (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + should_break = base->event_break; + EVBASE_RELEASE_LOCK(base, th_base_lock); + + if (should_break) { + if (ncalls != 0) + ev->ev_pncalls = NULL; + return; + } + } +} + +/* Common timeouts are special timeouts that are handled as queues rather than + * in the minheap. This is more efficient than the minheap if we happen to + * know that we're going to get several thousands of timeout events all with + * the same timeout value. + * + * Since all our timeout handling code assumes timevals can be copied, + * assigned, etc, we can't use "magic pointer" to encode these common + * timeouts. Searching through a list to see if every timeout is common could + * also get inefficient. Instead, we take advantage of the fact that tv_usec + * is 32 bits long, but only uses 20 of those bits (since it can never be over + * 999999.) We use the top bits to encode 4 bites of magic number, and 8 bits + * of index into the event_base's aray of common timeouts. + */ + +#define MICROSECONDS_MASK COMMON_TIMEOUT_MICROSECONDS_MASK +#define COMMON_TIMEOUT_IDX_MASK 0x0ff00000 +#define COMMON_TIMEOUT_IDX_SHIFT 20 +#define COMMON_TIMEOUT_MASK 0xf0000000 +#define COMMON_TIMEOUT_MAGIC 0x50000000 + +#define COMMON_TIMEOUT_IDX(tv) \ + (((tv)->tv_usec & COMMON_TIMEOUT_IDX_MASK)>>COMMON_TIMEOUT_IDX_SHIFT) + +/** Return true iff if 'tv' is a common timeout in 'base' */ +static inline int +is_common_timeout(const struct timeval *tv, + const struct event_base *base) +{ + int idx; + if ((tv->tv_usec & COMMON_TIMEOUT_MASK) != COMMON_TIMEOUT_MAGIC) + return 0; + idx = COMMON_TIMEOUT_IDX(tv); + return idx < base->n_common_timeouts; +} + +/* True iff tv1 and tv2 have the same common-timeout index, or if neither + * one is a common timeout. */ +static inline int +is_same_common_timeout(const struct timeval *tv1, const struct timeval *tv2) +{ + return (tv1->tv_usec & ~MICROSECONDS_MASK) == + (tv2->tv_usec & ~MICROSECONDS_MASK); +} + +/** Requires that 'tv' is a common timeout. Return the corresponding + * common_timeout_list. */ +static inline struct common_timeout_list * +get_common_timeout_list(struct event_base *base, const struct timeval *tv) +{ + return base->common_timeout_queues[COMMON_TIMEOUT_IDX(tv)]; +} + +#if 0 +static inline int +common_timeout_ok(const struct timeval *tv, + struct event_base *base) +{ + const struct timeval *expect = + &get_common_timeout_list(base, tv)->duration; + return tv->tv_sec == expect->tv_sec && + tv->tv_usec == expect->tv_usec; +} +#endif + +/* Add the timeout for the first event in given common timeout list to the + * event_base's minheap. */ +static void +common_timeout_schedule(struct common_timeout_list *ctl, + const struct timeval *now, struct event *head) +{ + struct timeval timeout = head->ev_timeout; + timeout.tv_usec &= MICROSECONDS_MASK; + event_add_internal(&ctl->timeout_event, &timeout, 1); +} + +/* Callback: invoked when the timeout for a common timeout queue triggers. + * This means that (at least) the first event in that queue should be run, + * and the timeout should be rescheduled if there are more events. */ +static void +common_timeout_callback(evutil_socket_t fd, short what, void *arg) +{ + struct timeval now; + struct common_timeout_list *ctl = arg; + struct event_base *base = ctl->base; + struct event *ev = NULL; + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + gettime(base, &now); + while (1) { + ev = TAILQ_FIRST(&ctl->events); + if (!ev || ev->ev_timeout.tv_sec > now.tv_sec || + (ev->ev_timeout.tv_sec == now.tv_sec && + (ev->ev_timeout.tv_usec&MICROSECONDS_MASK) > now.tv_usec)) + break; + event_del_internal(ev); + event_active_nolock(ev, EV_TIMEOUT, 1); + } + if (ev) + common_timeout_schedule(ctl, &now, ev); + EVBASE_RELEASE_LOCK(base, th_base_lock); +} + +#define MAX_COMMON_TIMEOUTS 256 + +const struct timeval * +event_base_init_common_timeout(struct event_base *base, + const struct timeval *duration) +{ + int i; + struct timeval tv; + const struct timeval *result=NULL; + struct common_timeout_list *new_ctl; + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + if (duration->tv_usec > 1000000) { + memcpy(&tv, duration, sizeof(struct timeval)); + if (is_common_timeout(duration, base)) + tv.tv_usec &= MICROSECONDS_MASK; + tv.tv_sec += tv.tv_usec / 1000000; + tv.tv_usec %= 1000000; + duration = &tv; + } + for (i = 0; i < base->n_common_timeouts; ++i) { + const struct common_timeout_list *ctl = + base->common_timeout_queues[i]; + if (duration->tv_sec == ctl->duration.tv_sec && + duration->tv_usec == + (ctl->duration.tv_usec & MICROSECONDS_MASK)) { + EVUTIL_ASSERT(is_common_timeout(&ctl->duration, base)); + result = &ctl->duration; + goto done; + } + } + if (base->n_common_timeouts == MAX_COMMON_TIMEOUTS) { + event_warnx("%s: Too many common timeouts already in use; " + "we only support %d per event_base", __func__, + MAX_COMMON_TIMEOUTS); + goto done; + } + if (base->n_common_timeouts_allocated == base->n_common_timeouts) { + int n = base->n_common_timeouts < 16 ? 16 : + base->n_common_timeouts*2; + struct common_timeout_list **newqueues = + mm_realloc(base->common_timeout_queues, + n*sizeof(struct common_timeout_queue *)); + if (!newqueues) { + event_warn("%s: realloc",__func__); + goto done; + } + base->n_common_timeouts_allocated = n; + base->common_timeout_queues = newqueues; + } + new_ctl = mm_calloc(1, sizeof(struct common_timeout_list)); + if (!new_ctl) { + event_warn("%s: calloc",__func__); + goto done; + } + TAILQ_INIT(&new_ctl->events); + new_ctl->duration.tv_sec = duration->tv_sec; + new_ctl->duration.tv_usec = + duration->tv_usec | COMMON_TIMEOUT_MAGIC | + (base->n_common_timeouts << COMMON_TIMEOUT_IDX_SHIFT); + evtimer_assign(&new_ctl->timeout_event, base, + common_timeout_callback, new_ctl); + new_ctl->timeout_event.ev_flags |= EVLIST_INTERNAL; + event_priority_set(&new_ctl->timeout_event, 0); + new_ctl->base = base; + base->common_timeout_queues[base->n_common_timeouts++] = new_ctl; + result = &new_ctl->duration; + +done: + if (result) + EVUTIL_ASSERT(is_common_timeout(result, base)); + + EVBASE_RELEASE_LOCK(base, th_base_lock); + return result; +} + +/* Closure function invoked when we're activating a persistent event. */ +static inline void +event_persist_closure(struct event_base *base, struct event *ev) +{ + /* reschedule the persistent event if we have a timeout. */ + if (ev->ev_io_timeout.tv_sec || ev->ev_io_timeout.tv_usec) { + /* If there was a timeout, we want it to run at an interval of + * ev_io_timeout after the last time it was _scheduled_ for, + * not ev_io_timeout after _now_. If it fired for another + * reason, though, the timeout ought to start ticking _now_. */ + struct timeval run_at; + EVUTIL_ASSERT(is_same_common_timeout(&ev->ev_timeout, + &ev->ev_io_timeout)); + if (is_common_timeout(&ev->ev_timeout, base)) { + ev_uint32_t usec_mask; + struct timeval delay, relative_to; + delay = ev->ev_io_timeout; + usec_mask = delay.tv_usec & ~MICROSECONDS_MASK; + delay.tv_usec &= MICROSECONDS_MASK; + if (ev->ev_res & EV_TIMEOUT) { + relative_to = ev->ev_timeout; + relative_to.tv_usec &= MICROSECONDS_MASK; + } else { + gettime(base, &relative_to); + } + evutil_timeradd(&relative_to, &delay, &run_at); + run_at.tv_usec |= usec_mask; + } else { + struct timeval relative_to; + if (ev->ev_res & EV_TIMEOUT) { + relative_to = ev->ev_timeout; + } else { + gettime(base, &relative_to); + } + evutil_timeradd(&ev->ev_io_timeout, &relative_to, + &run_at); + } + event_add_internal(ev, &run_at, 1); + } + EVBASE_RELEASE_LOCK(base, th_base_lock); + (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg); +} + +/* + Helper for event_process_active to process all the events in a single queue, + releasing the lock as we go. This function requires that the lock be held + when it's invoked. Returns -1 if we get a signal or an event_break that + means we should stop processing any active events now. Otherwise returns + the number of non-internal events that we processed. +*/ +static int +event_process_active_single_queue(struct event_base *base, + struct event_list *activeq) +{ + struct event *ev; + int count = 0; + + EVUTIL_ASSERT(activeq != NULL); + + for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) { + if (ev->ev_events & EV_PERSIST) + event_queue_remove(base, ev, EVLIST_ACTIVE); + else + event_del_internal(ev); + if (!(ev->ev_flags & EVLIST_INTERNAL)) + ++count; + + event_debug(( + "event_process_active: event: %p, %s%scall %p", + ev, + ev->ev_res & EV_READ ? "EV_READ " : " ", + ev->ev_res & EV_WRITE ? "EV_WRITE " : " ", + ev->ev_callback)); + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + base->current_event = ev; + base->current_event_waiters = 0; +#endif + + switch (ev->ev_closure) { + case EV_CLOSURE_SIGNAL: + event_signal_closure(base, ev); + break; + case EV_CLOSURE_PERSIST: + event_persist_closure(base, ev); + break; + default: + case EV_CLOSURE_NONE: + EVBASE_RELEASE_LOCK(base, th_base_lock); + (*ev->ev_callback)( + ev->ev_fd, ev->ev_res, ev->ev_arg); + break; + } + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + base->current_event = NULL; + if (base->current_event_waiters) { + base->current_event_waiters = 0; + EVTHREAD_COND_BROADCAST(base->current_event_cond); + } +#endif + + if (base->event_break) + return -1; + } + return count; +} + +/* + Process up to MAX_DEFERRED of the defered_cb entries in 'queue'. If + *breakptr becomes set to 1, stop. Requires that we start out holding + the lock on 'queue'; releases the lock around 'queue' for each deferred_cb + we process. + */ +static int +event_process_deferred_callbacks(struct deferred_cb_queue *queue, int *breakptr) +{ + int count = 0; + struct deferred_cb *cb; + +#define MAX_DEFERRED 16 + while ((cb = TAILQ_FIRST(&queue->deferred_cb_list))) { + cb->queued = 0; + TAILQ_REMOVE(&queue->deferred_cb_list, cb, cb_next); + --queue->active_count; + UNLOCK_DEFERRED_QUEUE(queue); + + cb->cb(cb, cb->arg); + + LOCK_DEFERRED_QUEUE(queue); + if (*breakptr) + return -1; + if (++count == MAX_DEFERRED) + break; + } +#undef MAX_DEFERRED + return count; +} + +/* + * Active events are stored in priority queues. Lower priorities are always + * process before higher priorities. Low priority events can starve high + * priority ones. + */ + +static int +event_process_active(struct event_base *base) +{ + /* Caller must hold th_base_lock */ + struct event_list *activeq = NULL; + int i, c = 0; + + for (i = 0; i < base->nactivequeues; ++i) { + if (TAILQ_FIRST(&base->activequeues[i]) != NULL) { + activeq = &base->activequeues[i]; + c = event_process_active_single_queue(base, activeq); + if (c < 0) + return -1; + else if (c > 0) + break; /* Processed a real event; do not + * consider lower-priority events */ + /* If we get here, all of the events we processed + * were internal. Continue. */ + } + } + + event_process_deferred_callbacks(&base->defer_queue,&base->event_break); + return c; +} + +/* + * Wait continuously for events. We exit only if no events are left. + */ + +int +event_dispatch(void) +{ + return (event_loop(0)); +} + +int +event_base_dispatch(struct event_base *event_base) +{ + return (event_base_loop(event_base, 0)); +} + +const char * +event_base_get_method(const struct event_base *base) +{ + EVUTIL_ASSERT(base); + return (base->evsel->name); +} + +/** Callback: used to implement event_base_loopexit by telling the event_base + * that it's time to exit its loop. */ +static void +event_loopexit_cb(evutil_socket_t fd, short what, void *arg) +{ + struct event_base *base = arg; + base->event_gotterm = 1; +} + +int +event_loopexit(const struct timeval *tv) +{ + return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, + current_base, tv)); +} + +int +event_base_loopexit(struct event_base *event_base, const struct timeval *tv) +{ + return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb, + event_base, tv)); +} + +int +event_loopbreak(void) +{ + return (event_base_loopbreak(current_base)); +} + +int +event_base_loopbreak(struct event_base *event_base) +{ + int r = 0; + if (event_base == NULL) + return (-1); + + EVBASE_ACQUIRE_LOCK(event_base, th_base_lock); + event_base->event_break = 1; + + if (EVBASE_NEED_NOTIFY(event_base)) { + r = evthread_notify_base(event_base); + } else { + r = (0); + } + EVBASE_RELEASE_LOCK(event_base, th_base_lock); + return r; +} + +int +event_base_got_break(struct event_base *event_base) +{ + int res; + EVBASE_ACQUIRE_LOCK(event_base, th_base_lock); + res = event_base->event_break; + EVBASE_RELEASE_LOCK(event_base, th_base_lock); + return res; +} + +int +event_base_got_exit(struct event_base *event_base) +{ + int res; + EVBASE_ACQUIRE_LOCK(event_base, th_base_lock); + res = event_base->event_gotterm; + EVBASE_RELEASE_LOCK(event_base, th_base_lock); + return res; +} + +/* not thread safe */ + +int +event_loop(int flags) +{ + return event_base_loop(current_base, flags); +} + +int +event_base_loop(struct event_base *base, int flags) +{ + const struct eventop *evsel = base->evsel; + struct timeval tv; + struct timeval *tv_p; + int res, done, retval = 0; + + /* Grab the lock. We will release it inside evsel.dispatch, and again + * as we invoke user callbacks. */ + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + if (base->running_loop) { + event_warnx("%s: reentrant invocation. Only one event_base_loop" + " can run on each event_base at once.", __func__); + EVBASE_RELEASE_LOCK(base, th_base_lock); + return -1; + } + + base->running_loop = 1; + + clear_time_cache(base); + + if (base->sig.ev_signal_added && base->sig.ev_n_signals_added) + evsig_set_base(base); + + done = 0; + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + base->th_owner_id = EVTHREAD_GET_ID(); +#endif + + base->event_gotterm = base->event_break = 0; + + while (!done) { + /* Terminate the loop if we have been asked to */ + if (base->event_gotterm) { + break; + } + + if (base->event_break) { + break; + } + + timeout_correct(base, &tv); + + tv_p = &tv; + if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK)) { + timeout_next(base, &tv_p); + } else { + /* + * if we have active events, we just poll new events + * without waiting. + */ + evutil_timerclear(&tv); + } + + /* If we have no events, we just exit */ + if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base)) { + event_debug(("%s: no events registered.", __func__)); + retval = 1; + goto done; + } + + /* update last old time */ + gettime(base, &base->event_tv); + + clear_time_cache(base); + + res = evsel->dispatch(base, tv_p); + + if (res == -1) { + event_debug(("%s: dispatch returned unsuccessfully.", + __func__)); + retval = -1; + goto done; + } + + update_time_cache(base); + + timeout_process(base); + + if (N_ACTIVE_CALLBACKS(base)) { + int n = event_process_active(base); + if ((flags & EVLOOP_ONCE) + && N_ACTIVE_CALLBACKS(base) == 0 + && n != 0) + done = 1; + } else if (flags & EVLOOP_NONBLOCK) + done = 1; + } + event_debug(("%s: asked to terminate loop.", __func__)); + +done: + clear_time_cache(base); + base->running_loop = 0; + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + return (retval); +} + +/* Sets up an event for processing once */ +struct event_once { + struct event ev; + + void (*cb)(evutil_socket_t, short, void *); + void *arg; +}; + +/* One-time callback to implement event_base_once: invokes the user callback, + * then deletes the allocated storage */ +static void +event_once_cb(evutil_socket_t fd, short events, void *arg) +{ + struct event_once *eonce = arg; + + (*eonce->cb)(fd, events, eonce->arg); + event_debug_unassign(&eonce->ev); + mm_free(eonce); +} + +/* not threadsafe, event scheduled once. */ +int +event_once(evutil_socket_t fd, short events, + void (*callback)(evutil_socket_t, short, void *), + void *arg, const struct timeval *tv) +{ + return event_base_once(current_base, fd, events, callback, arg, tv); +} + +/* Schedules an event once */ +int +event_base_once(struct event_base *base, evutil_socket_t fd, short events, + void (*callback)(evutil_socket_t, short, void *), + void *arg, const struct timeval *tv) +{ + struct event_once *eonce; + struct timeval etv; + int res = 0; + + /* We cannot support signals that just fire once, or persistent + * events. */ + if (events & (EV_SIGNAL|EV_PERSIST)) + return (-1); + + if ((eonce = mm_calloc(1, sizeof(struct event_once))) == NULL) + return (-1); + + eonce->cb = callback; + eonce->arg = arg; + + if (events == EV_TIMEOUT) { + if (tv == NULL) { + evutil_timerclear(&etv); + tv = &etv; + } + + evtimer_assign(&eonce->ev, base, event_once_cb, eonce); + } else if (events & (EV_READ|EV_WRITE)) { + events &= EV_READ|EV_WRITE; + + event_assign(&eonce->ev, base, fd, events, event_once_cb, eonce); + } else { + /* Bad event combination */ + mm_free(eonce); + return (-1); + } + + if (res == 0) + res = event_add(&eonce->ev, tv); + if (res != 0) { + mm_free(eonce); + return (res); + } + + return (0); +} + +int +event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg) +{ + if (!base) + base = current_base; + + _event_debug_assert_not_added(ev); + + ev->ev_base = base; + + ev->ev_callback = callback; + ev->ev_arg = arg; + ev->ev_fd = fd; + ev->ev_events = events; + ev->ev_res = 0; + ev->ev_flags = EVLIST_INIT; + ev->ev_ncalls = 0; + ev->ev_pncalls = NULL; + + if (events & EV_SIGNAL) { + if ((events & (EV_READ|EV_WRITE)) != 0) { + event_warnx("%s: EV_SIGNAL is not compatible with " + "EV_READ or EV_WRITE", __func__); + return -1; + } + ev->ev_closure = EV_CLOSURE_SIGNAL; + } else { + if (events & EV_PERSIST) { + evutil_timerclear(&ev->ev_io_timeout); + ev->ev_closure = EV_CLOSURE_PERSIST; + } else { + ev->ev_closure = EV_CLOSURE_NONE; + } + } + + min_heap_elem_init(ev); + + if (base != NULL) { + /* by default, we put new events into the middle priority */ + ev->ev_pri = base->nactivequeues / 2; + } + + _event_debug_note_setup(ev); + + return 0; +} + +int +event_base_set(struct event_base *base, struct event *ev) +{ + /* Only innocent events may be assigned to a different base */ + if (ev->ev_flags != EVLIST_INIT) + return (-1); + + _event_debug_assert_is_setup(ev); + + ev->ev_base = base; + ev->ev_pri = base->nactivequeues/2; + + return (0); +} + +void +event_set(struct event *ev, evutil_socket_t fd, short events, + void (*callback)(evutil_socket_t, short, void *), void *arg) +{ + int r; + r = event_assign(ev, current_base, fd, events, callback, arg); + EVUTIL_ASSERT(r == 0); +} + +struct event * +event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void *), void *arg) +{ + struct event *ev; + ev = mm_malloc(sizeof(struct event)); + if (ev == NULL) + return (NULL); + if (event_assign(ev, base, fd, events, cb, arg) < 0) { + mm_free(ev); + return (NULL); + } + + return (ev); +} + +void +event_free(struct event *ev) +{ + _event_debug_assert_is_setup(ev); + + /* make sure that this event won't be coming back to haunt us. */ + event_del(ev); + _event_debug_note_teardown(ev); + mm_free(ev); + +} + +void +event_debug_unassign(struct event *ev) +{ + _event_debug_assert_not_added(ev); + _event_debug_note_teardown(ev); + + ev->ev_flags &= ~EVLIST_INIT; +} + +/* + * Set's the priority of an event - if an event is already scheduled + * changing the priority is going to fail. + */ + +int +event_priority_set(struct event *ev, int pri) +{ + _event_debug_assert_is_setup(ev); + + if (ev->ev_flags & EVLIST_ACTIVE) + return (-1); + if (pri < 0 || pri >= ev->ev_base->nactivequeues) + return (-1); + + ev->ev_pri = pri; + + return (0); +} + +/* + * Checks if a specific event is pending or scheduled. + */ + +int +event_pending(const struct event *ev, short event, struct timeval *tv) +{ + int flags = 0; + + _event_debug_assert_is_setup(ev); + + if (ev->ev_flags & EVLIST_INSERTED) + flags |= (ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)); + if (ev->ev_flags & EVLIST_ACTIVE) + flags |= ev->ev_res; + if (ev->ev_flags & EVLIST_TIMEOUT) + flags |= EV_TIMEOUT; + + event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL); + + /* See if there is a timeout that we should report */ + if (tv != NULL && (flags & event & EV_TIMEOUT)) { + struct timeval tmp = ev->ev_timeout; + tmp.tv_usec &= MICROSECONDS_MASK; +#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + /* correctly remamp to real time */ + evutil_timeradd(&ev->ev_base->tv_clock_diff, &tmp, tv); +#else + *tv = tmp; +#endif + } + + return (flags & event); +} + +int +event_initialized(const struct event *ev) +{ + if (!(ev->ev_flags & EVLIST_INIT)) + return 0; + + return 1; +} + +void +event_get_assignment(const struct event *event, struct event_base **base_out, evutil_socket_t *fd_out, short *events_out, event_callback_fn *callback_out, void **arg_out) +{ + _event_debug_assert_is_setup(event); + + if (base_out) + *base_out = event->ev_base; + if (fd_out) + *fd_out = event->ev_fd; + if (events_out) + *events_out = event->ev_events; + if (callback_out) + *callback_out = event->ev_callback; + if (arg_out) + *arg_out = event->ev_arg; +} + +size_t +event_get_struct_event_size(void) +{ + return sizeof(struct event); +} + +evutil_socket_t +event_get_fd(const struct event *ev) +{ + _event_debug_assert_is_setup(ev); + return ev->ev_fd; +} + +struct event_base * +event_get_base(const struct event *ev) +{ + _event_debug_assert_is_setup(ev); + return ev->ev_base; +} + +short +event_get_events(const struct event *ev) +{ + _event_debug_assert_is_setup(ev); + return ev->ev_events; +} + +event_callback_fn +event_get_callback(const struct event *ev) +{ + _event_debug_assert_is_setup(ev); + return ev->ev_callback; +} + +void * +event_get_callback_arg(const struct event *ev) +{ + _event_debug_assert_is_setup(ev); + return ev->ev_arg; +} + +int +event_add(struct event *ev, const struct timeval *tv) +{ + int res; + + if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) { + event_warnx("%s: event has no event_base set.", __func__); + return -1; + } + + EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock); + + res = event_add_internal(ev, tv, 0); + + EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock); + + return (res); +} + +/* Helper callback: wake an event_base from another thread. This version + * works by writing a byte to one end of a socketpair, so that the event_base + * listening on the other end will wake up as the corresponding event + * triggers */ +static int +evthread_notify_base_default(struct event_base *base) +{ + char buf[1]; + int r; + buf[0] = (char) 0; +#ifdef WIN32 + r = send(base->th_notify_fd[1], buf, 1, 0); +#else + r = write(base->th_notify_fd[1], buf, 1); +#endif + return (r < 0 && errno != EAGAIN) ? -1 : 0; +} + +#if defined(_EVENT_HAVE_EVENTFD) && defined(_EVENT_HAVE_SYS_EVENTFD_H) +/* Helper callback: wake an event_base from another thread. This version + * assumes that you have a working eventfd() implementation. */ +static int +evthread_notify_base_eventfd(struct event_base *base) +{ + ev_uint64_t msg = 1; + int r; + do { + r = write(base->th_notify_fd[0], (void*) &msg, sizeof(msg)); + } while (r < 0 && errno == EAGAIN); + + return (r < 0) ? -1 : 0; +} +#endif + +/** Tell the thread currently running the event_loop for base (if any) that it + * needs to stop waiting in its dispatch function (if it is) and process all + * active events and deferred callbacks (if there are any). */ +static int +evthread_notify_base(struct event_base *base) +{ + EVENT_BASE_ASSERT_LOCKED(base); + if (!base->th_notify_fn) + return -1; + if (base->is_notify_pending) + return 0; + base->is_notify_pending = 1; + return base->th_notify_fn(base); +} + +/* Implementation function to add an event. Works just like event_add, + * except: 1) it requires that we have the lock. 2) if tv_is_absolute is set, + * we treat tv as an absolute time, not as an interval to add to the current + * time */ +static inline int +event_add_internal(struct event *ev, const struct timeval *tv, + int tv_is_absolute) +{ + struct event_base *base = ev->ev_base; + int res = 0; + int notify = 0; + + EVENT_BASE_ASSERT_LOCKED(base); + _event_debug_assert_is_setup(ev); + + event_debug(( + "event_add: event: %p (fd %d), %s%s%scall %p", + ev, + (int)ev->ev_fd, + ev->ev_events & EV_READ ? "EV_READ " : " ", + ev->ev_events & EV_WRITE ? "EV_WRITE " : " ", + tv ? "EV_TIMEOUT " : " ", + ev->ev_callback)); + + EVUTIL_ASSERT(!(ev->ev_flags & ~EVLIST_ALL)); + + /* + * prepare for timeout insertion further below, if we get a + * failure on any step, we should not change any state. + */ + if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) { + if (min_heap_reserve(&base->timeheap, + 1 + min_heap_size(&base->timeheap)) == -1) + return (-1); /* ENOMEM == errno */ + } + + /* If the main thread is currently executing a signal event's + * callback, and we are not the main thread, then we want to wait + * until the callback is done before we mess with the event, or else + * we can race on ev_ncalls and ev_pncalls below. */ +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + if (base->current_event == ev && (ev->ev_events & EV_SIGNAL) + && !EVBASE_IN_THREAD(base)) { + ++base->current_event_waiters; + EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock); + } +#endif + + if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) && + !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) { + if (ev->ev_events & (EV_READ|EV_WRITE)) + res = evmap_io_add(base, ev->ev_fd, ev); + else if (ev->ev_events & EV_SIGNAL) + res = evmap_signal_add(base, (int)ev->ev_fd, ev); + if (res != -1) + event_queue_insert(base, ev, EVLIST_INSERTED); + if (res == 1) { + /* evmap says we need to notify the main thread. */ + notify = 1; + res = 0; + } + } + + /* + * we should change the timeout state only if the previous event + * addition succeeded. + */ + if (res != -1 && tv != NULL) { + struct timeval now; + int common_timeout; + + /* + * for persistent timeout events, we remember the + * timeout value and re-add the event. + * + * If tv_is_absolute, this was already set. + */ + if (ev->ev_closure == EV_CLOSURE_PERSIST && !tv_is_absolute) + ev->ev_io_timeout = *tv; + + /* + * we already reserved memory above for the case where we + * are not replacing an existing timeout. + */ + if (ev->ev_flags & EVLIST_TIMEOUT) { + /* XXX I believe this is needless. */ + if (min_heap_elt_is_top(ev)) + notify = 1; + event_queue_remove(base, ev, EVLIST_TIMEOUT); + } + + /* Check if it is active due to a timeout. Rescheduling + * this timeout before the callback can be executed + * removes it from the active list. */ + if ((ev->ev_flags & EVLIST_ACTIVE) && + (ev->ev_res & EV_TIMEOUT)) { + if (ev->ev_events & EV_SIGNAL) { + /* See if we are just active executing + * this event in a loop + */ + if (ev->ev_ncalls && ev->ev_pncalls) { + /* Abort loop */ + *ev->ev_pncalls = 0; + } + } + + event_queue_remove(base, ev, EVLIST_ACTIVE); + } + + gettime(base, &now); + + common_timeout = is_common_timeout(tv, base); + if (tv_is_absolute) { + ev->ev_timeout = *tv; + } else if (common_timeout) { + struct timeval tmp = *tv; + tmp.tv_usec &= MICROSECONDS_MASK; + evutil_timeradd(&now, &tmp, &ev->ev_timeout); + ev->ev_timeout.tv_usec |= + (tv->tv_usec & ~MICROSECONDS_MASK); + } else { + evutil_timeradd(&now, tv, &ev->ev_timeout); + } + + event_debug(( + "event_add: timeout in %d seconds, call %p", + (int)tv->tv_sec, ev->ev_callback)); + + event_queue_insert(base, ev, EVLIST_TIMEOUT); + if (common_timeout) { + struct common_timeout_list *ctl = + get_common_timeout_list(base, &ev->ev_timeout); + if (ev == TAILQ_FIRST(&ctl->events)) { + common_timeout_schedule(ctl, &now, ev); + } + } else { + /* See if the earliest timeout is now earlier than it + * was before: if so, we will need to tell the main + * thread to wake up earlier than it would + * otherwise. */ + if (min_heap_elt_is_top(ev)) + notify = 1; + } + } + + /* if we are not in the right thread, we need to wake up the loop */ + if (res != -1 && notify && EVBASE_NEED_NOTIFY(base)) + evthread_notify_base(base); + + _event_debug_note_add(ev); + + return (res); +} + +int +event_del(struct event *ev) +{ + int res; + + if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) { + event_warnx("%s: event has no event_base set.", __func__); + return -1; + } + + EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock); + + res = event_del_internal(ev); + + EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock); + + return (res); +} + +/* Helper for event_del: always called with th_base_lock held. */ +static inline int +event_del_internal(struct event *ev) +{ + struct event_base *base; + int res = 0, notify = 0; + + event_debug(("event_del: %p (fd %d), callback %p", + ev, (int)ev->ev_fd, ev->ev_callback)); + + /* An event without a base has not been added */ + if (ev->ev_base == NULL) + return (-1); + + EVENT_BASE_ASSERT_LOCKED(ev->ev_base); + + /* If the main thread is currently executing this event's callback, + * and we are not the main thread, then we want to wait until the + * callback is done before we start removing the event. That way, + * when this function returns, it will be safe to free the + * user-supplied argument. */ + base = ev->ev_base; +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + if (base->current_event == ev && !EVBASE_IN_THREAD(base)) { + ++base->current_event_waiters; + EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock); + } +#endif + + EVUTIL_ASSERT(!(ev->ev_flags & ~EVLIST_ALL)); + + /* See if we are just active executing this event in a loop */ + if (ev->ev_events & EV_SIGNAL) { + if (ev->ev_ncalls && ev->ev_pncalls) { + /* Abort loop */ + *ev->ev_pncalls = 0; + } + } + + if (ev->ev_flags & EVLIST_TIMEOUT) { + /* NOTE: We never need to notify the main thread because of a + * deleted timeout event: all that could happen if we don't is + * that the dispatch loop might wake up too early. But the + * point of notifying the main thread _is_ to wake up the + * dispatch loop early anyway, so we wouldn't gain anything by + * doing it. + */ + event_queue_remove(base, ev, EVLIST_TIMEOUT); + } + + if (ev->ev_flags & EVLIST_ACTIVE) + event_queue_remove(base, ev, EVLIST_ACTIVE); + + if (ev->ev_flags & EVLIST_INSERTED) { + event_queue_remove(base, ev, EVLIST_INSERTED); + if (ev->ev_events & (EV_READ|EV_WRITE)) + res = evmap_io_del(base, ev->ev_fd, ev); + else + res = evmap_signal_del(base, (int)ev->ev_fd, ev); + if (res == 1) { + /* evmap says we need to notify the main thread. */ + notify = 1; + res = 0; + } + } + + /* if we are not in the right thread, we need to wake up the loop */ + if (res != -1 && notify && EVBASE_NEED_NOTIFY(base)) + evthread_notify_base(base); + + _event_debug_note_del(ev); + + return (res); +} + +void +event_active(struct event *ev, int res, short ncalls) +{ + if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) { + event_warnx("%s: event has no event_base set.", __func__); + return; + } + + EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock); + + _event_debug_assert_is_setup(ev); + + event_active_nolock(ev, res, ncalls); + + EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock); +} + + +void +event_active_nolock(struct event *ev, int res, short ncalls) +{ + struct event_base *base; + + event_debug(("event_active: %p (fd %d), res %d, callback %p", + ev, (int)ev->ev_fd, (int)res, ev->ev_callback)); + + + /* We get different kinds of events, add them together */ + if (ev->ev_flags & EVLIST_ACTIVE) { + ev->ev_res |= res; + return; + } + + base = ev->ev_base; + + EVENT_BASE_ASSERT_LOCKED(base); + + ev->ev_res = res; + + if (ev->ev_events & EV_SIGNAL) { +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + if (base->current_event == ev && !EVBASE_IN_THREAD(base)) { + ++base->current_event_waiters; + EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock); + } +#endif + ev->ev_ncalls = ncalls; + ev->ev_pncalls = NULL; + } + + event_queue_insert(base, ev, EVLIST_ACTIVE); + + if (EVBASE_NEED_NOTIFY(base)) + evthread_notify_base(base); +} + +void +event_deferred_cb_init(struct deferred_cb *cb, deferred_cb_fn fn, void *arg) +{ + memset(cb, 0, sizeof(struct deferred_cb)); + cb->cb = fn; + cb->arg = arg; +} + +void +event_deferred_cb_cancel(struct deferred_cb_queue *queue, + struct deferred_cb *cb) +{ + if (!queue) { + if (current_base) + queue = ¤t_base->defer_queue; + else + return; + } + + LOCK_DEFERRED_QUEUE(queue); + if (cb->queued) { + TAILQ_REMOVE(&queue->deferred_cb_list, cb, cb_next); + --queue->active_count; + cb->queued = 0; + } + UNLOCK_DEFERRED_QUEUE(queue); +} + +void +event_deferred_cb_schedule(struct deferred_cb_queue *queue, + struct deferred_cb *cb) +{ + if (!queue) { + if (current_base) + queue = ¤t_base->defer_queue; + else + return; + } + + LOCK_DEFERRED_QUEUE(queue); + if (!cb->queued) { + cb->queued = 1; + TAILQ_INSERT_TAIL(&queue->deferred_cb_list, cb, cb_next); + ++queue->active_count; + if (queue->notify_fn) + queue->notify_fn(queue, queue->notify_arg); + } + UNLOCK_DEFERRED_QUEUE(queue); +} + +static int +timeout_next(struct event_base *base, struct timeval **tv_p) +{ + /* Caller must hold th_base_lock */ + struct timeval now; + struct event *ev; + struct timeval *tv = *tv_p; + int res = 0; + + ev = min_heap_top(&base->timeheap); + + if (ev == NULL) { + /* if no time-based events are active wait for I/O */ + *tv_p = NULL; + goto out; + } + + if (gettime(base, &now) == -1) { + res = -1; + goto out; + } + + if (evutil_timercmp(&ev->ev_timeout, &now, <=)) { + evutil_timerclear(tv); + goto out; + } + + evutil_timersub(&ev->ev_timeout, &now, tv); + + EVUTIL_ASSERT(tv->tv_sec >= 0); + EVUTIL_ASSERT(tv->tv_usec >= 0); + event_debug(("timeout_next: in %d seconds", (int)tv->tv_sec)); + +out: + return (res); +} + +/* + * Determines if the time is running backwards by comparing the current time + * against the last time we checked. Not needed when using clock monotonic. + * If time is running backwards, we adjust the firing time of every event by + * the amount that time seems to have jumped. + */ +static void +timeout_correct(struct event_base *base, struct timeval *tv) +{ + /* Caller must hold th_base_lock. */ + struct event **pev; + unsigned int size; + struct timeval off; + int i; + + if (use_monotonic) + return; + + /* Check if time is running backwards */ + gettime(base, tv); + + if (evutil_timercmp(tv, &base->event_tv, >=)) { + base->event_tv = *tv; + return; + } + + event_debug(("%s: time is running backwards, corrected", + __func__)); + evutil_timersub(&base->event_tv, tv, &off); + + /* + * We can modify the key element of the node without destroying + * the minheap property, because we change every element. + */ + pev = base->timeheap.p; + size = base->timeheap.n; + for (; size-- > 0; ++pev) { + struct timeval *ev_tv = &(**pev).ev_timeout; + evutil_timersub(ev_tv, &off, ev_tv); + } + for (i=0; in_common_timeouts; ++i) { + struct event *ev; + struct common_timeout_list *ctl = + base->common_timeout_queues[i]; + TAILQ_FOREACH(ev, &ctl->events, + ev_timeout_pos.ev_next_with_common_timeout) { + struct timeval *ev_tv = &ev->ev_timeout; + ev_tv->tv_usec &= MICROSECONDS_MASK; + evutil_timersub(ev_tv, &off, ev_tv); + ev_tv->tv_usec |= COMMON_TIMEOUT_MAGIC | + (i<event_tv = *tv; +} + +/* Activate every event whose timeout has elapsed. */ +static void +timeout_process(struct event_base *base) +{ + /* Caller must hold lock. */ + struct timeval now; + struct event *ev; + + if (min_heap_empty(&base->timeheap)) { + return; + } + + gettime(base, &now); + + while ((ev = min_heap_top(&base->timeheap))) { + if (evutil_timercmp(&ev->ev_timeout, &now, >)) + break; + + /* delete this event from the I/O queues */ + event_del_internal(ev); + + event_debug(("timeout_process: call %p", + ev->ev_callback)); + event_active_nolock(ev, EV_TIMEOUT, 1); + } +} + +/* Remove 'ev' from 'queue' (EVLIST_...) in base. */ +static void +event_queue_remove(struct event_base *base, struct event *ev, int queue) +{ + EVENT_BASE_ASSERT_LOCKED(base); + + if (!(ev->ev_flags & queue)) { + event_errx(1, "%s: %p(fd %d) not on queue %x", __func__, + ev, ev->ev_fd, queue); + return; + } + + if (~ev->ev_flags & EVLIST_INTERNAL) + base->event_count--; + + ev->ev_flags &= ~queue; + switch (queue) { + case EVLIST_INSERTED: + TAILQ_REMOVE(&base->eventqueue, ev, ev_next); + break; + case EVLIST_ACTIVE: + base->event_count_active--; + TAILQ_REMOVE(&base->activequeues[ev->ev_pri], + ev, ev_active_next); + break; + case EVLIST_TIMEOUT: + if (is_common_timeout(&ev->ev_timeout, base)) { + struct common_timeout_list *ctl = + get_common_timeout_list(base, &ev->ev_timeout); + TAILQ_REMOVE(&ctl->events, ev, + ev_timeout_pos.ev_next_with_common_timeout); + } else { + min_heap_erase(&base->timeheap, ev); + } + break; + default: + event_errx(1, "%s: unknown queue %x", __func__, queue); + } +} + +/* Add 'ev' to the common timeout list in 'ev'. */ +static void +insert_common_timeout_inorder(struct common_timeout_list *ctl, + struct event *ev) +{ + struct event *e; + /* By all logic, we should just be able to append 'ev' to the end of + * ctl->events, since the timeout on each 'ev' is set to {the common + * timeout} + {the time when we add the event}, and so the events + * should arrive in order of their timeeouts. But just in case + * there's some wacky threading issue going on, we do a search from + * the end of 'ev' to find the right insertion point. + */ + TAILQ_FOREACH_REVERSE(e, &ctl->events, + event_list, ev_timeout_pos.ev_next_with_common_timeout) { + /* This timercmp is a little sneaky, since both ev and e have + * magic values in tv_usec. Fortunately, they ought to have + * the _same_ magic values in tv_usec. Let's assert for that. + */ + EVUTIL_ASSERT( + is_same_common_timeout(&e->ev_timeout, &ev->ev_timeout)); + if (evutil_timercmp(&ev->ev_timeout, &e->ev_timeout, >=)) { + TAILQ_INSERT_AFTER(&ctl->events, e, ev, + ev_timeout_pos.ev_next_with_common_timeout); + return; + } + } + TAILQ_INSERT_HEAD(&ctl->events, ev, + ev_timeout_pos.ev_next_with_common_timeout); +} + +static void +event_queue_insert(struct event_base *base, struct event *ev, int queue) +{ + EVENT_BASE_ASSERT_LOCKED(base); + + if (ev->ev_flags & queue) { + /* Double insertion is possible for active events */ + if (queue & EVLIST_ACTIVE) + return; + + event_errx(1, "%s: %p(fd %d) already on queue %x", __func__, + ev, ev->ev_fd, queue); + return; + } + + if (~ev->ev_flags & EVLIST_INTERNAL) + base->event_count++; + + ev->ev_flags |= queue; + switch (queue) { + case EVLIST_INSERTED: + TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next); + break; + case EVLIST_ACTIVE: + base->event_count_active++; + TAILQ_INSERT_TAIL(&base->activequeues[ev->ev_pri], + ev,ev_active_next); + break; + case EVLIST_TIMEOUT: { + if (is_common_timeout(&ev->ev_timeout, base)) { + struct common_timeout_list *ctl = + get_common_timeout_list(base, &ev->ev_timeout); + insert_common_timeout_inorder(ctl, ev); + } else + min_heap_push(&base->timeheap, ev); + break; + } + default: + event_errx(1, "%s: unknown queue %x", __func__, queue); + } +} + +/* Functions for debugging */ + +const char * +event_get_version(void) +{ + return (_EVENT_VERSION); +} + +ev_uint32_t +event_get_version_number(void) +{ + return (_EVENT_NUMERIC_VERSION); +} + +/* + * No thread-safe interface needed - the information should be the same + * for all threads. + */ + +const char * +event_get_method(void) +{ + return (current_base->evsel->name); +} + +#ifndef _EVENT_DISABLE_MM_REPLACEMENT +static void *(*_mm_malloc_fn)(size_t sz) = NULL; +static void *(*_mm_realloc_fn)(void *p, size_t sz) = NULL; +static void (*_mm_free_fn)(void *p) = NULL; + +void * +event_mm_malloc_(size_t sz) +{ + if (_mm_malloc_fn) + return _mm_malloc_fn(sz); + else + return malloc(sz); +} + +void * +event_mm_calloc_(size_t count, size_t size) +{ + if (_mm_malloc_fn) { + size_t sz = count * size; + void *p = _mm_malloc_fn(sz); + if (p) + memset(p, 0, sz); + return p; + } else + return calloc(count, size); +} + +char * +event_mm_strdup_(const char *str) +{ + if (_mm_malloc_fn) { + size_t ln = strlen(str); + void *p = _mm_malloc_fn(ln+1); + if (p) + memcpy(p, str, ln+1); + return p; + } else +#ifdef WIN32 + return _strdup(str); +#else + return strdup(str); +#endif +} + +void * +event_mm_realloc_(void *ptr, size_t sz) +{ + if (_mm_realloc_fn) + return _mm_realloc_fn(ptr, sz); + else + return realloc(ptr, sz); +} + +void +event_mm_free_(void *ptr) +{ + if (_mm_free_fn) + _mm_free_fn(ptr); + else + free(ptr); +} + +void +event_set_mem_functions(void *(*malloc_fn)(size_t sz), + void *(*realloc_fn)(void *ptr, size_t sz), + void (*free_fn)(void *ptr)) +{ + _mm_malloc_fn = malloc_fn; + _mm_realloc_fn = realloc_fn; + _mm_free_fn = free_fn; +} +#endif + +#if defined(_EVENT_HAVE_EVENTFD) && defined(_EVENT_HAVE_SYS_EVENTFD_H) +static void +evthread_notify_drain_eventfd(evutil_socket_t fd, short what, void *arg) +{ + ev_uint64_t msg; + ev_ssize_t r; + struct event_base *base = arg; + + r = read(fd, (void*) &msg, sizeof(msg)); + if (r<0 && errno != EAGAIN) { + event_sock_warn(fd, "Error reading from eventfd"); + } + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + base->is_notify_pending = 0; + EVBASE_RELEASE_LOCK(base, th_base_lock); +} +#endif + +static void +evthread_notify_drain_default(evutil_socket_t fd, short what, void *arg) +{ + unsigned char buf[1024]; + struct event_base *base = arg; +#ifdef WIN32 + while (recv(fd, (char*)buf, sizeof(buf), 0) > 0) + ; +#else + while (read(fd, (char*)buf, sizeof(buf)) > 0) + ; +#endif + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + base->is_notify_pending = 0; + EVBASE_RELEASE_LOCK(base, th_base_lock); +} + +int +evthread_make_base_notifiable(struct event_base *base) +{ + void (*cb)(evutil_socket_t, short, void *) = evthread_notify_drain_default; + int (*notify)(struct event_base *) = evthread_notify_base_default; + + /* XXXX grab the lock here? */ + if (!base) + return -1; + + if (base->th_notify_fd[0] >= 0) + return 0; + +#if defined(_EVENT_HAVE_EVENTFD) && defined(_EVENT_HAVE_SYS_EVENTFD_H) +#ifndef EFD_CLOEXEC +#define EFD_CLOEXEC 0 +#endif + base->th_notify_fd[0] = eventfd(0, EFD_CLOEXEC); + if (base->th_notify_fd[0] >= 0) { + evutil_make_socket_closeonexec(base->th_notify_fd[0]); + notify = evthread_notify_base_eventfd; + cb = evthread_notify_drain_eventfd; + } +#endif +#if defined(_EVENT_HAVE_PIPE) + if (base->th_notify_fd[0] < 0) { + if ((base->evsel->features & EV_FEATURE_FDS)) { + if (pipe(base->th_notify_fd) < 0) { + event_warn("%s: pipe", __func__); + } else { + evutil_make_socket_closeonexec(base->th_notify_fd[0]); + evutil_make_socket_closeonexec(base->th_notify_fd[1]); + } + } + } +#endif + +#ifdef WIN32 +#define LOCAL_SOCKETPAIR_AF AF_INET +#else +#define LOCAL_SOCKETPAIR_AF AF_UNIX +#endif + if (base->th_notify_fd[0] < 0) { + if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, + base->th_notify_fd) == -1) { + event_sock_warn(-1, "%s: socketpair", __func__); + return (-1); + } else { + evutil_make_socket_closeonexec(base->th_notify_fd[0]); + evutil_make_socket_closeonexec(base->th_notify_fd[1]); + } + } + + evutil_make_socket_nonblocking(base->th_notify_fd[0]); + + base->th_notify_fn = notify; + + /* + Making the second socket nonblocking is a bit subtle, given that we + ignore any EAGAIN returns when writing to it, and you don't usally + do that for a nonblocking socket. But if the kernel gives us EAGAIN, + then there's no need to add any more data to the buffer, since + the main thread is already either about to wake up and drain it, + or woken up and in the process of draining it. + */ + if (base->th_notify_fd[1] > 0) + evutil_make_socket_nonblocking(base->th_notify_fd[1]); + + /* prepare an event that we can use for wakeup */ + event_assign(&base->th_notify, base, base->th_notify_fd[0], + EV_READ|EV_PERSIST, cb, base); + + /* we need to mark this as internal event */ + base->th_notify.ev_flags |= EVLIST_INTERNAL; + event_priority_set(&base->th_notify, 0); + + return event_add(&base->th_notify, NULL); +} + +void +event_base_dump_events(struct event_base *base, FILE *output) +{ + struct event *e; + int i; + fprintf(output, "Inserted events:\n"); + TAILQ_FOREACH(e, &base->eventqueue, ev_next) { + fprintf(output, " %p [fd %ld]%s%s%s%s%s\n", + (void*)e, (long)e->ev_fd, + (e->ev_events&EV_READ)?" Read":"", + (e->ev_events&EV_WRITE)?" Write":"", + (e->ev_events&EV_SIGNAL)?" Signal":"", + (e->ev_events&EV_TIMEOUT)?" Timeout":"", + (e->ev_events&EV_PERSIST)?" Persist":""); + + } + for (i = 0; i < base->nactivequeues; ++i) { + if (TAILQ_EMPTY(&base->activequeues[i])) + continue; + fprintf(output, "Active events [priority %d]:\n", i); + TAILQ_FOREACH(e, &base->eventqueue, ev_next) { + fprintf(output, " %p [fd %ld]%s%s%s%s\n", + (void*)e, (long)e->ev_fd, + (e->ev_res&EV_READ)?" Read active":"", + (e->ev_res&EV_WRITE)?" Write active":"", + (e->ev_res&EV_SIGNAL)?" Signal active":"", + (e->ev_res&EV_TIMEOUT)?" Timeout active":""); + } + } +} + +void +event_base_add_virtual(struct event_base *base) +{ + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + base->virtual_event_count++; + EVBASE_RELEASE_LOCK(base, th_base_lock); +} + +void +event_base_del_virtual(struct event_base *base) +{ + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + EVUTIL_ASSERT(base->virtual_event_count > 0); + base->virtual_event_count--; + if (base->virtual_event_count == 0 && EVBASE_NEED_NOTIFY(base)) + evthread_notify_base(base); + EVBASE_RELEASE_LOCK(base, th_base_lock); +} + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT +int +event_global_setup_locks_(const int enable_locks) +{ +#ifndef _EVENT_DISABLE_DEBUG_MODE + EVTHREAD_SETUP_GLOBAL_LOCK(_event_debug_map_lock, 0); +#endif + if (evsig_global_setup_locks_(enable_locks) < 0) + return -1; + if (evutil_secure_rng_global_setup_locks_(enable_locks) < 0) + return -1; + return 0; +} +#endif + +void +event_base_assert_ok(struct event_base *base) +{ + int i; + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + evmap_check_integrity(base); + + /* Check the heap property */ + for (i = 1; i < (int)base->timeheap.n; ++i) { + int parent = (i - 1) / 2; + struct event *ev, *p_ev; + ev = base->timeheap.p[i]; + p_ev = base->timeheap.p[parent]; + EVUTIL_ASSERT(ev->ev_flags & EV_TIMEOUT); + EVUTIL_ASSERT(evutil_timercmp(&p_ev->ev_timeout, &ev->ev_timeout, <=)); + EVUTIL_ASSERT(ev->ev_timeout_pos.min_heap_idx == i); + } + + /* Check that the common timeouts are fine */ + for (i = 0; i < base->n_common_timeouts; ++i) { + struct common_timeout_list *ctl = base->common_timeout_queues[i]; + struct event *last=NULL, *ev; + TAILQ_FOREACH(ev, &ctl->events, ev_timeout_pos.ev_next_with_common_timeout) { + if (last) + EVUTIL_ASSERT(evutil_timercmp(&last->ev_timeout, &ev->ev_timeout, <=)); + EVUTIL_ASSERT(ev->ev_flags & EV_TIMEOUT); + EVUTIL_ASSERT(is_common_timeout(&ev->ev_timeout,base)); + EVUTIL_ASSERT(COMMON_TIMEOUT_IDX(&ev->ev_timeout) == i); + last = ev; + } + } + + EVBASE_RELEASE_LOCK(base, th_base_lock); +} diff --git a/libevent/event.h b/libevent/event.h new file mode 100644 index 0000000..a3785b9 --- /dev/null +++ b/libevent/event.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT_H_ +#define _EVENT_H_ + +/** @file event.h + + A library for writing event-driven network servers. + + The header is deprecated in Libevent 2.0 and later; please + use instead. Depending on what functionality you + need, you may also want to include more of the other event2/ + headers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#ifdef _EVENT_HAVE_STDINT_H +#include +#endif +#include + +/* For int types. */ +#include + +#ifdef WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#undef WIN32_LEAN_AND_MEAN +typedef unsigned char u_char; +typedef unsigned short u_short; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT_H_ */ diff --git a/libevent/event_iocp.c b/libevent/event_iocp.c new file mode 100644 index 0000000..4321281 --- /dev/null +++ b/libevent/event_iocp.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2009-2012 Niels Provos, Nick Mathewson + * + * 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. + */ + +#ifndef _WIN32_WINNT +/* Minimum required for InitializeCriticalSectionAndSpinCount */ +#define _WIN32_WINNT 0x0403 +#endif +#include +#include +#include +#include +#include + +#include "event2/util.h" +#include "util-internal.h" +#include "iocp-internal.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "event-internal.h" +#include "evthread-internal.h" + +#define NOTIFICATION_KEY ((ULONG_PTR)-1) + +void +event_overlapped_init(struct event_overlapped *o, iocp_callback cb) +{ + memset(o, 0, sizeof(struct event_overlapped)); + o->cb = cb; +} + +static void +handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes, int ok) +{ + struct event_overlapped *eo = + EVUTIL_UPCAST(o, struct event_overlapped, overlapped); + eo->cb(eo, completion_key, nBytes, ok); +} + +static void +loop(void *_port) +{ + struct event_iocp_port *port = _port; + long ms = port->ms; + HANDLE p = port->port; + + if (ms <= 0) + ms = INFINITE; + + while (1) { + OVERLAPPED *overlapped=NULL; + ULONG_PTR key=0; + DWORD bytes=0; + int ok = GetQueuedCompletionStatus(p, &bytes, &key, + &overlapped, ms); + EnterCriticalSection(&port->lock); + if (port->shutdown) { + if (--port->n_live_threads == 0) + ReleaseSemaphore(port->shutdownSemaphore, 1, + NULL); + LeaveCriticalSection(&port->lock); + return; + } + LeaveCriticalSection(&port->lock); + + if (key != NOTIFICATION_KEY && overlapped) + handle_entry(overlapped, key, bytes, ok); + else if (!overlapped) + break; + } + event_warnx("GetQueuedCompletionStatus exited with no event."); + EnterCriticalSection(&port->lock); + if (--port->n_live_threads == 0) + ReleaseSemaphore(port->shutdownSemaphore, 1, NULL); + LeaveCriticalSection(&port->lock); +} + +int +event_iocp_port_associate(struct event_iocp_port *port, evutil_socket_t fd, + ev_uintptr_t key) +{ + HANDLE h; + h = CreateIoCompletionPort((HANDLE)fd, port->port, key, port->n_threads); + if (!h) + return -1; + return 0; +} + +static void * +get_extension_function(SOCKET s, const GUID *which_fn) +{ + void *ptr = NULL; + DWORD bytes=0; + WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, + (GUID*)which_fn, sizeof(*which_fn), + &ptr, sizeof(ptr), + &bytes, NULL, NULL); + + /* No need to detect errors here: if ptr is set, then we have a good + function pointer. Otherwise, we should behave as if we had no + function pointer. + */ + return ptr; +} + +/* Mingw doesn't have these in its mswsock.h. The values are copied from + wine.h. Perhaps if we copy them exactly, the cargo will come again. +*/ +#ifndef WSAID_ACCEPTEX +#define WSAID_ACCEPTEX \ + {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} +#endif +#ifndef WSAID_CONNECTEX +#define WSAID_CONNECTEX \ + {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}} +#endif +#ifndef WSAID_GETACCEPTEXSOCKADDRS +#define WSAID_GETACCEPTEXSOCKADDRS \ + {0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} +#endif + +static void +init_extension_functions(struct win32_extension_fns *ext) +{ + const GUID acceptex = WSAID_ACCEPTEX; + const GUID connectex = WSAID_CONNECTEX; + const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS; + SOCKET s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) + return; + ext->AcceptEx = get_extension_function(s, &acceptex); + ext->ConnectEx = get_extension_function(s, &connectex); + ext->GetAcceptExSockaddrs = get_extension_function(s, + &getacceptexsockaddrs); + closesocket(s); +} + +static struct win32_extension_fns the_extension_fns; +static int extension_fns_initialized = 0; + +const struct win32_extension_fns * +event_get_win32_extension_fns(void) +{ + return &the_extension_fns; +} + +#define N_CPUS_DEFAULT 2 + +struct event_iocp_port * +event_iocp_port_launch(int n_cpus) +{ + struct event_iocp_port *port; + int i; + + if (!extension_fns_initialized) + init_extension_functions(&the_extension_fns); + + if (!(port = mm_calloc(1, sizeof(struct event_iocp_port)))) + return NULL; + + if (n_cpus <= 0) + n_cpus = N_CPUS_DEFAULT; + port->n_threads = n_cpus * 2; + port->threads = mm_calloc(port->n_threads, sizeof(HANDLE)); + if (!port->threads) + goto err; + + port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, + n_cpus); + port->ms = -1; + if (!port->port) + goto err; + + port->shutdownSemaphore = CreateSemaphore(NULL, 0, 1, NULL); + if (!port->shutdownSemaphore) + goto err; + + for (i=0; in_threads; ++i) { + ev_uintptr_t th = _beginthread(loop, 0, port); + if (th == (ev_uintptr_t)-1) + goto err; + port->threads[i] = (HANDLE)th; + ++port->n_live_threads; + } + + InitializeCriticalSectionAndSpinCount(&port->lock, 1000); + + return port; +err: + if (port->port) + CloseHandle(port->port); + if (port->threads) + mm_free(port->threads); + if (port->shutdownSemaphore) + CloseHandle(port->shutdownSemaphore); + mm_free(port); + return NULL; +} + +static void +_event_iocp_port_unlock_and_free(struct event_iocp_port *port) +{ + DeleteCriticalSection(&port->lock); + CloseHandle(port->port); + CloseHandle(port->shutdownSemaphore); + mm_free(port->threads); + mm_free(port); +} + +static int +event_iocp_notify_all(struct event_iocp_port *port) +{ + int i, r, ok=1; + for (i=0; in_threads; ++i) { + r = PostQueuedCompletionStatus(port->port, 0, NOTIFICATION_KEY, + NULL); + if (!r) + ok = 0; + } + return ok ? 0 : -1; +} + +int +event_iocp_shutdown(struct event_iocp_port *port, long waitMsec) +{ + DWORD ms = INFINITE; + int n; + + EnterCriticalSection(&port->lock); + port->shutdown = 1; + LeaveCriticalSection(&port->lock); + event_iocp_notify_all(port); + + if (waitMsec >= 0) + ms = waitMsec; + + WaitForSingleObject(port->shutdownSemaphore, ms); + EnterCriticalSection(&port->lock); + n = port->n_live_threads; + LeaveCriticalSection(&port->lock); + if (n == 0) { + _event_iocp_port_unlock_and_free(port); + return 0; + } else { + return -1; + } +} + +int +event_iocp_activate_overlapped( + struct event_iocp_port *port, struct event_overlapped *o, + ev_uintptr_t key, ev_uint32_t n) +{ + BOOL r; + + r = PostQueuedCompletionStatus(port->port, n, key, &o->overlapped); + return (r==0) ? -1 : 0; +} + +struct event_iocp_port * +event_base_get_iocp(struct event_base *base) +{ +#ifdef WIN32 + return base->iocp; +#else + return NULL; +#endif +} diff --git a/libevent/event_rpcgen.py b/libevent/event_rpcgen.py new file mode 100755 index 0000000..e051aa9 --- /dev/null +++ b/libevent/event_rpcgen.py @@ -0,0 +1,1717 @@ +#!/usr/bin/env python +# +# Copyright (c) 2005-2007 Niels Provos +# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson +# All rights reserved. +# +# Generates marshaling code based on libevent. + +# TODO: +# 1) use optparse to allow the strategy shell to parse options, and +# to allow the instantiated factory (for the specific output language) +# to parse remaining options +# 2) move the globals into a class that manages execution (including the +# progress outputs that space stderr at the moment) +# 3) emit other languages + +import sys +import re + +_NAME = "event_rpcgen.py" +_VERSION = "0.1" + +# Globals +line_count = 0 + +white = re.compile(r'\s+') +cppcomment = re.compile(r'\/\/.*$') +nonident = re.compile(r'[^a-zA-Z0-9_]') +structref = re.compile(r'^struct\[([a-zA-Z_][a-zA-Z0-9_]*)\]$') +structdef = re.compile(r'^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$') + +headerdirect = [] +cppdirect = [] + +def TranslateList(mylist, mydict): + return map(lambda x: x % mydict, mylist) + +# Exception class for parse errors +class RpcGenError(Exception): + def __init__(self, why): + self.why = why + def __str__(self): + return str(self.why) + +# Holds everything that makes a struct +class Struct: + def __init__(self, name): + self._name = name + self._entries = [] + self._tags = {} + print >>sys.stderr, ' Created struct: %s' % name + + def AddEntry(self, entry): + if self._tags.has_key(entry.Tag()): + raise RpcGenError( + 'Entry "%s" duplicates tag number %d from "%s" ' + 'around line %d' % (entry.Name(), entry.Tag(), + self._tags[entry.Tag()], line_count)) + self._entries.append(entry) + self._tags[entry.Tag()] = entry.Name() + print >>sys.stderr, ' Added entry: %s' % entry.Name() + + def Name(self): + return self._name + + def EntryTagName(self, entry): + """Creates the name inside an enumeration for distinguishing data + types.""" + name = "%s_%s" % (self._name, entry.Name()) + return name.upper() + + def PrintIndented(self, file, ident, code): + """Takes an array, add indentation to each entry and prints it.""" + for entry in code: + print >>file, '%s%s' % (ident, entry) + +class StructCCode(Struct): + """ Knows how to generate C code for a struct """ + + def __init__(self, name): + Struct.__init__(self, name) + + def PrintTags(self, file): + """Prints the tag definitions for a structure.""" + print >>file, '/* Tag definition for %s */' % self._name + print >>file, 'enum %s_ {' % self._name.lower() + for entry in self._entries: + print >>file, ' %s=%d,' % (self.EntryTagName(entry), + entry.Tag()) + print >>file, ' %s_MAX_TAGS' % (self._name.upper()) + print >>file, '};\n' + + def PrintForwardDeclaration(self, file): + print >>file, 'struct %s;' % self._name + + def PrintDeclaration(self, file): + print >>file, '/* Structure declaration for %s */' % self._name + print >>file, 'struct %s_access_ {' % self._name + for entry in self._entries: + dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name()) + dcl.extend( + entry.GetDeclaration('(*%s_get)' % entry.Name())) + if entry.Array(): + dcl.extend( + entry.AddDeclaration('(*%s_add)' % entry.Name())) + self.PrintIndented(file, ' ', dcl) + print >>file, '};\n' + + print >>file, 'struct %s {' % self._name + print >>file, ' struct %s_access_ *base;\n' % self._name + for entry in self._entries: + dcl = entry.Declaration() + self.PrintIndented(file, ' ', dcl) + print >>file, '' + for entry in self._entries: + print >>file, ' ev_uint8_t %s_set;' % entry.Name() + print >>file, '};\n' + + print >>file, \ +"""struct %(name)s *%(name)s_new(void); +struct %(name)s *%(name)s_new_with_arg(void *); +void %(name)s_free(struct %(name)s *); +void %(name)s_clear(struct %(name)s *); +void %(name)s_marshal(struct evbuffer *, const struct %(name)s *); +int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *); +int %(name)s_complete(struct %(name)s *); +void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t, + const struct %(name)s *); +int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t, + struct %(name)s *);""" % { 'name' : self._name } + + + # Write a setting function of every variable + for entry in self._entries: + self.PrintIndented(file, '', entry.AssignDeclaration( + entry.AssignFuncName())) + self.PrintIndented(file, '', entry.GetDeclaration( + entry.GetFuncName())) + if entry.Array(): + self.PrintIndented(file, '', entry.AddDeclaration( + entry.AddFuncName())) + + print >>file, '/* --- %s done --- */\n' % self._name + + def PrintCode(self, file): + print >>file, ('/*\n' + ' * Implementation of %s\n' + ' */\n') % self._name + + print >>file, \ + 'static struct %(name)s_access_ __%(name)s_base = {' % \ + { 'name' : self._name } + for entry in self._entries: + self.PrintIndented(file, ' ', entry.CodeBase()) + print >>file, '};\n' + + # Creation + print >>file, ( + 'struct %(name)s *\n' + '%(name)s_new(void)\n' + '{\n' + ' return %(name)s_new_with_arg(NULL);\n' + '}\n' + '\n' + 'struct %(name)s *\n' + '%(name)s_new_with_arg(void *unused)\n' + '{\n' + ' struct %(name)s *tmp;\n' + ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n' + ' event_warn("%%s: malloc", __func__);\n' + ' return (NULL);\n' + ' }\n' + ' tmp->base = &__%(name)s_base;\n') % { 'name' : self._name } + + for entry in self._entries: + self.PrintIndented(file, ' ', entry.CodeInitialize('tmp')) + print >>file, ' tmp->%s_set = 0;\n' % entry.Name() + + print >>file, ( + ' return (tmp);\n' + '}\n') + + # Adding + for entry in self._entries: + if entry.Array(): + self.PrintIndented(file, '', entry.CodeAdd()) + print >>file, '' + + # Assigning + for entry in self._entries: + self.PrintIndented(file, '', entry.CodeAssign()) + print >>file, '' + + # Getting + for entry in self._entries: + self.PrintIndented(file, '', entry.CodeGet()) + print >>file, '' + + # Clearing + print >>file, ( 'void\n' + '%(name)s_clear(struct %(name)s *tmp)\n' + '{' + ) % { 'name' : self._name } + for entry in self._entries: + self.PrintIndented(file, ' ', entry.CodeClear('tmp')) + + print >>file, '}\n' + + # Freeing + print >>file, ( 'void\n' + '%(name)s_free(struct %(name)s *tmp)\n' + '{' + ) % { 'name' : self._name } + + for entry in self._entries: + self.PrintIndented(file, ' ', entry.CodeFree('tmp')) + + print >>file, (' free(tmp);\n' + '}\n') + + # Marshaling + print >>file, ('void\n' + '%(name)s_marshal(struct evbuffer *evbuf, ' + 'const struct %(name)s *tmp)' + '{') % { 'name' : self._name } + for entry in self._entries: + indent = ' ' + # Optional entries do not have to be set + if entry.Optional(): + indent += ' ' + print >>file, ' if (tmp->%s_set) {' % entry.Name() + self.PrintIndented( + file, indent, + entry.CodeMarshal('evbuf', self.EntryTagName(entry), + entry.GetVarName('tmp'), + entry.GetVarLen('tmp'))) + if entry.Optional(): + print >>file, ' }' + + print >>file, '}\n' + + # Unmarshaling + print >>file, ('int\n' + '%(name)s_unmarshal(struct %(name)s *tmp, ' + ' struct evbuffer *evbuf)\n' + '{\n' + ' ev_uint32_t tag;\n' + ' while (evbuffer_get_length(evbuf) > 0) {\n' + ' if (evtag_peek(evbuf, &tag) == -1)\n' + ' return (-1);\n' + ' switch (tag) {\n' + ) % { 'name' : self._name } + for entry in self._entries: + print >>file, ' case %s:\n' % self.EntryTagName(entry) + if not entry.Array(): + print >>file, ( + ' if (tmp->%s_set)\n' + ' return (-1);' + ) % (entry.Name()) + + self.PrintIndented( + file, ' ', + entry.CodeUnmarshal('evbuf', + self.EntryTagName(entry), + entry.GetVarName('tmp'), + entry.GetVarLen('tmp'))) + + print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() + + ' break;\n' ) + print >>file, ( ' default:\n' + ' return -1;\n' + ' }\n' + ' }\n' ) + # Check if it was decoded completely + print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n' + ' return (-1);' + ) % { 'name' : self._name } + + # Successfully decoded + print >>file, ( ' return (0);\n' + '}\n') + + # Checking if a structure has all the required data + print >>file, ( + 'int\n' + '%(name)s_complete(struct %(name)s *msg)\n' + '{' ) % { 'name' : self._name } + for entry in self._entries: + if not entry.Optional(): + code = [ + 'if (!msg->%(name)s_set)', + ' return (-1);' ] + code = TranslateList(code, entry.GetTranslation()) + self.PrintIndented( + file, ' ', code) + + self.PrintIndented( + file, ' ', + entry.CodeComplete('msg', entry.GetVarName('msg'))) + print >>file, ( + ' return (0);\n' + '}\n' ) + + # Complete message unmarshaling + print >>file, ( + 'int\n' + 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, ' + 'ev_uint32_t need_tag, struct %(name)s *msg)\n' + '{\n' + ' ev_uint32_t tag;\n' + ' int res = -1;\n' + '\n' + ' struct evbuffer *tmp = evbuffer_new();\n' + '\n' + ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1' + ' || tag != need_tag)\n' + ' goto error;\n' + '\n' + ' if (%(name)s_unmarshal(msg, tmp) == -1)\n' + ' goto error;\n' + '\n' + ' res = 0;\n' + '\n' + ' error:\n' + ' evbuffer_free(tmp);\n' + ' return (res);\n' + '}\n' ) % { 'name' : self._name } + + # Complete message marshaling + print >>file, ( + 'void\n' + 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, ' + 'const struct %(name)s *msg)\n' + '{\n' + ' struct evbuffer *_buf = evbuffer_new();\n' + ' assert(_buf != NULL);\n' + ' %(name)s_marshal(_buf, msg);\n' + ' evtag_marshal_buffer(evbuf, tag, _buf);\n ' + ' evbuffer_free(_buf);\n' + '}\n' ) % { 'name' : self._name } + +class Entry: + def __init__(self, type, name, tag): + self._type = type + self._name = name + self._tag = int(tag) + self._ctype = type + self._optional = 0 + self._can_be_array = 0 + self._array = 0 + self._line_count = -1 + self._struct = None + self._refname = None + + self._optpointer = True + self._optaddarg = True + + def GetInitializer(self): + assert 0, "Entry does not provide initializer" + + def SetStruct(self, struct): + self._struct = struct + + def LineCount(self): + assert self._line_count != -1 + return self._line_count + + def SetLineCount(self, number): + self._line_count = number + + def Array(self): + return self._array + + def Optional(self): + return self._optional + + def Tag(self): + return self._tag + + def Name(self): + return self._name + + def Type(self): + return self._type + + def MakeArray(self, yes=1): + self._array = yes + + def MakeOptional(self): + self._optional = 1 + + def Verify(self): + if self.Array() and not self._can_be_array: + raise RpcGenError( + 'Entry "%s" cannot be created as an array ' + 'around line %d' % (self._name, self.LineCount())) + if not self._struct: + raise RpcGenError( + 'Entry "%s" does not know which struct it belongs to ' + 'around line %d' % (self._name, self.LineCount())) + if self._optional and self._array: + raise RpcGenError( + 'Entry "%s" has illegal combination of optional and array ' + 'around line %d' % (self._name, self.LineCount())) + + def GetTranslation(self, extradict = {}): + mapping = { + "parent_name" : self._struct.Name(), + "name" : self._name, + "ctype" : self._ctype, + "refname" : self._refname, + "optpointer" : self._optpointer and "*" or "", + "optreference" : self._optpointer and "&" or "", + "optaddarg" : + self._optaddarg and ", const %s value" % self._ctype or "" + } + for (k, v) in extradict.items(): + mapping[k] = v + + return mapping + + def GetVarName(self, var): + return '%(var)s->%(name)s_data' % self.GetTranslation({ 'var' : var }) + + def GetVarLen(self, var): + return 'sizeof(%s)' % self._ctype + + def GetFuncName(self): + return '%s_%s_get' % (self._struct.Name(), self._name) + + def GetDeclaration(self, funcname): + code = [ 'int %s(struct %s *, %s *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def CodeGet(self): + code = ( + 'int', + '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, ' + '%(ctype)s *value)', + '{', + ' if (msg->%(name)s_set != 1)', + ' return (-1);', + ' *value = msg->%(name)s_data;', + ' return (0);', + '}' ) + code = '\n'.join(code) + code = code % self.GetTranslation() + return code.split('\n') + + def AssignFuncName(self): + return '%s_%s_assign' % (self._struct.Name(), self._name) + + def AddFuncName(self): + return '%s_%s_add' % (self._struct.Name(), self._name) + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, const %s);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def CodeAssign(self): + code = [ 'int', + '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,' + ' const %(ctype)s value)', + '{', + ' msg->%(name)s_set = 1;', + ' msg->%(name)s_data = value;', + ' return (0);', + '}' ] + code = '\n'.join(code) + code = code % self.GetTranslation() + return code.split('\n') + + def CodeClear(self, structname): + code = [ '%s->%s_set = 0;' % (structname, self.Name()) ] + + return code + + def CodeComplete(self, structname, var_name): + return [] + + def CodeFree(self, name): + return [] + + def CodeBase(self): + code = [ + '%(parent_name)s_%(name)s_assign,', + '%(parent_name)s_%(name)s_get,' + ] + if self.Array(): + code.append('%(parent_name)s_%(name)s_add,') + + code = '\n'.join(code) + code = code % self.GetTranslation() + return code.split('\n') + +class EntryBytes(Entry): + def __init__(self, type, name, tag, length): + # Init base class + Entry.__init__(self, type, name, tag) + + self._length = length + self._ctype = 'ev_uint8_t' + + def GetInitializer(self): + return "NULL" + + def GetVarLen(self, var): + return '(%s)' % self._length + + def CodeArrayAdd(self, varname, value): + # XXX: copy here + return [ '%(varname)s = NULL;' % { 'varname' : varname } ] + + def GetDeclaration(self, funcname): + code = [ 'int %s(struct %s *, %s **);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, const %s *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def Declaration(self): + dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)] + + return dcl + + def CodeGet(self): + name = self._name + code = [ 'int', + '%s_%s_get(struct %s *msg, %s **value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1)' % name, + ' return (-1);', + ' *value = msg->%s_data;' % name, + ' return (0);', + '}' ] + return code + + def CodeAssign(self): + name = self._name + code = [ 'int', + '%s_%s_assign(struct %s *msg, const %s *value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' msg->%s_set = 1;' % name, + ' memcpy(msg->%s_data, value, %s);' % ( + name, self._length), + ' return (0);', + '}' ] + return code + + def CodeUnmarshal(self, buf, tag_name, var_name, var_len): + code = [ 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, ' + '%(var)s, %(varlen)s) == -1) {', + ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', + ' return (-1);', + '}' + ] + return TranslateList(code, + self.GetTranslation({ + 'var' : var_name, + 'varlen' : var_len, + 'buf' : buf, + 'tag' : tag_name })) + + def CodeMarshal(self, buf, tag_name, var_name, var_len): + code = ['evtag_marshal(%s, %s, %s, %s);' % ( + buf, tag_name, var_name, var_len)] + return code + + def CodeClear(self, structname): + code = [ '%s->%s_set = 0;' % (structname, self.Name()), + 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( + structname, self._name, structname, self._name)] + + return code + + def CodeInitialize(self, name): + code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( + name, self._name, name, self._name)] + return code + + def Verify(self): + if not self._length: + raise RpcGenError( + 'Entry "%s" needs a length ' + 'around line %d' % (self._name, self.LineCount())) + + Entry.Verify(self) + +class EntryInt(Entry): + def __init__(self, type, name, tag, bits=32): + # Init base class + Entry.__init__(self, type, name, tag) + + self._can_be_array = 1 + if bits == 32: + self._ctype = 'ev_uint32_t' + self._marshal_type = 'int' + if bits == 64: + self._ctype = 'ev_uint64_t' + self._marshal_type = 'int64' + + def GetInitializer(self): + return "0" + + def CodeArrayFree(self, var): + return [] + + def CodeArrayAssign(self, varname, srcvar): + return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname, + 'srcvar' : srcvar } ] + + def CodeArrayAdd(self, varname, value): + """Returns a new entry of this type.""" + return [ '%(varname)s = %(value)s;' % { 'varname' : varname, + 'value' : value } ] + + def CodeUnmarshal(self, buf, tag_name, var_name, var_len): + code = [ + 'if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {', + ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', + ' return (-1);', + '}' ] + code = '\n'.join(code) % self.GetTranslation({ + 'ma' : self._marshal_type, + 'buf' : buf, + 'tag' : tag_name, + 'var' : var_name }) + return code.split('\n') + + def CodeMarshal(self, buf, tag_name, var_name, var_len): + code = [ + 'evtag_marshal_%s(%s, %s, %s);' % ( + self._marshal_type, buf, tag_name, var_name)] + return code + + def Declaration(self): + dcl = ['%s %s_data;' % (self._ctype, self._name)] + + return dcl + + def CodeInitialize(self, name): + code = ['%s->%s_data = 0;' % (name, self._name)] + return code + +class EntryString(Entry): + def __init__(self, type, name, tag): + # Init base class + Entry.__init__(self, type, name, tag) + + self._can_be_array = 1 + self._ctype = 'char *' + + def GetInitializer(self): + return "NULL" + + def CodeArrayFree(self, varname): + code = [ + 'if (%(var)s != NULL) free(%(var)s);' ] + + return TranslateList(code, { 'var' : varname }) + + def CodeArrayAssign(self, varname, srcvar): + code = [ + 'if (%(var)s != NULL)', + ' free(%(var)s);', + '%(var)s = strdup(%(srcvar)s);', + 'if (%(var)s == NULL) {', + ' event_warnx("%%s: strdup", __func__);', + ' return (-1);', + '}' ] + + return TranslateList(code, { 'var' : varname, + 'srcvar' : srcvar }) + + def CodeArrayAdd(self, varname, value): + code = [ + 'if (%(value)s != NULL) {', + ' %(var)s = strdup(%(value)s);', + ' if (%(var)s == NULL) {', + ' goto error;', + ' }', + '} else {', + ' %(var)s = NULL;', + '}' ] + + return TranslateList(code, { 'var' : varname, + 'value' : value }) + + def GetVarLen(self, var): + return 'strlen(%s)' % self.GetVarName(var) + + def CodeMakeInitalize(self, varname): + return '%(varname)s = NULL;' % { 'varname' : varname } + + def CodeAssign(self): + name = self._name + code = """int +%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, + const %(ctype)s value) +{ + if (msg->%(name)s_data != NULL) + free(msg->%(name)s_data); + if ((msg->%(name)s_data = strdup(value)) == NULL) + return (-1); + msg->%(name)s_set = 1; + return (0); +}""" % self.GetTranslation() + + return code.split('\n') + + def CodeUnmarshal(self, buf, tag_name, var_name, var_len): + code = ['if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {', + ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', + ' return (-1);', + '}' + ] + code = '\n'.join(code) % self.GetTranslation({ + 'buf' : buf, + 'tag' : tag_name, + 'var' : var_name }) + return code.split('\n') + + def CodeMarshal(self, buf, tag_name, var_name, var_len): + code = ['evtag_marshal_string(%s, %s, %s);' % ( + buf, tag_name, var_name)] + return code + + def CodeClear(self, structname): + code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), + ' free(%s->%s_data);' % (structname, self.Name()), + ' %s->%s_data = NULL;' % (structname, self.Name()), + ' %s->%s_set = 0;' % (structname, self.Name()), + '}' + ] + + return code + + def CodeInitialize(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name)] + return code + + def CodeFree(self, name): + code = ['if (%s->%s_data != NULL)' % (name, self._name), + ' free (%s->%s_data);' % (name, self._name)] + + return code + + def Declaration(self): + dcl = ['char *%s_data;' % self._name] + + return dcl + +class EntryStruct(Entry): + def __init__(self, type, name, tag, refname): + # Init base class + Entry.__init__(self, type, name, tag) + + self._optpointer = False + self._can_be_array = 1 + self._refname = refname + self._ctype = 'struct %s*' % refname + self._optaddarg = False + + def GetInitializer(self): + return "NULL" + + def GetVarLen(self, var): + return '-1' + + def CodeArrayAdd(self, varname, value): + code = [ + '%(varname)s = %(refname)s_new();', + 'if (%(varname)s == NULL)', + ' goto error;' ] + + return TranslateList(code, self.GetTranslation({ 'varname' : varname })) + + def CodeArrayFree(self, var): + code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation( + { 'var' : var }) ] + return code + + def CodeArrayAssign(self, var, srcvar): + code = [ + 'int had_error = 0;', + 'struct evbuffer *tmp = NULL;', + '%(refname)s_clear(%(var)s);', + 'if ((tmp = evbuffer_new()) == NULL) {', + ' event_warn("%%s: evbuffer_new()", __func__);', + ' had_error = 1;', + ' goto done;', + '}', + '%(refname)s_marshal(tmp, %(srcvar)s);', + 'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {', + ' event_warnx("%%s: %(refname)s_unmarshal", __func__);', + ' had_error = 1;', + ' goto done;', + '}', + 'done:' + 'if (tmp != NULL)', + ' evbuffer_free(tmp);', + 'if (had_error) {', + ' %(refname)s_clear(%(var)s);', + ' return (-1);', + '}' ] + + return TranslateList(code, self.GetTranslation({ + 'var' : var, + 'srcvar' : srcvar})) + + def CodeGet(self): + name = self._name + code = [ 'int', + '%s_%s_get(struct %s *msg, %s *value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1) {' % name, + ' msg->%s_data = %s_new();' % (name, self._refname), + ' if (msg->%s_data == NULL)' % name, + ' return (-1);', + ' msg->%s_set = 1;' % name, + ' }', + ' *value = msg->%s_data;' % name, + ' return (0);', + '}' ] + return code + + def CodeAssign(self): + name = self._name + code = """int +%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, + const %(ctype)s value) +{ + struct evbuffer *tmp = NULL; + if (msg->%(name)s_set) { + %(refname)s_clear(msg->%(name)s_data); + msg->%(name)s_set = 0; + } else { + msg->%(name)s_data = %(refname)s_new(); + if (msg->%(name)s_data == NULL) { + event_warn("%%s: %(refname)s_new()", __func__); + goto error; + } + } + if ((tmp = evbuffer_new()) == NULL) { + event_warn("%%s: evbuffer_new()", __func__); + goto error; + } + %(refname)s_marshal(tmp, value); + if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) { + event_warnx("%%s: %(refname)s_unmarshal", __func__); + goto error; + } + msg->%(name)s_set = 1; + evbuffer_free(tmp); + return (0); + error: + if (tmp != NULL) + evbuffer_free(tmp); + if (msg->%(name)s_data != NULL) { + %(refname)s_free(msg->%(name)s_data); + msg->%(name)s_data = NULL; + } + return (-1); +}""" % self.GetTranslation() + return code.split('\n') + + def CodeComplete(self, structname, var_name): + code = [ 'if (%(structname)s->%(name)s_set && ' + '%(refname)s_complete(%(var)s) == -1)', + ' return (-1);' ] + + return TranslateList(code, self.GetTranslation({ + 'structname' : structname, + 'var' : var_name })) + + def CodeUnmarshal(self, buf, tag_name, var_name, var_len): + code = ['%(var)s = %(refname)s_new();', + 'if (%(var)s == NULL)', + ' return (-1);', + 'if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, ' + '%(var)s) == -1) {', + ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', + ' return (-1);', + '}' + ] + code = '\n'.join(code) % self.GetTranslation({ + 'buf' : buf, + 'tag' : tag_name, + 'var' : var_name }) + return code.split('\n') + + def CodeMarshal(self, buf, tag_name, var_name, var_len): + code = ['evtag_marshal_%s(%s, %s, %s);' % ( + self._refname, buf, tag_name, var_name)] + return code + + def CodeClear(self, structname): + code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), + ' %s_free(%s->%s_data);' % ( + self._refname, structname, self.Name()), + ' %s->%s_data = NULL;' % (structname, self.Name()), + ' %s->%s_set = 0;' % (structname, self.Name()), + '}' + ] + + return code + + def CodeInitialize(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name)] + return code + + def CodeFree(self, name): + code = ['if (%s->%s_data != NULL)' % (name, self._name), + ' %s_free(%s->%s_data);' % ( + self._refname, name, self._name)] + + return code + + def Declaration(self): + dcl = ['%s %s_data;' % (self._ctype, self._name)] + + return dcl + +class EntryVarBytes(Entry): + def __init__(self, type, name, tag): + # Init base class + Entry.__init__(self, type, name, tag) + + self._ctype = 'ev_uint8_t *' + + def GetInitializer(self): + return "NULL" + + def GetVarLen(self, var): + return '%(var)s->%(name)s_length' % self.GetTranslation({ 'var' : var }) + + def CodeArrayAdd(self, varname, value): + # xxx: copy + return [ '%(varname)s = NULL;' % { 'varname' : varname } ] + + def GetDeclaration(self, funcname): + code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def CodeAssign(self): + name = self._name + code = [ 'int', + '%s_%s_assign(struct %s *msg, ' + 'const %s value, ev_uint32_t len)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_data != NULL)' % name, + ' free (msg->%s_data);' % name, + ' msg->%s_data = malloc(len);' % name, + ' if (msg->%s_data == NULL)' % name, + ' return (-1);', + ' msg->%s_set = 1;' % name, + ' msg->%s_length = len;' % name, + ' memcpy(msg->%s_data, value, len);' % name, + ' return (0);', + '}' ] + return code + + def CodeGet(self): + name = self._name + code = [ 'int', + '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1)' % name, + ' return (-1);', + ' *value = msg->%s_data;' % name, + ' *plen = msg->%s_length;' % name, + ' return (0);', + '}' ] + return code + + def CodeUnmarshal(self, buf, tag_name, var_name, var_len): + code = ['if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)', + ' return (-1);', + # We do not want DoS opportunities + 'if (%(varlen)s > evbuffer_get_length(%(buf)s))', + ' return (-1);', + 'if ((%(var)s = malloc(%(varlen)s)) == NULL)', + ' return (-1);', + 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, ' + '%(varlen)s) == -1) {', + ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', + ' return (-1);', + '}' + ] + code = '\n'.join(code) % self.GetTranslation({ + 'buf' : buf, + 'tag' : tag_name, + 'var' : var_name, + 'varlen' : var_len }) + return code.split('\n') + + def CodeMarshal(self, buf, tag_name, var_name, var_len): + code = ['evtag_marshal(%s, %s, %s, %s);' % ( + buf, tag_name, var_name, var_len)] + return code + + def CodeClear(self, structname): + code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), + ' free (%s->%s_data);' % (structname, self.Name()), + ' %s->%s_data = NULL;' % (structname, self.Name()), + ' %s->%s_length = 0;' % (structname, self.Name()), + ' %s->%s_set = 0;' % (structname, self.Name()), + '}' + ] + + return code + + def CodeInitialize(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name), + '%s->%s_length = 0;' % (name, self._name) ] + return code + + def CodeFree(self, name): + code = ['if (%s->%s_data != NULL)' % (name, self._name), + ' free(%s->%s_data);' % (name, self._name)] + + return code + + def Declaration(self): + dcl = ['ev_uint8_t *%s_data;' % self._name, + 'ev_uint32_t %s_length;' % self._name] + + return dcl + +class EntryArray(Entry): + def __init__(self, entry): + # Init base class + Entry.__init__(self, entry._type, entry._name, entry._tag) + + self._entry = entry + self._refname = entry._refname + self._ctype = self._entry._ctype + self._optional = True + self._optpointer = self._entry._optpointer + self._optaddarg = self._entry._optaddarg + + # provide a new function for accessing the variable name + def GetVarName(var_name): + return '%(var)s->%(name)s_data[%(index)s]' % \ + self._entry.GetTranslation({'var' : var_name, + 'index' : self._index}) + self._entry.GetVarName = GetVarName + + def GetInitializer(self): + return "NULL" + + def GetVarName(self, var_name): + return var_name + + def GetVarLen(self, var_name): + return '-1' + + def GetDeclaration(self, funcname): + """Allows direct access to elements of the array.""" + code = [ + 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' % + self.GetTranslation({ 'funcname' : funcname }) ] + return code + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, int, const %s);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AddDeclaration(self, funcname): + code = [ + '%(ctype)s %(optpointer)s ' + '%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);' % \ + self.GetTranslation({ 'funcname' : funcname }) ] + return code + + def CodeGet(self): + code = """int +%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset, + %(ctype)s *value) +{ + if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length) + return (-1); + *value = msg->%(name)s_data[offset]; + return (0); +}""" % self.GetTranslation() + + return code.split('\n') + + def CodeAssign(self): + code = [ + 'int', + '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,', + ' const %(ctype)s value)', + '{', + ' if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)', + ' return (-1);\n', + ' {' ] + code = TranslateList(code, self.GetTranslation()) + + codearrayassign = self._entry.CodeArrayAssign( + 'msg->%(name)s_data[off]' % self.GetTranslation(), 'value') + code += map(lambda x: ' ' + x, codearrayassign) + + code += TranslateList([ + ' }', + ' return (0);', + '}' ], self.GetTranslation()) + + return code + + def CodeAdd(self): + codearrayadd = self._entry.CodeArrayAdd( + 'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(), + 'value') + code = [ + 'static int', + '%(parent_name)s_%(name)s_expand_to_hold_more(' + 'struct %(parent_name)s *msg)', + '{', + ' int tobe_allocated = msg->%(name)s_num_allocated;', + ' %(ctype)s* new_data = NULL;', + ' tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;', + ' new_data = (%(ctype)s*) realloc(msg->%(name)s_data,', + ' tobe_allocated * sizeof(%(ctype)s));', + ' if (new_data == NULL)', + ' return -1;', + ' msg->%(name)s_data = new_data;', + ' msg->%(name)s_num_allocated = tobe_allocated;', + ' return 0;' + '}', + '', + '%(ctype)s %(optpointer)s', + '%(parent_name)s_%(name)s_add(' + 'struct %(parent_name)s *msg%(optaddarg)s)', + '{', + ' if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {', + ' if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)', + ' goto error;', + ' }' ] + + code = TranslateList(code, self.GetTranslation()) + + code += map(lambda x: ' ' + x, codearrayadd) + + code += TranslateList([ + ' msg->%(name)s_set = 1;', + ' return %(optreference)s(msg->%(name)s_data[' + 'msg->%(name)s_length - 1]);', + 'error:', + ' --msg->%(name)s_length;', + ' return (NULL);', + '}' ], self.GetTranslation()) + + return code + + def CodeComplete(self, structname, var_name): + self._index = 'i' + tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name)) + # skip the whole loop if there is nothing to check + if not tmp: + return [] + + translate = self.GetTranslation({ 'structname' : structname }) + code = [ + '{', + ' int i;', + ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ] + + code = TranslateList(code, translate) + + code += map(lambda x: ' ' + x, tmp) + + code += [ + ' }', + '}' ] + + return code + + def CodeUnmarshal(self, buf, tag_name, var_name, var_len): + translate = self.GetTranslation({ 'var' : var_name, + 'buf' : buf, + 'tag' : tag_name, + 'init' : self._entry.GetInitializer()}) + code = [ + 'if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&', + ' %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {', + ' puts("HEY NOW");', + ' return (-1);', + '}'] + + # the unmarshal code directly returns + code = TranslateList(code, translate) + + self._index = '%(var)s->%(name)s_length' % translate + code += self._entry.CodeUnmarshal(buf, tag_name, + self._entry.GetVarName(var_name), + self._entry.GetVarLen(var_name)) + + code += [ '++%(var)s->%(name)s_length;' % translate ] + + return code + + def CodeMarshal(self, buf, tag_name, var_name, var_len): + code = ['{', + ' int i;', + ' for (i = 0; i < %(var)s->%(name)s_length; ++i) {' ] + + self._index = 'i' + code += self._entry.CodeMarshal(buf, tag_name, + self._entry.GetVarName(var_name), + self._entry.GetVarLen(var_name)) + code += [' }', + '}' + ] + + code = "\n".join(code) % self.GetTranslation({ 'var' : var_name }) + + return code.split('\n') + + def CodeClear(self, structname): + translate = self.GetTranslation({ 'structname' : structname }) + codearrayfree = self._entry.CodeArrayFree( + '%(structname)s->%(name)s_data[i]' % self.GetTranslation( + { 'structname' : structname } )) + + code = [ 'if (%(structname)s->%(name)s_set == 1) {' ] + + if codearrayfree: + code += [ + ' int i;', + ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ] + + code = TranslateList(code, translate) + + if codearrayfree: + code += map(lambda x: ' ' + x, codearrayfree) + code += [ + ' }' ] + + code += TranslateList([ + ' free(%(structname)s->%(name)s_data);', + ' %(structname)s->%(name)s_data = NULL;', + ' %(structname)s->%(name)s_set = 0;', + ' %(structname)s->%(name)s_length = 0;', + ' %(structname)s->%(name)s_num_allocated = 0;', + '}' + ], translate) + + return code + + def CodeInitialize(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name), + '%s->%s_length = 0;' % (name, self._name), + '%s->%s_num_allocated = 0;' % (name, self._name)] + return code + + def CodeFree(self, structname): + code = self.CodeClear(structname); + + code += TranslateList([ + 'free(%(structname)s->%(name)s_data);' ], + self.GetTranslation({'structname' : structname })) + + return code + + def Declaration(self): + dcl = ['%s *%s_data;' % (self._ctype, self._name), + 'int %s_length;' % self._name, + 'int %s_num_allocated;' % self._name ] + + return dcl + +def NormalizeLine(line): + global white + global cppcomment + + line = cppcomment.sub('', line) + line = line.strip() + line = white.sub(' ', line) + + return line + +def ProcessOneEntry(factory, newstruct, entry): + optional = 0 + array = 0 + entry_type = '' + name = '' + tag = '' + tag_set = None + separator = '' + fixed_length = '' + + tokens = entry.split(' ') + while tokens: + token = tokens[0] + tokens = tokens[1:] + + if not entry_type: + if not optional and token == 'optional': + optional = 1 + continue + + if not array and token == 'array': + array = 1 + continue + + if not entry_type: + entry_type = token + continue + + if not name: + res = re.match(r'^([^\[\]]+)(\[.*\])?$', token) + if not res: + raise RpcGenError( + 'Cannot parse name: \"%s\" ' + 'around line %d' % (entry, line_count)) + name = res.group(1) + fixed_length = res.group(2) + if fixed_length: + fixed_length = fixed_length[1:-1] + continue + + if not separator: + separator = token + if separator != '=': + raise RpcGenError('Expected "=" after name \"%s\" got %s' + % (name, token)) + continue + + if not tag_set: + tag_set = 1 + if not re.match(r'^(0x)?[0-9]+$', token): + raise RpcGenError('Expected tag number: \"%s\"' % entry) + tag = int(token, 0) + continue + + raise RpcGenError('Cannot parse \"%s\"' % entry) + + if not tag_set: + raise RpcGenError('Need tag number: \"%s\"' % entry) + + # Create the right entry + if entry_type == 'bytes': + if fixed_length: + newentry = factory.EntryBytes(entry_type, name, tag, fixed_length) + else: + newentry = factory.EntryVarBytes(entry_type, name, tag) + elif entry_type == 'int' and not fixed_length: + newentry = factory.EntryInt(entry_type, name, tag) + elif entry_type == 'int64' and not fixed_length: + newentry = factory.EntryInt(entry_type, name, tag, bits=64) + elif entry_type == 'string' and not fixed_length: + newentry = factory.EntryString(entry_type, name, tag) + else: + res = structref.match(entry_type) + if res: + # References another struct defined in our file + newentry = factory.EntryStruct(entry_type, name, tag, res.group(1)) + else: + raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry)) + + structs = [] + + if optional: + newentry.MakeOptional() + if array: + newentry.MakeArray() + + newentry.SetStruct(newstruct) + newentry.SetLineCount(line_count) + newentry.Verify() + + if array: + # We need to encapsulate this entry into a struct + newname = newentry.Name()+ '_array' + + # Now borgify the new entry. + newentry = factory.EntryArray(newentry) + newentry.SetStruct(newstruct) + newentry.SetLineCount(line_count) + newentry.MakeArray() + + newstruct.AddEntry(newentry) + + return structs + +def ProcessStruct(factory, data): + tokens = data.split(' ') + + # First three tokens are: 'struct' 'name' '{' + newstruct = factory.Struct(tokens[1]) + + inside = ' '.join(tokens[3:-1]) + + tokens = inside.split(';') + + structs = [] + + for entry in tokens: + entry = NormalizeLine(entry) + if not entry: + continue + + # It's possible that new structs get defined in here + structs.extend(ProcessOneEntry(factory, newstruct, entry)) + + structs.append(newstruct) + return structs + +def GetNextStruct(file): + global line_count + global cppdirect + + got_struct = 0 + + processed_lines = [] + + have_c_comment = 0 + data = '' + while 1: + line = file.readline() + if not line: + break + + line_count += 1 + line = line[:-1] + + if not have_c_comment and re.search(r'/\*', line): + if re.search(r'/\*.*?\*/', line): + line = re.sub(r'/\*.*?\*/', '', line) + else: + line = re.sub(r'/\*.*$', '', line) + have_c_comment = 1 + + if have_c_comment: + if not re.search(r'\*/', line): + continue + have_c_comment = 0 + line = re.sub(r'^.*\*/', '', line) + + line = NormalizeLine(line) + + if not line: + continue + + if not got_struct: + if re.match(r'#include ["<].*[>"]', line): + cppdirect.append(line) + continue + + if re.match(r'^#(if( |def)|endif)', line): + cppdirect.append(line) + continue + + if re.match(r'^#define', line): + headerdirect.append(line) + continue + + if not structdef.match(line): + raise RpcGenError('Missing struct on line %d: %s' + % (line_count, line)) + else: + got_struct = 1 + data += line + continue + + # We are inside the struct + tokens = line.split('}') + if len(tokens) == 1: + data += ' ' + line + continue + + if len(tokens[1]): + raise RpcGenError('Trailing garbage after struct on line %d' + % line_count) + + # We found the end of the struct + data += ' %s}' % tokens[0] + break + + # Remove any comments, that might be in there + data = re.sub(r'/\*.*\*/', '', data) + + return data + + +def Parse(factory, file): + """ + Parses the input file and returns C code and corresponding header file. + """ + + entities = [] + + while 1: + # Just gets the whole struct nicely formatted + data = GetNextStruct(file) + + if not data: + break + + entities.extend(ProcessStruct(factory, data)) + + return entities + +class CCodeGenerator: + def __init__(self): + pass + + def GuardName(self, name): + # Use the complete provided path to the input file, with all + # non-identifier characters replaced with underscores, to + # reduce the chance of a collision between guard macros. + return '_' + nonident.sub('_', name).upper() + '_' + + def HeaderPreamble(self, name): + guard = self.GuardName(name) + pre = ( + '/*\n' + ' * Automatically generated from %s\n' + ' */\n\n' + '#ifndef %s\n' + '#define %s\n\n' ) % ( + name, guard, guard) + + for statement in headerdirect: + pre += '%s\n' % statement + if headerdirect: + pre += '\n' + + pre += ( + '#include /* for ev_uint*_t */\n' + '#include \n' + ) + + return pre + + def HeaderPostamble(self, name): + guard = self.GuardName(name) + return '#endif /* %s */' % guard + + def BodyPreamble(self, name, header_file): + global _NAME + global _VERSION + + slash = header_file.rfind('/') + if slash != -1: + header_file = header_file[slash+1:] + + pre = ( '/*\n' + ' * Automatically generated from %s\n' + ' * by %s/%s. DO NOT EDIT THIS FILE.\n' + ' */\n\n' ) % (name, _NAME, _VERSION) + pre += ( '#include \n' + '#include \n' + '#include \n' + '#include \n' + '#include \n' + '#include \n' + '#include \n\n' + '#ifdef _EVENT___func__\n' + '#define __func__ _EVENT___func__\n' + '#endif\n\n' + ) + + for statement in cppdirect: + pre += '%s\n' % statement + + pre += '\n#include "%s"\n\n' % header_file + + pre += 'void event_warn(const char *fmt, ...);\n' + pre += 'void event_warnx(const char *fmt, ...);\n\n' + + return pre + + def HeaderFilename(self, filename): + return '.'.join(filename.split('.')[:-1]) + '.h' + + def CodeFilename(self, filename): + return '.'.join(filename.split('.')[:-1]) + '.gen.c' + + def Struct(self, name): + return StructCCode(name) + + def EntryBytes(self, entry_type, name, tag, fixed_length): + return EntryBytes(entry_type, name, tag, fixed_length) + + def EntryVarBytes(self, entry_type, name, tag): + return EntryVarBytes(entry_type, name, tag) + + def EntryInt(self, entry_type, name, tag, bits=32): + return EntryInt(entry_type, name, tag, bits) + + def EntryString(self, entry_type, name, tag): + return EntryString(entry_type, name, tag) + + def EntryStruct(self, entry_type, name, tag, struct_name): + return EntryStruct(entry_type, name, tag, struct_name) + + def EntryArray(self, entry): + return EntryArray(entry) + +class Usage(RpcGenError): + def __init__(self, argv0): + RpcGenError.__init__("usage: %s input.rpc [[output.h] output.c]" + % argv0) + +class CommandLine: + def __init__(self, argv): + """Initialize a command-line to launch event_rpcgen, as if + from a command-line with CommandLine(sys.argv). If you're + calling this directly, remember to provide a dummy value + for sys.argv[0] + """ + self.filename = None + self.header_file = None + self.impl_file = None + self.factory = CCodeGenerator() + + if len(argv) < 2 or len(argv) > 4: + raise Usage(argv[0]) + + self.filename = argv[1].replace('\\', '/') + if len(argv) == 3: + self.impl_file = argv[2].replace('\\', '/') + if len(argv) == 4: + self.header_file = argv[2].replace('\\', '/') + self.impl_file = argv[3].replace('\\', '/') + + if not self.filename: + raise Usage(argv[0]) + + if not self.impl_file: + self.impl_file = self.factory.CodeFilename(self.filename) + + if not self.header_file: + self.header_file = self.factory.HeaderFilename(self.impl_file) + + if not self.impl_file.endswith('.c'): + raise RpcGenError("can only generate C implementation files") + if not self.header_file.endswith('.h'): + raise RpcGenError("can only generate C header files") + + def run(self): + filename = self.filename + header_file = self.header_file + impl_file = self.impl_file + factory = self.factory + + print >>sys.stderr, 'Reading \"%s\"' % filename + + fp = open(filename, 'r') + entities = Parse(factory, fp) + fp.close() + + print >>sys.stderr, '... creating "%s"' % header_file + header_fp = open(header_file, 'w') + print >>header_fp, factory.HeaderPreamble(filename) + + # Create forward declarations: allows other structs to reference + # each other + for entry in entities: + entry.PrintForwardDeclaration(header_fp) + print >>header_fp, '' + + for entry in entities: + entry.PrintTags(header_fp) + entry.PrintDeclaration(header_fp) + print >>header_fp, factory.HeaderPostamble(filename) + header_fp.close() + + print >>sys.stderr, '... creating "%s"' % impl_file + impl_fp = open(impl_file, 'w') + print >>impl_fp, factory.BodyPreamble(filename, header_file) + for entry in entities: + entry.PrintCode(impl_fp) + impl_fp.close() + +if __name__ == '__main__': + try: + CommandLine(sys.argv).run() + sys.exit(0) + + except RpcGenError, e: + print >>sys.stderr, e + sys.exit(1) + + except EnvironmentError, e: + if e.filename and e.strerror: + print >>sys.stderr, "%s: %s" % (e.filename, e.strerror) + sys.exit(1) + elif e.strerror: + print >> sys.stderr, e.strerror + sys.exit(1) + else: + raise diff --git a/libevent/event_tagging.c b/libevent/event_tagging.c new file mode 100644 index 0000000..a83e719 --- /dev/null +++ b/libevent/event_tagging.c @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2003-2009 Niels Provos + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#include "event2/event-config.h" + +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_PARAM_H +#include +#endif + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#undef WIN32_LEAN_AND_MEAN +#else +#include +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#ifndef WIN32 +#include +#endif +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#include + +#include "event2/event.h" +#include "event2/tag.h" +#include "event2/buffer.h" +#include "log-internal.h" +#include "mm-internal.h" +#include "util-internal.h" + +/* + Here's our wire format: + + Stream = TaggedData* + + TaggedData = Tag Length Data + where the integer value of 'Length' is the length of 'data'. + + Tag = HByte* LByte + where HByte is a byte with the high bit set, and LByte is a byte + with the high bit clear. The integer value of the tag is taken + by concatenating the lower 7 bits from all the tags. So for example, + the tag 0x66 is encoded as [66], whereas the tag 0x166 is encoded as + [82 66] + + Length = Integer + + Integer = NNibbles Nibble* Padding? + where NNibbles is a 4-bit value encoding the number of nibbles-1, + and each Nibble is 4 bits worth of encoded integer, in big-endian + order. If the total encoded integer size is an odd number of nibbles, + a final padding nibble with value 0 is appended. +*/ + +int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf); +int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf); +int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag); +int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf); + +void +evtag_init(void) +{ +} + +/* + * We encode integers by nibbles; the first nibble contains the number + * of significant nibbles - 1; this allows us to encode up to 64-bit + * integers. This function is byte-order independent. + * + * @param number a 32-bit unsigned integer to encode + * @param data a pointer to where the data should be written. Must + * have at least 5 bytes free. + * @return the number of bytes written into data. + */ + +#define ENCODE_INT_INTERNAL(data, number) do { \ + int off = 1, nibbles = 0; \ + \ + memset(data, 0, sizeof(number)+1); \ + while (number) { \ + if (off & 0x1) \ + data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); \ + else \ + data[off/2] = (data[off/2] & 0x0f) | \ + ((number & 0x0f) << 4); \ + number >>= 4; \ + off++; \ + } \ + \ + if (off > 2) \ + nibbles = off - 2; \ + \ + /* Off - 1 is the number of encoded nibbles */ \ + data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); \ + \ + return ((off + 1) / 2); \ +} while (0) + +static inline int +encode_int_internal(ev_uint8_t *data, ev_uint32_t number) +{ + ENCODE_INT_INTERNAL(data, number); +} + +static inline int +encode_int64_internal(ev_uint8_t *data, ev_uint64_t number) +{ + ENCODE_INT_INTERNAL(data, number); +} + +void +evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number) +{ + ev_uint8_t data[5]; + int len = encode_int_internal(data, number); + evbuffer_add(evbuf, data, len); +} + +void +evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number) +{ + ev_uint8_t data[9]; + int len = encode_int64_internal(data, number); + evbuffer_add(evbuf, data, len); +} + +/* + * Support variable length encoding of tags; we use the high bit in each + * octet as a continuation signal. + */ + +int +evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag) +{ + int bytes = 0; + ev_uint8_t data[5]; + + memset(data, 0, sizeof(data)); + do { + ev_uint8_t lower = tag & 0x7f; + tag >>= 7; + + if (tag) + lower |= 0x80; + + data[bytes++] = lower; + } while (tag); + + if (evbuf != NULL) + evbuffer_add(evbuf, data, bytes); + + return (bytes); +} + +static int +decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain) +{ + ev_uint32_t number = 0; + size_t len = evbuffer_get_length(evbuf); + ev_uint8_t *data; + size_t count = 0; + int shift = 0, done = 0; + + /* + * the encoding of a number is at most one byte more than its + * storage size. however, it may also be much smaller. + */ + data = evbuffer_pullup( + evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1); + + while (count++ < len) { + ev_uint8_t lower = *data++; + number |= (lower & 0x7f) << shift; + shift += 7; + + if (!(lower & 0x80)) { + done = 1; + break; + } + } + + if (!done) + return (-1); + + if (dodrain) + evbuffer_drain(evbuf, count); + + if (ptag != NULL) + *ptag = number; + + return count > INT_MAX ? INT_MAX : (int)(count); +} + +int +evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf) +{ + return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */)); +} + +/* + * Marshal a data type, the general format is as follows: + * + * tag number: one byte; length: var bytes; payload: var bytes + */ + +void +evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, + const void *data, ev_uint32_t len) +{ + evtag_encode_tag(evbuf, tag); + evtag_encode_int(evbuf, len); + evbuffer_add(evbuf, (void *)data, len); +} + +void +evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag, + struct evbuffer *data) +{ + evtag_encode_tag(evbuf, tag); + /* XXX support more than UINT32_MAX data */ + evtag_encode_int(evbuf, (ev_uint32_t)evbuffer_get_length(data)); + evbuffer_add_buffer(evbuf, data); +} + +/* Marshaling for integers */ +void +evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer) +{ + ev_uint8_t data[5]; + int len = encode_int_internal(data, integer); + + evtag_encode_tag(evbuf, tag); + evtag_encode_int(evbuf, len); + evbuffer_add(evbuf, data, len); +} + +void +evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint64_t integer) +{ + ev_uint8_t data[9]; + int len = encode_int64_internal(data, integer); + + evtag_encode_tag(evbuf, tag); + evtag_encode_int(evbuf, len); + evbuffer_add(evbuf, data, len); +} + +void +evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string) +{ + /* TODO support strings longer than UINT32_MAX ? */ + evtag_marshal(buf, tag, string, (ev_uint32_t)strlen(string)); +} + +void +evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv) +{ + ev_uint8_t data[10]; + int len = encode_int_internal(data, tv->tv_sec); + len += encode_int_internal(data + len, tv->tv_usec); + evtag_marshal(evbuf, tag, data, len); +} + +#define DECODE_INT_INTERNAL(number, maxnibbles, pnumber, evbuf, offset) \ +do { \ + ev_uint8_t *data; \ + ev_ssize_t len = evbuffer_get_length(evbuf) - offset; \ + int nibbles = 0; \ + \ + if (len <= 0) \ + return (-1); \ + \ + /* XXX(niels): faster? */ \ + data = evbuffer_pullup(evbuf, offset + 1) + offset; \ + \ + nibbles = ((data[0] & 0xf0) >> 4) + 1; \ + if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len) \ + return (-1); \ + len = (nibbles >> 1) + 1; \ + \ + data = evbuffer_pullup(evbuf, offset + len) + offset; \ + \ + while (nibbles > 0) { \ + number <<= 4; \ + if (nibbles & 0x1) \ + number |= data[nibbles >> 1] & 0x0f; \ + else \ + number |= (data[nibbles >> 1] & 0xf0) >> 4; \ + nibbles--; \ + } \ + \ + *pnumber = number; \ + \ + return (int)(len); \ +} while (0) + +/* Internal: decode an integer from an evbuffer, without draining it. + * Only integers up to 32-bits are supported. + * + * @param evbuf the buffer to read from + * @param offset an index into the buffer at which we should start reading. + * @param pnumber a pointer to receive the integer. + * @return The length of the number as encoded, or -1 on error. + */ + +static int +decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset) +{ + ev_uint32_t number = 0; + DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset); +} + +static int +decode_int64_internal(ev_uint64_t *pnumber, struct evbuffer *evbuf, int offset) +{ + ev_uint64_t number = 0; + DECODE_INT_INTERNAL(number, 16, pnumber, evbuf, offset); +} + +int +evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf) +{ + int res = decode_int_internal(pnumber, evbuf, 0); + if (res != -1) + evbuffer_drain(evbuf, res); + + return (res == -1 ? -1 : 0); +} + +int +evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf) +{ + int res = decode_int64_internal(pnumber, evbuf, 0); + if (res != -1) + evbuffer_drain(evbuf, res); + + return (res == -1 ? -1 : 0); +} + +int +evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag) +{ + return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */)); +} + +int +evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength) +{ + int res, len; + + len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */); + if (len == -1) + return (-1); + + res = decode_int_internal(plength, evbuf, len); + if (res == -1) + return (-1); + + *plength += res + len; + + return (0); +} + +int +evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength) +{ + int res, len; + + len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */); + if (len == -1) + return (-1); + + res = decode_int_internal(plength, evbuf, len); + if (res == -1) + return (-1); + + return (0); +} + +/* just unmarshals the header and returns the length of the remaining data */ + +int +evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag) +{ + ev_uint32_t len; + + if (decode_tag_internal(ptag, evbuf, 1 /* dodrain */) == -1) + return (-1); + if (evtag_decode_int(&len, evbuf) == -1) + return (-1); + + if (evbuffer_get_length(evbuf) < len) + return (-1); + + return (len); +} + +int +evtag_consume(struct evbuffer *evbuf) +{ + int len; + if ((len = evtag_unmarshal_header(evbuf, NULL)) == -1) + return (-1); + evbuffer_drain(evbuf, len); + + return (0); +} + +/* Reads the data type from an event buffer */ + +int +evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst) +{ + int len; + + if ((len = evtag_unmarshal_header(src, ptag)) == -1) + return (-1); + + if (evbuffer_add(dst, evbuffer_pullup(src, len), len) == -1) + return (-1); + + evbuffer_drain(src, len); + + return (len); +} + +/* Marshaling for integers */ + +int +evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint32_t *pinteger) +{ + ev_uint32_t tag; + ev_uint32_t len; + int result; + + if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1) + return (-1); + if (need_tag != tag) + return (-1); + if (evtag_decode_int(&len, evbuf) == -1) + return (-1); + + if (evbuffer_get_length(evbuf) < len) + return (-1); + + result = decode_int_internal(pinteger, evbuf, 0); + evbuffer_drain(evbuf, len); + if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/ + return (-1); + else + return result; +} + +int +evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint64_t *pinteger) +{ + ev_uint32_t tag; + ev_uint32_t len; + int result; + + if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1) + return (-1); + if (need_tag != tag) + return (-1); + if (evtag_decode_int(&len, evbuf) == -1) + return (-1); + + if (evbuffer_get_length(evbuf) < len) + return (-1); + + result = decode_int64_internal(pinteger, evbuf, 0); + evbuffer_drain(evbuf, len); + if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/ + return (-1); + else + return result; +} + +/* Unmarshal a fixed length tag */ + +int +evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data, + size_t len) +{ + ev_uint32_t tag; + int tag_len; + + /* Now unmarshal a tag and check that it matches the tag we want */ + if ((tag_len = evtag_unmarshal_header(src, &tag)) < 0 || + tag != need_tag) + return (-1); + + if ((size_t)tag_len != len) + return (-1); + + evbuffer_remove(src, data, len); + return (0); +} + +int +evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, + char **pstring) +{ + ev_uint32_t tag; + int tag_len; + + if ((tag_len = evtag_unmarshal_header(evbuf, &tag)) == -1 || + tag != need_tag) + return (-1); + + *pstring = mm_malloc(tag_len + 1); + if (*pstring == NULL) { + event_warn("%s: malloc", __func__); + return -1; + } + evbuffer_remove(evbuf, *pstring, tag_len); + (*pstring)[tag_len] = '\0'; + + return (0); +} + +int +evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag, + struct timeval *ptv) +{ + ev_uint32_t tag; + ev_uint32_t integer; + int len, offset, offset2; + int result = -1; + + if ((len = evtag_unmarshal_header(evbuf, &tag)) == -1) + return (-1); + if (tag != need_tag) + goto done; + if ((offset = decode_int_internal(&integer, evbuf, 0)) == -1) + goto done; + ptv->tv_sec = integer; + if ((offset2 = decode_int_internal(&integer, evbuf, offset)) == -1) + goto done; + ptv->tv_usec = integer; + if (offset + offset2 > len) /* XXX Should this be != instead of > ? */ + goto done; + + result = 0; + done: + evbuffer_drain(evbuf, len); + return result; +} diff --git a/libevent/evhttp.h b/libevent/evhttp.h new file mode 100644 index 0000000..5ce15e6 --- /dev/null +++ b/libevent/evhttp.h @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVHTTP_H_ +#define _EVHTTP_H_ + +/** @file evhttp.h + + An http implementation subsystem for Libevent. + + The header is deprecated in Libevent 2.0 and later; please + use instead. Depending on what functionality you + need, you may also want to include more of the other + headers. + */ + +#include +#include +#include +#include + +#endif /* _EVHTTP_H_ */ diff --git a/libevent/evmap-internal.h b/libevent/evmap-internal.h new file mode 100644 index 0000000..23b5a8a --- /dev/null +++ b/libevent/evmap-internal.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVMAP_H_ +#define _EVMAP_H_ + +/** @file evmap-internal.h + * + * An event_map is a utility structure to map each fd or signal to zero or + * more events. Functions to manipulate event_maps should only be used from + * inside libevent. They generally need to hold the lock on the corresponding + * event_base. + **/ + +struct event_base; +struct event; + +/** Initialize an event_map for use. + */ +void evmap_io_initmap(struct event_io_map* ctx); +void evmap_signal_initmap(struct event_signal_map* ctx); + +/** Remove all entries from an event_map. + + @param ctx the map to clear. + */ +void evmap_io_clear(struct event_io_map* ctx); +void evmap_signal_clear(struct event_signal_map* ctx); + +/** Add an IO event (some combination of EV_READ or EV_WRITE) to an + event_base's list of events on a given file descriptor, and tell the + underlying eventops about the fd if its state has changed. + + Requires that ev is not already added. + + @param base the event_base to operate on. + @param fd the file descriptor corresponding to ev. + @param ev the event to add. +*/ +int evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev); +/** Remove an IO event (some combination of EV_READ or EV_WRITE) to an + event_base's list of events on a given file descriptor, and tell the + underlying eventops about the fd if its state has changed. + + @param base the event_base to operate on. + @param fd the file descriptor corresponding to ev. + @param ev the event to remove. + */ +int evmap_io_del(struct event_base *base, evutil_socket_t fd, struct event *ev); +/** Active the set of events waiting on an event_base for a given fd. + + @param base the event_base to operate on. + @param fd the file descriptor that has become active. + @param events a bitmask of EV_READ|EV_WRITE|EV_ET. +*/ +void evmap_io_active(struct event_base *base, evutil_socket_t fd, short events); + + +/* These functions behave in the same way as evmap_io_*, except they work on + * signals rather than fds. signals use a linear map everywhere; fds use + * either a linear map or a hashtable. */ +int evmap_signal_add(struct event_base *base, int signum, struct event *ev); +int evmap_signal_del(struct event_base *base, int signum, struct event *ev); +void evmap_signal_active(struct event_base *base, evutil_socket_t signum, int ncalls); + +void *evmap_io_get_fdinfo(struct event_io_map *ctx, evutil_socket_t fd); + +void evmap_check_integrity(struct event_base *base); + +#endif /* _EVMAP_H_ */ diff --git a/libevent/evmap.c b/libevent/evmap.c new file mode 100644 index 0000000..69c1067 --- /dev/null +++ b/libevent/evmap.c @@ -0,0 +1,799 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#ifdef WIN32 +#include +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#endif +#include +#if !defined(WIN32) && defined(_EVENT_HAVE_SYS_TIME_H) +#include +#endif +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include +#include +#include + +#include "event-internal.h" +#include "evmap-internal.h" +#include "mm-internal.h" +#include "changelist-internal.h" + +/** An entry for an evmap_io list: notes all the events that want to read or + write on a given fd, and the number of each. + */ +struct evmap_io { + struct event_list events; + ev_uint16_t nread; + ev_uint16_t nwrite; +}; + +/* An entry for an evmap_signal list: notes all the events that want to know + when a signal triggers. */ +struct evmap_signal { + struct event_list events; +}; + +/* On some platforms, fds start at 0 and increment by 1 as they are + allocated, and old numbers get used. For these platforms, we + implement io maps just like signal maps: as an array of pointers to + struct evmap_io. But on other platforms (windows), sockets are not + 0-indexed, not necessarily consecutive, and not necessarily reused. + There, we use a hashtable to implement evmap_io. +*/ +#ifdef EVMAP_USE_HT +struct event_map_entry { + HT_ENTRY(event_map_entry) map_node; + evutil_socket_t fd; + union { /* This is a union in case we need to make more things that can + be in the hashtable. */ + struct evmap_io evmap_io; + } ent; +}; + +/* Helper used by the event_io_map hashtable code; tries to return a good hash + * of the fd in e->fd. */ +static inline unsigned +hashsocket(struct event_map_entry *e) +{ + /* On win32, in practice, the low 2-3 bits of a SOCKET seem not to + * matter. Our hashtable implementation really likes low-order bits, + * though, so let's do the rotate-and-add trick. */ + unsigned h = (unsigned) e->fd; + h += (h >> 2) | (h << 30); + return h; +} + +/* Helper used by the event_io_map hashtable code; returns true iff e1 and e2 + * have the same e->fd. */ +static inline int +eqsocket(struct event_map_entry *e1, struct event_map_entry *e2) +{ + return e1->fd == e2->fd; +} + +HT_PROTOTYPE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket) +HT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket, + 0.5, mm_malloc, mm_realloc, mm_free) + +#define GET_IO_SLOT(x, map, slot, type) \ + do { \ + struct event_map_entry _key, *_ent; \ + _key.fd = slot; \ + _ent = HT_FIND(event_io_map, map, &_key); \ + (x) = _ent ? &_ent->ent.type : NULL; \ + } while (0); + +#define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \ + do { \ + struct event_map_entry _key, *_ent; \ + _key.fd = slot; \ + _HT_FIND_OR_INSERT(event_io_map, map_node, hashsocket, map, \ + event_map_entry, &_key, ptr, \ + { \ + _ent = *ptr; \ + }, \ + { \ + _ent = mm_calloc(1,sizeof(struct event_map_entry)+fdinfo_len); \ + if (EVUTIL_UNLIKELY(_ent == NULL)) \ + return (-1); \ + _ent->fd = slot; \ + (ctor)(&_ent->ent.type); \ + _HT_FOI_INSERT(map_node, map, &_key, _ent, ptr) \ + }); \ + (x) = &_ent->ent.type; \ + } while (0) + +void evmap_io_initmap(struct event_io_map *ctx) +{ + HT_INIT(event_io_map, ctx); +} + +void evmap_io_clear(struct event_io_map *ctx) +{ + struct event_map_entry **ent, **next, *this; + for (ent = HT_START(event_io_map, ctx); ent; ent = next) { + this = *ent; + next = HT_NEXT_RMV(event_io_map, ctx, ent); + mm_free(this); + } + HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */ +} +#endif + +/* Set the variable 'x' to the field in event_map 'map' with fields of type + 'struct type *' corresponding to the fd or signal 'slot'. Set 'x' to NULL + if there are no entries for 'slot'. Does no bounds-checking. */ +#define GET_SIGNAL_SLOT(x, map, slot, type) \ + (x) = (struct type *)((map)->entries[slot]) +/* As GET_SLOT, but construct the entry for 'slot' if it is not present, + by allocating enough memory for a 'struct type', and initializing the new + value by calling the function 'ctor' on it. Makes the function + return -1 on allocation failure. + */ +#define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \ + do { \ + if ((map)->entries[slot] == NULL) { \ + (map)->entries[slot] = \ + mm_calloc(1,sizeof(struct type)+fdinfo_len); \ + if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \ + return (-1); \ + (ctor)((struct type *)(map)->entries[slot]); \ + } \ + (x) = (struct type *)((map)->entries[slot]); \ + } while (0) + +/* If we aren't using hashtables, then define the IO_SLOT macros and functions + as thin aliases over the SIGNAL_SLOT versions. */ +#ifndef EVMAP_USE_HT +#define GET_IO_SLOT(x,map,slot,type) GET_SIGNAL_SLOT(x,map,slot,type) +#define GET_IO_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) \ + GET_SIGNAL_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) +#define FDINFO_OFFSET sizeof(struct evmap_io) +void +evmap_io_initmap(struct event_io_map* ctx) +{ + evmap_signal_initmap(ctx); +} +void +evmap_io_clear(struct event_io_map* ctx) +{ + evmap_signal_clear(ctx); +} +#endif + + +/** Expand 'map' with new entries of width 'msize' until it is big enough + to store a value in 'slot'. + */ +static int +evmap_make_space(struct event_signal_map *map, int slot, int msize) +{ + if (map->nentries <= slot) { + int nentries = map->nentries ? map->nentries : 32; + void **tmp; + + while (nentries <= slot) + nentries <<= 1; + + tmp = (void **)mm_realloc(map->entries, nentries * msize); + if (tmp == NULL) + return (-1); + + memset(&tmp[map->nentries], 0, + (nentries - map->nentries) * msize); + + map->nentries = nentries; + map->entries = tmp; + } + + return (0); +} + +void +evmap_signal_initmap(struct event_signal_map *ctx) +{ + ctx->nentries = 0; + ctx->entries = NULL; +} + +void +evmap_signal_clear(struct event_signal_map *ctx) +{ + if (ctx->entries != NULL) { + int i; + for (i = 0; i < ctx->nentries; ++i) { + if (ctx->entries[i] != NULL) + mm_free(ctx->entries[i]); + } + mm_free(ctx->entries); + ctx->entries = NULL; + } + ctx->nentries = 0; +} + + +/* code specific to file descriptors */ + +/** Constructor for struct evmap_io */ +static void +evmap_io_init(struct evmap_io *entry) +{ + TAILQ_INIT(&entry->events); + entry->nread = 0; + entry->nwrite = 0; +} + + +/* return -1 on error, 0 on success if nothing changed in the event backend, + * and 1 on success if something did. */ +int +evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev) +{ + const struct eventop *evsel = base->evsel; + struct event_io_map *io = &base->io; + struct evmap_io *ctx = NULL; + int nread, nwrite, retval = 0; + short res = 0, old = 0; + struct event *old_ev; + + EVUTIL_ASSERT(fd == ev->ev_fd); + + if (fd < 0) + return 0; + +#ifndef EVMAP_USE_HT + if (fd >= io->nentries) { + if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1) + return (-1); + } +#endif + GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init, + evsel->fdinfo_len); + + nread = ctx->nread; + nwrite = ctx->nwrite; + + if (nread) + old |= EV_READ; + if (nwrite) + old |= EV_WRITE; + + if (ev->ev_events & EV_READ) { + if (++nread == 1) + res |= EV_READ; + } + if (ev->ev_events & EV_WRITE) { + if (++nwrite == 1) + res |= EV_WRITE; + } + if (EVUTIL_UNLIKELY(nread > 0xffff || nwrite > 0xffff)) { + event_warnx("Too many events reading or writing on fd %d", + (int)fd); + return -1; + } + if (EVENT_DEBUG_MODE_IS_ON() && + (old_ev = TAILQ_FIRST(&ctx->events)) && + (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) { + event_warnx("Tried to mix edge-triggered and non-edge-triggered" + " events on fd %d", (int)fd); + return -1; + } + + if (res) { + void *extra = ((char*)ctx) + sizeof(struct evmap_io); + /* XXX(niels): we cannot mix edge-triggered and + * level-triggered, we should probably assert on + * this. */ + if (evsel->add(base, ev->ev_fd, + old, (ev->ev_events & EV_ET) | res, extra) == -1) + return (-1); + retval = 1; + } + + ctx->nread = (ev_uint16_t) nread; + ctx->nwrite = (ev_uint16_t) nwrite; + TAILQ_INSERT_TAIL(&ctx->events, ev, ev_io_next); + + return (retval); +} + +/* return -1 on error, 0 on success if nothing changed in the event backend, + * and 1 on success if something did. */ +int +evmap_io_del(struct event_base *base, evutil_socket_t fd, struct event *ev) +{ + const struct eventop *evsel = base->evsel; + struct event_io_map *io = &base->io; + struct evmap_io *ctx; + int nread, nwrite, retval = 0; + short res = 0, old = 0; + + if (fd < 0) + return 0; + + EVUTIL_ASSERT(fd == ev->ev_fd); + +#ifndef EVMAP_USE_HT + if (fd >= io->nentries) + return (-1); +#endif + + GET_IO_SLOT(ctx, io, fd, evmap_io); + + nread = ctx->nread; + nwrite = ctx->nwrite; + + if (nread) + old |= EV_READ; + if (nwrite) + old |= EV_WRITE; + + if (ev->ev_events & EV_READ) { + if (--nread == 0) + res |= EV_READ; + EVUTIL_ASSERT(nread >= 0); + } + if (ev->ev_events & EV_WRITE) { + if (--nwrite == 0) + res |= EV_WRITE; + EVUTIL_ASSERT(nwrite >= 0); + } + + if (res) { + void *extra = ((char*)ctx) + sizeof(struct evmap_io); + if (evsel->del(base, ev->ev_fd, old, res, extra) == -1) + return (-1); + retval = 1; + } + + ctx->nread = nread; + ctx->nwrite = nwrite; + TAILQ_REMOVE(&ctx->events, ev, ev_io_next); + + return (retval); +} + +void +evmap_io_active(struct event_base *base, evutil_socket_t fd, short events) +{ + struct event_io_map *io = &base->io; + struct evmap_io *ctx; + struct event *ev; + +#ifndef EVMAP_USE_HT + EVUTIL_ASSERT(fd < io->nentries); +#endif + GET_IO_SLOT(ctx, io, fd, evmap_io); + + EVUTIL_ASSERT(ctx); + TAILQ_FOREACH(ev, &ctx->events, ev_io_next) { + if (ev->ev_events & events) + event_active_nolock(ev, ev->ev_events & events, 1); + } +} + +/* code specific to signals */ + +static void +evmap_signal_init(struct evmap_signal *entry) +{ + TAILQ_INIT(&entry->events); +} + + +int +evmap_signal_add(struct event_base *base, int sig, struct event *ev) +{ + const struct eventop *evsel = base->evsigsel; + struct event_signal_map *map = &base->sigmap; + struct evmap_signal *ctx = NULL; + + if (sig >= map->nentries) { + if (evmap_make_space( + map, sig, sizeof(struct evmap_signal *)) == -1) + return (-1); + } + GET_SIGNAL_SLOT_AND_CTOR(ctx, map, sig, evmap_signal, evmap_signal_init, + base->evsigsel->fdinfo_len); + + if (TAILQ_EMPTY(&ctx->events)) { + if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL) + == -1) + return (-1); + } + + TAILQ_INSERT_TAIL(&ctx->events, ev, ev_signal_next); + + return (1); +} + +int +evmap_signal_del(struct event_base *base, int sig, struct event *ev) +{ + const struct eventop *evsel = base->evsigsel; + struct event_signal_map *map = &base->sigmap; + struct evmap_signal *ctx; + + if (sig >= map->nentries) + return (-1); + + GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal); + + if (TAILQ_FIRST(&ctx->events) == TAILQ_LAST(&ctx->events, event_list)) { + if (evsel->del(base, ev->ev_fd, 0, EV_SIGNAL, NULL) == -1) + return (-1); + } + + TAILQ_REMOVE(&ctx->events, ev, ev_signal_next); + + return (1); +} + +void +evmap_signal_active(struct event_base *base, evutil_socket_t sig, int ncalls) +{ + struct event_signal_map *map = &base->sigmap; + struct evmap_signal *ctx; + struct event *ev; + + EVUTIL_ASSERT(sig < map->nentries); + GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal); + + TAILQ_FOREACH(ev, &ctx->events, ev_signal_next) + event_active_nolock(ev, EV_SIGNAL, ncalls); +} + +void * +evmap_io_get_fdinfo(struct event_io_map *map, evutil_socket_t fd) +{ + struct evmap_io *ctx; + GET_IO_SLOT(ctx, map, fd, evmap_io); + if (ctx) + return ((char*)ctx) + sizeof(struct evmap_io); + else + return NULL; +} + +/** Per-fd structure for use with changelists. It keeps track, for each fd or + * signal using the changelist, of where its entry in the changelist is. + */ +struct event_changelist_fdinfo { + int idxplus1; /* this is the index +1, so that memset(0) will make it + * a no-such-element */ +}; + +void +event_changelist_init(struct event_changelist *changelist) +{ + changelist->changes = NULL; + changelist->changes_size = 0; + changelist->n_changes = 0; +} + +/** Helper: return the changelist_fdinfo corresponding to a given change. */ +static inline struct event_changelist_fdinfo * +event_change_get_fdinfo(struct event_base *base, + const struct event_change *change) +{ + char *ptr; + if (change->read_change & EV_CHANGE_SIGNAL) { + struct evmap_signal *ctx; + GET_SIGNAL_SLOT(ctx, &base->sigmap, change->fd, evmap_signal); + ptr = ((char*)ctx) + sizeof(struct evmap_signal); + } else { + struct evmap_io *ctx; + GET_IO_SLOT(ctx, &base->io, change->fd, evmap_io); + ptr = ((char*)ctx) + sizeof(struct evmap_io); + } + return (void*)ptr; +} + +#ifdef DEBUG_CHANGELIST +/** Make sure that the changelist is consistent with the evmap structures. */ +static void +event_changelist_check(struct event_base *base) +{ + int i; + struct event_changelist *changelist = &base->changelist; + + EVUTIL_ASSERT(changelist->changes_size >= changelist->n_changes); + for (i = 0; i < changelist->n_changes; ++i) { + struct event_change *c = &changelist->changes[i]; + struct event_changelist_fdinfo *f; + EVUTIL_ASSERT(c->fd >= 0); + f = event_change_get_fdinfo(base, c); + EVUTIL_ASSERT(f); + EVUTIL_ASSERT(f->idxplus1 == i + 1); + } + + for (i = 0; i < base->io.nentries; ++i) { + struct evmap_io *io = base->io.entries[i]; + struct event_changelist_fdinfo *f; + if (!io) + continue; + f = (void*) + ( ((char*)io) + sizeof(struct evmap_io) ); + if (f->idxplus1) { + struct event_change *c = &changelist->changes[f->idxplus1 - 1]; + EVUTIL_ASSERT(c->fd == i); + } + } +} +#else +#define event_changelist_check(base) ((void)0) +#endif + +void +event_changelist_remove_all(struct event_changelist *changelist, + struct event_base *base) +{ + int i; + + event_changelist_check(base); + + for (i = 0; i < changelist->n_changes; ++i) { + struct event_change *ch = &changelist->changes[i]; + struct event_changelist_fdinfo *fdinfo = + event_change_get_fdinfo(base, ch); + EVUTIL_ASSERT(fdinfo->idxplus1 == i + 1); + fdinfo->idxplus1 = 0; + } + + changelist->n_changes = 0; + + event_changelist_check(base); +} + +void +event_changelist_freemem(struct event_changelist *changelist) +{ + if (changelist->changes) + mm_free(changelist->changes); + event_changelist_init(changelist); /* zero it all out. */ +} + +/** Increase the size of 'changelist' to hold more changes. */ +static int +event_changelist_grow(struct event_changelist *changelist) +{ + int new_size; + struct event_change *new_changes; + if (changelist->changes_size < 64) + new_size = 64; + else + new_size = changelist->changes_size * 2; + + new_changes = mm_realloc(changelist->changes, + new_size * sizeof(struct event_change)); + + if (EVUTIL_UNLIKELY(new_changes == NULL)) + return (-1); + + changelist->changes = new_changes; + changelist->changes_size = new_size; + + return (0); +} + +/** Return a pointer to the changelist entry for the file descriptor or signal + * 'fd', whose fdinfo is 'fdinfo'. If none exists, construct it, setting its + * old_events field to old_events. + */ +static struct event_change * +event_changelist_get_or_construct(struct event_changelist *changelist, + evutil_socket_t fd, + short old_events, + struct event_changelist_fdinfo *fdinfo) +{ + struct event_change *change; + + if (fdinfo->idxplus1 == 0) { + int idx; + EVUTIL_ASSERT(changelist->n_changes <= changelist->changes_size); + + if (changelist->n_changes == changelist->changes_size) { + if (event_changelist_grow(changelist) < 0) + return NULL; + } + + idx = changelist->n_changes++; + change = &changelist->changes[idx]; + fdinfo->idxplus1 = idx + 1; + + memset(change, 0, sizeof(struct event_change)); + change->fd = fd; + change->old_events = old_events; + } else { + change = &changelist->changes[fdinfo->idxplus1 - 1]; + EVUTIL_ASSERT(change->fd == fd); + } + return change; +} + +int +event_changelist_add(struct event_base *base, evutil_socket_t fd, short old, short events, + void *p) +{ + struct event_changelist *changelist = &base->changelist; + struct event_changelist_fdinfo *fdinfo = p; + struct event_change *change; + + event_changelist_check(base); + + change = event_changelist_get_or_construct(changelist, fd, old, fdinfo); + if (!change) + return -1; + + /* An add replaces any previous delete, but doesn't result in a no-op, + * since the delete might fail (because the fd had been closed since + * the last add, for instance. */ + + if (events & (EV_READ|EV_SIGNAL)) { + change->read_change = EV_CHANGE_ADD | + (events & (EV_ET|EV_PERSIST|EV_SIGNAL)); + } + if (events & EV_WRITE) { + change->write_change = EV_CHANGE_ADD | + (events & (EV_ET|EV_PERSIST|EV_SIGNAL)); + } + + event_changelist_check(base); + return (0); +} + +int +event_changelist_del(struct event_base *base, evutil_socket_t fd, short old, short events, + void *p) +{ + struct event_changelist *changelist = &base->changelist; + struct event_changelist_fdinfo *fdinfo = p; + struct event_change *change; + + event_changelist_check(base); + change = event_changelist_get_or_construct(changelist, fd, old, fdinfo); + event_changelist_check(base); + if (!change) + return -1; + + /* A delete removes any previous add, rather than replacing it: + on those platforms where "add, delete, dispatch" is not the same + as "no-op, dispatch", we want the no-op behavior. + + As well as checking the current operation we should also check + the original set of events to make sure were not ignoring + the case where the add operation is present on an event that + was already set. + + If we have a no-op item, we could remove it it from the list + entirely, but really there's not much point: skipping the no-op + change when we do the dispatch later is far cheaper than rejuggling + the array now. + + As this stands, it also lets through deletions of events that are + not currently set. + */ + + if (events & (EV_READ|EV_SIGNAL)) { + if (!(change->old_events & (EV_READ | EV_SIGNAL)) && + (change->read_change & EV_CHANGE_ADD)) + change->read_change = 0; + else + change->read_change = EV_CHANGE_DEL; + } + if (events & EV_WRITE) { + if (!(change->old_events & EV_WRITE) && + (change->write_change & EV_CHANGE_ADD)) + change->write_change = 0; + else + change->write_change = EV_CHANGE_DEL; + } + + event_changelist_check(base); + return (0); +} + +void +evmap_check_integrity(struct event_base *base) +{ +#define EVLIST_X_SIGFOUND 0x1000 +#define EVLIST_X_IOFOUND 0x2000 + + evutil_socket_t i; + struct event *ev; + struct event_io_map *io = &base->io; + struct event_signal_map *sigmap = &base->sigmap; +#ifdef EVMAP_USE_HT + struct event_map_entry **mapent; +#endif + int nsignals, ntimers, nio; + nsignals = ntimers = nio = 0; + + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { + EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED); + EVUTIL_ASSERT(ev->ev_flags & EVLIST_INIT); + ev->ev_flags &= ~(EVLIST_X_SIGFOUND|EVLIST_X_IOFOUND); + } + +#ifdef EVMAP_USE_HT + HT_FOREACH(mapent, event_io_map, io) { + struct evmap_io *ctx = &(*mapent)->ent.evmap_io; + i = (*mapent)->fd; +#else + for (i = 0; i < io->nentries; ++i) { + struct evmap_io *ctx = io->entries[i]; + + if (!ctx) + continue; +#endif + + TAILQ_FOREACH(ev, &ctx->events, ev_io_next) { + EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_IOFOUND)); + EVUTIL_ASSERT(ev->ev_fd == i); + ev->ev_flags |= EVLIST_X_IOFOUND; + nio++; + } + } + + for (i = 0; i < sigmap->nentries; ++i) { + struct evmap_signal *ctx = sigmap->entries[i]; + if (!ctx) + continue; + + TAILQ_FOREACH(ev, &ctx->events, ev_signal_next) { + EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_SIGFOUND)); + EVUTIL_ASSERT(ev->ev_fd == i); + ev->ev_flags |= EVLIST_X_SIGFOUND; + nsignals++; + } + } + + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { + if (ev->ev_events & (EV_READ|EV_WRITE)) { + EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_IOFOUND); + --nio; + } + if (ev->ev_events & EV_SIGNAL) { + EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_SIGFOUND); + --nsignals; + } + } + + EVUTIL_ASSERT(nio == 0); + EVUTIL_ASSERT(nsignals == 0); + /* There is no "EVUTIL_ASSERT(ntimers == 0)": eventqueue is only for + * pending signals and io events. + */ +} diff --git a/libevent/evport.c b/libevent/evport.c new file mode 100644 index 0000000..0d714d8 --- /dev/null +++ b/libevent/evport.c @@ -0,0 +1,473 @@ +/* + * Submitted by David Pacheco (dp.spambait@gmail.com) + * + * Copyright 2006-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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 SUN MICROSYSTEMS, INC. ``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 SUN MICROSYSTEMS, INC. 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) 2007 Sun Microsystems. All rights reserved. + * Use is subject to license terms. + */ + +/* + * evport.c: event backend using Solaris 10 event ports. See port_create(3C). + * This implementation is loosely modeled after the one used for select(2) (in + * select.c). + * + * The outstanding events are tracked in a data structure called evport_data. + * Each entry in the ed_fds array corresponds to a file descriptor, and contains + * pointers to the read and write events that correspond to that fd. (That is, + * when the file is readable, the "read" event should handle it, etc.) + * + * evport_add and evport_del update this data structure. evport_dispatch uses it + * to determine where to callback when an event occurs (which it gets from + * port_getn). + * + * Helper functions are used: grow() grows the file descriptor array as + * necessary when large fd's come in. reassociate() takes care of maintaining + * the proper file-descriptor/event-port associations. + * + * As in the select(2) implementation, signals are handled by evsignal. + */ + +#include "event2/event-config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "event2/thread.h" + +#include "evthread-internal.h" +#include "event-internal.h" +#include "log-internal.h" +#include "evsignal-internal.h" +#include "evmap-internal.h" + +/* + * Default value for ed_nevents, which is the maximum file descriptor number we + * can handle. If an event comes in for a file descriptor F > nevents, we will + * grow the array of file descriptors, doubling its size. + */ +#define DEFAULT_NFDS 16 + + +/* + * EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on + * any particular call. You can speed things up by increasing this, but it will + * (obviously) require more memory. + */ +#define EVENTS_PER_GETN 8 + +/* + * Per-file-descriptor information about what events we're subscribed to. These + * fields are NULL if no event is subscribed to either of them. + */ + +struct fd_info { + short fdi_what; /* combinations of EV_READ and EV_WRITE */ +}; + +#define FDI_HAS_READ(fdi) ((fdi)->fdi_what & EV_READ) +#define FDI_HAS_WRITE(fdi) ((fdi)->fdi_what & EV_WRITE) +#define FDI_HAS_EVENTS(fdi) (FDI_HAS_READ(fdi) || FDI_HAS_WRITE(fdi)) +#define FDI_TO_SYSEVENTS(fdi) (FDI_HAS_READ(fdi) ? POLLIN : 0) | \ + (FDI_HAS_WRITE(fdi) ? POLLOUT : 0) + +struct evport_data { + int ed_port; /* event port for system events */ + int ed_nevents; /* number of allocated fdi's */ + struct fd_info *ed_fds; /* allocated fdi table */ + /* fdi's that we need to reassoc */ + int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */ +}; + +static void* evport_init(struct event_base *); +static int evport_add(struct event_base *, int fd, short old, short events, void *); +static int evport_del(struct event_base *, int fd, short old, short events, void *); +static int evport_dispatch(struct event_base *, struct timeval *); +static void evport_dealloc(struct event_base *); + +const struct eventop evportops = { + "evport", + evport_init, + evport_add, + evport_del, + evport_dispatch, + evport_dealloc, + 1, /* need reinit */ + 0, /* features */ + 0, /* fdinfo length */ +}; + +/* + * Initialize the event port implementation. + */ + +static void* +evport_init(struct event_base *base) +{ + struct evport_data *evpd; + int i; + + if (!(evpd = mm_calloc(1, sizeof(struct evport_data)))) + return (NULL); + + if ((evpd->ed_port = port_create()) == -1) { + mm_free(evpd); + return (NULL); + } + + /* + * Initialize file descriptor structure + */ + evpd->ed_fds = mm_calloc(DEFAULT_NFDS, sizeof(struct fd_info)); + if (evpd->ed_fds == NULL) { + close(evpd->ed_port); + mm_free(evpd); + return (NULL); + } + evpd->ed_nevents = DEFAULT_NFDS; + for (i = 0; i < EVENTS_PER_GETN; i++) + evpd->ed_pending[i] = -1; + + evsig_init(base); + + return (evpd); +} + +#ifdef CHECK_INVARIANTS +/* + * Checks some basic properties about the evport_data structure. Because it + * checks all file descriptors, this function can be expensive when the maximum + * file descriptor ever used is rather large. + */ + +static void +check_evportop(struct evport_data *evpd) +{ + EVUTIL_ASSERT(evpd); + EVUTIL_ASSERT(evpd->ed_nevents > 0); + EVUTIL_ASSERT(evpd->ed_port > 0); + EVUTIL_ASSERT(evpd->ed_fds > 0); +} + +/* + * Verifies very basic integrity of a given port_event. + */ +static void +check_event(port_event_t* pevt) +{ + /* + * We've only registered for PORT_SOURCE_FD events. The only + * other thing we can legitimately receive is PORT_SOURCE_ALERT, + * but since we're not using port_alert either, we can assume + * PORT_SOURCE_FD. + */ + EVUTIL_ASSERT(pevt->portev_source == PORT_SOURCE_FD); + EVUTIL_ASSERT(pevt->portev_user == NULL); +} + +#else +#define check_evportop(epop) +#define check_event(pevt) +#endif /* CHECK_INVARIANTS */ + +/* + * Doubles the size of the allocated file descriptor array. + */ +static int +grow(struct evport_data *epdp, int factor) +{ + struct fd_info *tmp; + int oldsize = epdp->ed_nevents; + int newsize = factor * oldsize; + EVUTIL_ASSERT(factor > 1); + + check_evportop(epdp); + + tmp = mm_realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize); + if (NULL == tmp) + return -1; + epdp->ed_fds = tmp; + memset((char*) (epdp->ed_fds + oldsize), 0, + (newsize - oldsize)*sizeof(struct fd_info)); + epdp->ed_nevents = newsize; + + check_evportop(epdp); + + return 0; +} + + +/* + * (Re)associates the given file descriptor with the event port. The OS events + * are specified (implicitly) from the fd_info struct. + */ +static int +reassociate(struct evport_data *epdp, struct fd_info *fdip, int fd) +{ + int sysevents = FDI_TO_SYSEVENTS(fdip); + + if (sysevents != 0) { + if (port_associate(epdp->ed_port, PORT_SOURCE_FD, + fd, sysevents, NULL) == -1) { + event_warn("port_associate"); + return (-1); + } + } + + check_evportop(epdp); + + return (0); +} + +/* + * Main event loop - polls port_getn for some number of events, and processes + * them. + */ + +static int +evport_dispatch(struct event_base *base, struct timeval *tv) +{ + int i, res; + struct evport_data *epdp = base->evbase; + port_event_t pevtlist[EVENTS_PER_GETN]; + + /* + * port_getn will block until it has at least nevents events. It will + * also return how many it's given us (which may be more than we asked + * for, as long as it's less than our maximum (EVENTS_PER_GETN)) in + * nevents. + */ + int nevents = 1; + + /* + * We have to convert a struct timeval to a struct timespec + * (only difference is nanoseconds vs. microseconds). If no time-based + * events are active, we should wait for I/O (and tv == NULL). + */ + struct timespec ts; + struct timespec *ts_p = NULL; + if (tv != NULL) { + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec * 1000; + ts_p = &ts; + } + + /* + * Before doing anything else, we need to reassociate the events we hit + * last time which need reassociation. See comment at the end of the + * loop below. + */ + for (i = 0; i < EVENTS_PER_GETN; ++i) { + struct fd_info *fdi = NULL; + if (epdp->ed_pending[i] != -1) { + fdi = &(epdp->ed_fds[epdp->ed_pending[i]]); + } + + if (fdi != NULL && FDI_HAS_EVENTS(fdi)) { + int fd = epdp->ed_pending[i]; + reassociate(epdp, fdi, fd); + epdp->ed_pending[i] = -1; + } + } + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN, + (unsigned int *) &nevents, ts_p); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + if (res == -1) { + if (errno == EINTR || errno == EAGAIN) { + return (0); + } else if (errno == ETIME) { + if (nevents == 0) + return (0); + } else { + event_warn("port_getn"); + return (-1); + } + } + + event_debug(("%s: port_getn reports %d events", __func__, nevents)); + + for (i = 0; i < nevents; ++i) { + struct fd_info *fdi; + port_event_t *pevt = &pevtlist[i]; + int fd = (int) pevt->portev_object; + + check_evportop(epdp); + check_event(pevt); + epdp->ed_pending[i] = fd; + + /* + * Figure out what kind of event it was + * (because we have to pass this to the callback) + */ + res = 0; + if (pevt->portev_events & (POLLERR|POLLHUP)) { + res = EV_READ | EV_WRITE; + } else { + if (pevt->portev_events & POLLIN) + res |= EV_READ; + if (pevt->portev_events & POLLOUT) + res |= EV_WRITE; + } + + /* + * Check for the error situations or a hangup situation + */ + if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL)) + res |= EV_READ|EV_WRITE; + + EVUTIL_ASSERT(epdp->ed_nevents > fd); + fdi = &(epdp->ed_fds[fd]); + + evmap_io_active(base, fd, res); + } /* end of all events gotten */ + + check_evportop(epdp); + + return (0); +} + + +/* + * Adds the given event (so that you will be notified when it happens via + * the callback function). + */ + +static int +evport_add(struct event_base *base, int fd, short old, short events, void *p) +{ + struct evport_data *evpd = base->evbase; + struct fd_info *fdi; + int factor; + (void)p; + + check_evportop(evpd); + + /* + * If necessary, grow the file descriptor info table + */ + + factor = 1; + while (fd >= factor * evpd->ed_nevents) + factor *= 2; + + if (factor > 1) { + if (-1 == grow(evpd, factor)) { + return (-1); + } + } + + fdi = &evpd->ed_fds[fd]; + fdi->fdi_what |= events; + + return reassociate(evpd, fdi, fd); +} + +/* + * Removes the given event from the list of events to wait for. + */ + +static int +evport_del(struct event_base *base, int fd, short old, short events, void *p) +{ + struct evport_data *evpd = base->evbase; + struct fd_info *fdi; + int i; + int associated = 1; + (void)p; + + check_evportop(evpd); + + if (evpd->ed_nevents < fd) { + return (-1); + } + + for (i = 0; i < EVENTS_PER_GETN; ++i) { + if (evpd->ed_pending[i] == fd) { + associated = 0; + break; + } + } + + fdi = &evpd->ed_fds[fd]; + if (events & EV_READ) + fdi->fdi_what &= ~EV_READ; + if (events & EV_WRITE) + fdi->fdi_what &= ~EV_WRITE; + + if (associated) { + if (!FDI_HAS_EVENTS(fdi) && + port_dissociate(evpd->ed_port, PORT_SOURCE_FD, fd) == -1) { + /* + * Ignore EBADFD error the fd could have been closed + * before event_del() was called. + */ + if (errno != EBADFD) { + event_warn("port_dissociate"); + return (-1); + } + } else { + if (FDI_HAS_EVENTS(fdi)) { + return (reassociate(evpd, fdi, fd)); + } + } + } else { + if ((fdi->fdi_what & (EV_READ|EV_WRITE)) == 0) { + evpd->ed_pending[i] = -1; + } + } + return 0; +} + + +static void +evport_dealloc(struct event_base *base) +{ + struct evport_data *evpd = base->evbase; + + evsig_dealloc(base); + + close(evpd->ed_port); + + if (evpd->ed_fds) + mm_free(evpd->ed_fds); + mm_free(evpd); +} diff --git a/libevent/evrpc-internal.h b/libevent/evrpc-internal.h new file mode 100644 index 0000000..d6ea41a --- /dev/null +++ b/libevent/evrpc-internal.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVRPC_INTERNAL_H_ +#define _EVRPC_INTERNAL_H_ + +#include "http-internal.h" + +struct evrpc; +struct evrpc_request_wrapper; + +#define EVRPC_URI_PREFIX "/.rpc." + +struct evrpc_hook { + TAILQ_ENTRY(evrpc_hook) next; + + /* returns EVRPC_TERMINATE; if the rpc should be aborted. + * a hook is is allowed to rewrite the evbuffer + */ + int (*process)(void *, struct evhttp_request *, + struct evbuffer *, void *); + void *process_arg; +}; + +TAILQ_HEAD(evrpc_hook_list, evrpc_hook); + +/* + * this is shared between the base and the pool, so that we can reuse + * the hook adding functions; we alias both evrpc_pool and evrpc_base + * to this common structure. + */ + +struct evrpc_hook_ctx; +TAILQ_HEAD(evrpc_pause_list, evrpc_hook_ctx); + +struct _evrpc_hooks { + /* hooks for processing outbound and inbound rpcs */ + struct evrpc_hook_list in_hooks; + struct evrpc_hook_list out_hooks; + + struct evrpc_pause_list pause_requests; +}; + +#define input_hooks common.in_hooks +#define output_hooks common.out_hooks +#define paused_requests common.pause_requests + +struct evrpc_base { + struct _evrpc_hooks common; + + /* the HTTP server under which we register our RPC calls */ + struct evhttp* http_server; + + /* a list of all RPCs registered with us */ + TAILQ_HEAD(evrpc_list, evrpc) registered_rpcs; +}; + +struct evrpc_req_generic; +void evrpc_reqstate_free(struct evrpc_req_generic* rpc_state); + +/* A pool for holding evhttp_connection objects */ +struct evrpc_pool { + struct _evrpc_hooks common; + + struct event_base *base; + + struct evconq connections; + + int timeout; + + TAILQ_HEAD(evrpc_requestq, evrpc_request_wrapper) (requests); +}; + +struct evrpc_hook_ctx { + TAILQ_ENTRY(evrpc_hook_ctx) next; + + void *ctx; + void (*cb)(void *, enum EVRPC_HOOK_RESULT); +}; + +struct evrpc_meta { + TAILQ_ENTRY(evrpc_meta) next; + char *key; + + void *data; + size_t data_size; +}; + +TAILQ_HEAD(evrpc_meta_list, evrpc_meta); + +struct evrpc_hook_meta { + struct evrpc_meta_list meta_data; + struct evhttp_connection *evcon; +}; + +/* allows association of meta data with a request */ +static void evrpc_hook_associate_meta(struct evrpc_hook_meta **pctx, + struct evhttp_connection *evcon); + +/* creates a new meta data store */ +static struct evrpc_hook_meta *evrpc_hook_meta_new(void); + +/* frees the meta data associated with a request */ +static void evrpc_hook_context_free(struct evrpc_hook_meta *ctx); + +/* the server side of an rpc */ + +/* We alias the RPC specific structs to this voided one */ +struct evrpc_req_generic { + /* + * allows association of meta data via hooks - needs to be + * synchronized with evrpc_request_wrapper + */ + struct evrpc_hook_meta *hook_meta; + + /* the unmarshaled request object */ + void *request; + + /* the empty reply object that needs to be filled in */ + void *reply; + + /* + * the static structure for this rpc; that can be used to + * automatically unmarshal and marshal the http buffers. + */ + struct evrpc *rpc; + + /* + * the http request structure on which we need to answer. + */ + struct evhttp_request* http_req; + + /* + * Temporary data store for marshaled data + */ + struct evbuffer* rpc_data; +}; + +/* the client side of an rpc request */ +struct evrpc_request_wrapper { + /* + * allows association of meta data via hooks - needs to be + * synchronized with evrpc_req_generic. + */ + struct evrpc_hook_meta *hook_meta; + + TAILQ_ENTRY(evrpc_request_wrapper) next; + + /* pool on which this rpc request is being made */ + struct evrpc_pool *pool; + + /* connection on which the request is being sent */ + struct evhttp_connection *evcon; + + /* the actual request */ + struct evhttp_request *req; + + /* event for implementing request timeouts */ + struct event ev_timeout; + + /* the name of the rpc */ + char *name; + + /* callback */ + void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg); + void *cb_arg; + + void *request; + void *reply; + + /* unmarshals the buffer into the proper request structure */ + void (*request_marshal)(struct evbuffer *, void *); + + /* removes all stored state in the reply */ + void (*reply_clear)(void *); + + /* marshals the reply into a buffer */ + int (*reply_unmarshal)(void *, struct evbuffer*); +}; + +#endif /* _EVRPC_INTERNAL_H_ */ diff --git a/libevent/evrpc.c b/libevent/evrpc.c new file mode 100644 index 0000000..4bf3d2b --- /dev/null +++ b/libevent/evrpc.c @@ -0,0 +1,1174 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#undef WIN32_LEAN_AND_MEAN +#endif + +#include +#ifndef WIN32 +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include +#include + +#include + +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/rpc.h" +#include "event2/rpc_struct.h" +#include "evrpc-internal.h" +#include "event2/http.h" +#include "event2/buffer.h" +#include "event2/tag.h" +#include "event2/http_struct.h" +#include "event2/http_compat.h" +#include "event2/util.h" +#include "util-internal.h" +#include "log-internal.h" +#include "mm-internal.h" + +struct evrpc_base * +evrpc_init(struct evhttp *http_server) +{ + struct evrpc_base* base = mm_calloc(1, sizeof(struct evrpc_base)); + if (base == NULL) + return (NULL); + + /* we rely on the tagging sub system */ + evtag_init(); + + TAILQ_INIT(&base->registered_rpcs); + TAILQ_INIT(&base->input_hooks); + TAILQ_INIT(&base->output_hooks); + + TAILQ_INIT(&base->paused_requests); + + base->http_server = http_server; + + return (base); +} + +void +evrpc_free(struct evrpc_base *base) +{ + struct evrpc *rpc; + struct evrpc_hook *hook; + struct evrpc_hook_ctx *pause; + int r; + + while ((rpc = TAILQ_FIRST(&base->registered_rpcs)) != NULL) { + r = evrpc_unregister_rpc(base, rpc->uri); + EVUTIL_ASSERT(r == 0); + } + while ((pause = TAILQ_FIRST(&base->paused_requests)) != NULL) { + TAILQ_REMOVE(&base->paused_requests, pause, next); + mm_free(pause); + } + while ((hook = TAILQ_FIRST(&base->input_hooks)) != NULL) { + r = evrpc_remove_hook(base, EVRPC_INPUT, hook); + EVUTIL_ASSERT(r); + } + while ((hook = TAILQ_FIRST(&base->output_hooks)) != NULL) { + r = evrpc_remove_hook(base, EVRPC_OUTPUT, hook); + EVUTIL_ASSERT(r); + } + mm_free(base); +} + +void * +evrpc_add_hook(void *vbase, + enum EVRPC_HOOK_TYPE hook_type, + int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *), + void *cb_arg) +{ + struct _evrpc_hooks *base = vbase; + struct evrpc_hook_list *head = NULL; + struct evrpc_hook *hook = NULL; + switch (hook_type) { + case EVRPC_INPUT: + head = &base->in_hooks; + break; + case EVRPC_OUTPUT: + head = &base->out_hooks; + break; + default: + EVUTIL_ASSERT(hook_type == EVRPC_INPUT || hook_type == EVRPC_OUTPUT); + } + + hook = mm_calloc(1, sizeof(struct evrpc_hook)); + EVUTIL_ASSERT(hook != NULL); + + hook->process = cb; + hook->process_arg = cb_arg; + TAILQ_INSERT_TAIL(head, hook, next); + + return (hook); +} + +static int +evrpc_remove_hook_internal(struct evrpc_hook_list *head, void *handle) +{ + struct evrpc_hook *hook = NULL; + TAILQ_FOREACH(hook, head, next) { + if (hook == handle) { + TAILQ_REMOVE(head, hook, next); + mm_free(hook); + return (1); + } + } + + return (0); +} + +/* + * remove the hook specified by the handle + */ + +int +evrpc_remove_hook(void *vbase, enum EVRPC_HOOK_TYPE hook_type, void *handle) +{ + struct _evrpc_hooks *base = vbase; + struct evrpc_hook_list *head = NULL; + switch (hook_type) { + case EVRPC_INPUT: + head = &base->in_hooks; + break; + case EVRPC_OUTPUT: + head = &base->out_hooks; + break; + default: + EVUTIL_ASSERT(hook_type == EVRPC_INPUT || hook_type == EVRPC_OUTPUT); + } + + return (evrpc_remove_hook_internal(head, handle)); +} + +static int +evrpc_process_hooks(struct evrpc_hook_list *head, void *ctx, + struct evhttp_request *req, struct evbuffer *evbuf) +{ + struct evrpc_hook *hook; + TAILQ_FOREACH(hook, head, next) { + int res = hook->process(ctx, req, evbuf, hook->process_arg); + if (res != EVRPC_CONTINUE) + return (res); + } + + return (EVRPC_CONTINUE); +} + +static void evrpc_pool_schedule(struct evrpc_pool *pool); +static void evrpc_request_cb(struct evhttp_request *, void *); + +/* + * Registers a new RPC with the HTTP server. The evrpc object is expected + * to have been filled in via the EVRPC_REGISTER_OBJECT macro which in turn + * calls this function. + */ + +static char * +evrpc_construct_uri(const char *uri) +{ + char *constructed_uri; + size_t constructed_uri_len; + + constructed_uri_len = strlen(EVRPC_URI_PREFIX) + strlen(uri) + 1; + if ((constructed_uri = mm_malloc(constructed_uri_len)) == NULL) + event_err(1, "%s: failed to register rpc at %s", + __func__, uri); + memcpy(constructed_uri, EVRPC_URI_PREFIX, strlen(EVRPC_URI_PREFIX)); + memcpy(constructed_uri + strlen(EVRPC_URI_PREFIX), uri, strlen(uri)); + constructed_uri[constructed_uri_len - 1] = '\0'; + + return (constructed_uri); +} + +int +evrpc_register_rpc(struct evrpc_base *base, struct evrpc *rpc, + void (*cb)(struct evrpc_req_generic *, void *), void *cb_arg) +{ + char *constructed_uri = evrpc_construct_uri(rpc->uri); + + rpc->base = base; + rpc->cb = cb; + rpc->cb_arg = cb_arg; + + TAILQ_INSERT_TAIL(&base->registered_rpcs, rpc, next); + + evhttp_set_cb(base->http_server, + constructed_uri, + evrpc_request_cb, + rpc); + + mm_free(constructed_uri); + + return (0); +} + +int +evrpc_unregister_rpc(struct evrpc_base *base, const char *name) +{ + char *registered_uri = NULL; + struct evrpc *rpc; + int r; + + /* find the right rpc; linear search might be slow */ + TAILQ_FOREACH(rpc, &base->registered_rpcs, next) { + if (strcmp(rpc->uri, name) == 0) + break; + } + if (rpc == NULL) { + /* We did not find an RPC with this name */ + return (-1); + } + TAILQ_REMOVE(&base->registered_rpcs, rpc, next); + + registered_uri = evrpc_construct_uri(name); + + /* remove the http server callback */ + r = evhttp_del_cb(base->http_server, registered_uri); + EVUTIL_ASSERT(r == 0); + + mm_free(registered_uri); + + mm_free((char *)rpc->uri); + mm_free(rpc); + return (0); +} + +static int evrpc_pause_request(void *vbase, void *ctx, + void (*cb)(void *, enum EVRPC_HOOK_RESULT)); +static void evrpc_request_cb_closure(void *, enum EVRPC_HOOK_RESULT); + +static void +evrpc_request_cb(struct evhttp_request *req, void *arg) +{ + struct evrpc *rpc = arg; + struct evrpc_req_generic *rpc_state = NULL; + + /* let's verify the outside parameters */ + if (req->type != EVHTTP_REQ_POST || + evbuffer_get_length(req->input_buffer) <= 0) + goto error; + + rpc_state = mm_calloc(1, sizeof(struct evrpc_req_generic)); + if (rpc_state == NULL) + goto error; + rpc_state->rpc = rpc; + rpc_state->http_req = req; + rpc_state->rpc_data = NULL; + + if (TAILQ_FIRST(&rpc->base->input_hooks) != NULL) { + int hook_res; + + evrpc_hook_associate_meta(&rpc_state->hook_meta, req->evcon); + + /* + * allow hooks to modify the outgoing request + */ + hook_res = evrpc_process_hooks(&rpc->base->input_hooks, + rpc_state, req, req->input_buffer); + switch (hook_res) { + case EVRPC_TERMINATE: + goto error; + case EVRPC_PAUSE: + evrpc_pause_request(rpc->base, rpc_state, + evrpc_request_cb_closure); + return; + case EVRPC_CONTINUE: + break; + default: + EVUTIL_ASSERT(hook_res == EVRPC_TERMINATE || + hook_res == EVRPC_CONTINUE || + hook_res == EVRPC_PAUSE); + } + } + + evrpc_request_cb_closure(rpc_state, EVRPC_CONTINUE); + return; + +error: + if (rpc_state != NULL) + evrpc_reqstate_free(rpc_state); + evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL); + return; +} + +static void +evrpc_request_cb_closure(void *arg, enum EVRPC_HOOK_RESULT hook_res) +{ + struct evrpc_req_generic *rpc_state = arg; + struct evrpc *rpc; + struct evhttp_request *req; + + EVUTIL_ASSERT(rpc_state); + rpc = rpc_state->rpc; + req = rpc_state->http_req; + + if (hook_res == EVRPC_TERMINATE) + goto error; + + /* let's check that we can parse the request */ + rpc_state->request = rpc->request_new(rpc->request_new_arg); + if (rpc_state->request == NULL) + goto error; + + if (rpc->request_unmarshal( + rpc_state->request, req->input_buffer) == -1) { + /* we failed to parse the request; that's a bummer */ + goto error; + } + + /* at this point, we have a well formed request, prepare the reply */ + + rpc_state->reply = rpc->reply_new(rpc->reply_new_arg); + if (rpc_state->reply == NULL) + goto error; + + /* give the rpc to the user; they can deal with it */ + rpc->cb(rpc_state, rpc->cb_arg); + + return; + +error: + if (rpc_state != NULL) + evrpc_reqstate_free(rpc_state); + evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL); + return; +} + + +void +evrpc_reqstate_free(struct evrpc_req_generic* rpc_state) +{ + struct evrpc *rpc; + EVUTIL_ASSERT(rpc_state != NULL); + rpc = rpc_state->rpc; + + /* clean up all memory */ + if (rpc_state->hook_meta != NULL) + evrpc_hook_context_free(rpc_state->hook_meta); + if (rpc_state->request != NULL) + rpc->request_free(rpc_state->request); + if (rpc_state->reply != NULL) + rpc->reply_free(rpc_state->reply); + if (rpc_state->rpc_data != NULL) + evbuffer_free(rpc_state->rpc_data); + mm_free(rpc_state); +} + +static void +evrpc_request_done_closure(void *, enum EVRPC_HOOK_RESULT); + +void +evrpc_request_done(struct evrpc_req_generic *rpc_state) +{ + struct evhttp_request *req; + struct evrpc *rpc; + + EVUTIL_ASSERT(rpc_state); + + req = rpc_state->http_req; + rpc = rpc_state->rpc; + + if (rpc->reply_complete(rpc_state->reply) == -1) { + /* the reply was not completely filled in. error out */ + goto error; + } + + if ((rpc_state->rpc_data = evbuffer_new()) == NULL) { + /* out of memory */ + goto error; + } + + /* serialize the reply */ + rpc->reply_marshal(rpc_state->rpc_data, rpc_state->reply); + + if (TAILQ_FIRST(&rpc->base->output_hooks) != NULL) { + int hook_res; + + evrpc_hook_associate_meta(&rpc_state->hook_meta, req->evcon); + + /* do hook based tweaks to the request */ + hook_res = evrpc_process_hooks(&rpc->base->output_hooks, + rpc_state, req, rpc_state->rpc_data); + switch (hook_res) { + case EVRPC_TERMINATE: + goto error; + case EVRPC_PAUSE: + if (evrpc_pause_request(rpc->base, rpc_state, + evrpc_request_done_closure) == -1) + goto error; + return; + case EVRPC_CONTINUE: + break; + default: + EVUTIL_ASSERT(hook_res == EVRPC_TERMINATE || + hook_res == EVRPC_CONTINUE || + hook_res == EVRPC_PAUSE); + } + } + + evrpc_request_done_closure(rpc_state, EVRPC_CONTINUE); + return; + +error: + if (rpc_state != NULL) + evrpc_reqstate_free(rpc_state); + evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL); + return; +} + +void * +evrpc_get_request(struct evrpc_req_generic *req) +{ + return req->request; +} + +void * +evrpc_get_reply(struct evrpc_req_generic *req) +{ + return req->reply; +} + +static void +evrpc_request_done_closure(void *arg, enum EVRPC_HOOK_RESULT hook_res) +{ + struct evrpc_req_generic *rpc_state = arg; + struct evhttp_request *req; + EVUTIL_ASSERT(rpc_state); + req = rpc_state->http_req; + + if (hook_res == EVRPC_TERMINATE) + goto error; + + /* on success, we are going to transmit marshaled binary data */ + if (evhttp_find_header(req->output_headers, "Content-Type") == NULL) { + evhttp_add_header(req->output_headers, + "Content-Type", "application/octet-stream"); + } + evhttp_send_reply(req, HTTP_OK, "OK", rpc_state->rpc_data); + + evrpc_reqstate_free(rpc_state); + + return; + +error: + if (rpc_state != NULL) + evrpc_reqstate_free(rpc_state); + evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL); + return; +} + + +/* Client implementation of RPC site */ + +static int evrpc_schedule_request(struct evhttp_connection *connection, + struct evrpc_request_wrapper *ctx); + +struct evrpc_pool * +evrpc_pool_new(struct event_base *base) +{ + struct evrpc_pool *pool = mm_calloc(1, sizeof(struct evrpc_pool)); + if (pool == NULL) + return (NULL); + + TAILQ_INIT(&pool->connections); + TAILQ_INIT(&pool->requests); + + TAILQ_INIT(&pool->paused_requests); + + TAILQ_INIT(&pool->input_hooks); + TAILQ_INIT(&pool->output_hooks); + + pool->base = base; + pool->timeout = -1; + + return (pool); +} + +static void +evrpc_request_wrapper_free(struct evrpc_request_wrapper *request) +{ + if (request->hook_meta != NULL) + evrpc_hook_context_free(request->hook_meta); + mm_free(request->name); + mm_free(request); +} + +void +evrpc_pool_free(struct evrpc_pool *pool) +{ + struct evhttp_connection *connection; + struct evrpc_request_wrapper *request; + struct evrpc_hook_ctx *pause; + struct evrpc_hook *hook; + int r; + + while ((request = TAILQ_FIRST(&pool->requests)) != NULL) { + TAILQ_REMOVE(&pool->requests, request, next); + evrpc_request_wrapper_free(request); + } + + while ((pause = TAILQ_FIRST(&pool->paused_requests)) != NULL) { + TAILQ_REMOVE(&pool->paused_requests, pause, next); + mm_free(pause); + } + + while ((connection = TAILQ_FIRST(&pool->connections)) != NULL) { + TAILQ_REMOVE(&pool->connections, connection, next); + evhttp_connection_free(connection); + } + + while ((hook = TAILQ_FIRST(&pool->input_hooks)) != NULL) { + r = evrpc_remove_hook(pool, EVRPC_INPUT, hook); + EVUTIL_ASSERT(r); + } + + while ((hook = TAILQ_FIRST(&pool->output_hooks)) != NULL) { + r = evrpc_remove_hook(pool, EVRPC_OUTPUT, hook); + EVUTIL_ASSERT(r); + } + + mm_free(pool); +} + +/* + * Add a connection to the RPC pool. A request scheduled on the pool + * may use any available connection. + */ + +void +evrpc_pool_add_connection(struct evrpc_pool *pool, + struct evhttp_connection *connection) +{ + EVUTIL_ASSERT(connection->http_server == NULL); + TAILQ_INSERT_TAIL(&pool->connections, connection, next); + + /* + * associate an event base with this connection + */ + if (pool->base != NULL) + evhttp_connection_set_base(connection, pool->base); + + /* + * unless a timeout was specifically set for a connection, + * the connection inherits the timeout from the pool. + */ + if (connection->timeout == -1) + connection->timeout = pool->timeout; + + /* + * if we have any requests pending, schedule them with the new + * connections. + */ + + if (TAILQ_FIRST(&pool->requests) != NULL) { + struct evrpc_request_wrapper *request = + TAILQ_FIRST(&pool->requests); + TAILQ_REMOVE(&pool->requests, request, next); + evrpc_schedule_request(connection, request); + } +} + +void +evrpc_pool_remove_connection(struct evrpc_pool *pool, + struct evhttp_connection *connection) +{ + TAILQ_REMOVE(&pool->connections, connection, next); +} + +void +evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs) +{ + struct evhttp_connection *evcon; + TAILQ_FOREACH(evcon, &pool->connections, next) { + evcon->timeout = timeout_in_secs; + } + pool->timeout = timeout_in_secs; +} + + +static void evrpc_reply_done(struct evhttp_request *, void *); +static void evrpc_request_timeout(evutil_socket_t, short, void *); + +/* + * Finds a connection object associated with the pool that is currently + * idle and can be used to make a request. + */ +static struct evhttp_connection * +evrpc_pool_find_connection(struct evrpc_pool *pool) +{ + struct evhttp_connection *connection; + TAILQ_FOREACH(connection, &pool->connections, next) { + if (TAILQ_FIRST(&connection->requests) == NULL) + return (connection); + } + + return (NULL); +} + +/* + * Prototypes responsible for evrpc scheduling and hooking + */ + +static void evrpc_schedule_request_closure(void *ctx, enum EVRPC_HOOK_RESULT); + +/* + * We assume that the ctx is no longer queued on the pool. + */ +static int +evrpc_schedule_request(struct evhttp_connection *connection, + struct evrpc_request_wrapper *ctx) +{ + struct evhttp_request *req = NULL; + struct evrpc_pool *pool = ctx->pool; + struct evrpc_status status; + + if ((req = evhttp_request_new(evrpc_reply_done, ctx)) == NULL) + goto error; + + /* serialize the request data into the output buffer */ + ctx->request_marshal(req->output_buffer, ctx->request); + + /* we need to know the connection that we might have to abort */ + ctx->evcon = connection; + + /* if we get paused we also need to know the request */ + ctx->req = req; + + if (TAILQ_FIRST(&pool->output_hooks) != NULL) { + int hook_res; + + evrpc_hook_associate_meta(&ctx->hook_meta, connection); + + /* apply hooks to the outgoing request */ + hook_res = evrpc_process_hooks(&pool->output_hooks, + ctx, req, req->output_buffer); + + switch (hook_res) { + case EVRPC_TERMINATE: + goto error; + case EVRPC_PAUSE: + /* we need to be explicitly resumed */ + if (evrpc_pause_request(pool, ctx, + evrpc_schedule_request_closure) == -1) + goto error; + return (0); + case EVRPC_CONTINUE: + /* we can just continue */ + break; + default: + EVUTIL_ASSERT(hook_res == EVRPC_TERMINATE || + hook_res == EVRPC_CONTINUE || + hook_res == EVRPC_PAUSE); + } + } + + evrpc_schedule_request_closure(ctx, EVRPC_CONTINUE); + return (0); + +error: + memset(&status, 0, sizeof(status)); + status.error = EVRPC_STATUS_ERR_UNSTARTED; + (*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg); + evrpc_request_wrapper_free(ctx); + return (-1); +} + +static void +evrpc_schedule_request_closure(void *arg, enum EVRPC_HOOK_RESULT hook_res) +{ + struct evrpc_request_wrapper *ctx = arg; + struct evhttp_connection *connection = ctx->evcon; + struct evhttp_request *req = ctx->req; + struct evrpc_pool *pool = ctx->pool; + struct evrpc_status status; + char *uri = NULL; + int res = 0; + + if (hook_res == EVRPC_TERMINATE) + goto error; + + uri = evrpc_construct_uri(ctx->name); + if (uri == NULL) + goto error; + + if (pool->timeout > 0) { + /* + * a timeout after which the whole rpc is going to be aborted. + */ + struct timeval tv; + evutil_timerclear(&tv); + tv.tv_sec = pool->timeout; + evtimer_add(&ctx->ev_timeout, &tv); + } + + /* start the request over the connection */ + res = evhttp_make_request(connection, req, EVHTTP_REQ_POST, uri); + mm_free(uri); + + if (res == -1) + goto error; + + return; + +error: + memset(&status, 0, sizeof(status)); + status.error = EVRPC_STATUS_ERR_UNSTARTED; + (*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg); + evrpc_request_wrapper_free(ctx); +} + +/* we just queue the paused request on the pool under the req object */ +static int +evrpc_pause_request(void *vbase, void *ctx, + void (*cb)(void *, enum EVRPC_HOOK_RESULT)) +{ + struct _evrpc_hooks *base = vbase; + struct evrpc_hook_ctx *pause = mm_malloc(sizeof(*pause)); + if (pause == NULL) + return (-1); + + pause->ctx = ctx; + pause->cb = cb; + + TAILQ_INSERT_TAIL(&base->pause_requests, pause, next); + return (0); +} + +int +evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res) +{ + struct _evrpc_hooks *base = vbase; + struct evrpc_pause_list *head = &base->pause_requests; + struct evrpc_hook_ctx *pause; + + TAILQ_FOREACH(pause, head, next) { + if (pause->ctx == ctx) + break; + } + + if (pause == NULL) + return (-1); + + (*pause->cb)(pause->ctx, res); + TAILQ_REMOVE(head, pause, next); + mm_free(pause); + return (0); +} + +int +evrpc_make_request(struct evrpc_request_wrapper *ctx) +{ + struct evrpc_pool *pool = ctx->pool; + + /* initialize the event structure for this rpc */ + evtimer_assign(&ctx->ev_timeout, pool->base, evrpc_request_timeout, ctx); + + /* we better have some available connections on the pool */ + EVUTIL_ASSERT(TAILQ_FIRST(&pool->connections) != NULL); + + /* + * if no connection is available, we queue the request on the pool, + * the next time a connection is empty, the rpc will be send on that. + */ + TAILQ_INSERT_TAIL(&pool->requests, ctx, next); + + evrpc_pool_schedule(pool); + + return (0); +} + + +struct evrpc_request_wrapper * +evrpc_make_request_ctx( + struct evrpc_pool *pool, void *request, void *reply, + const char *rpcname, + void (*req_marshal)(struct evbuffer*, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *), + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cbarg) +{ + struct evrpc_request_wrapper *ctx = (struct evrpc_request_wrapper *) + mm_malloc(sizeof(struct evrpc_request_wrapper)); + if (ctx == NULL) + return (NULL); + + ctx->pool = pool; + ctx->hook_meta = NULL; + ctx->evcon = NULL; + ctx->name = mm_strdup(rpcname); + if (ctx->name == NULL) { + mm_free(ctx); + return (NULL); + } + ctx->cb = cb; + ctx->cb_arg = cbarg; + ctx->request = request; + ctx->reply = reply; + ctx->request_marshal = req_marshal; + ctx->reply_clear = rpl_clear; + ctx->reply_unmarshal = rpl_unmarshal; + + return (ctx); +} + +static void +evrpc_reply_done_closure(void *, enum EVRPC_HOOK_RESULT); + +static void +evrpc_reply_done(struct evhttp_request *req, void *arg) +{ + struct evrpc_request_wrapper *ctx = arg; + struct evrpc_pool *pool = ctx->pool; + int hook_res = EVRPC_CONTINUE; + + /* cancel any timeout we might have scheduled */ + event_del(&ctx->ev_timeout); + + ctx->req = req; + + /* we need to get the reply now */ + if (req == NULL) { + evrpc_reply_done_closure(ctx, EVRPC_CONTINUE); + return; + } + + if (TAILQ_FIRST(&pool->input_hooks) != NULL) { + evrpc_hook_associate_meta(&ctx->hook_meta, ctx->evcon); + + /* apply hooks to the incoming request */ + hook_res = evrpc_process_hooks(&pool->input_hooks, + ctx, req, req->input_buffer); + + switch (hook_res) { + case EVRPC_TERMINATE: + case EVRPC_CONTINUE: + break; + case EVRPC_PAUSE: + /* + * if we get paused we also need to know the + * request. unfortunately, the underlying + * layer is going to free it. we need to + * request ownership explicitly + */ + if (req != NULL) + evhttp_request_own(req); + + evrpc_pause_request(pool, ctx, + evrpc_reply_done_closure); + return; + default: + EVUTIL_ASSERT(hook_res == EVRPC_TERMINATE || + hook_res == EVRPC_CONTINUE || + hook_res == EVRPC_PAUSE); + } + } + + evrpc_reply_done_closure(ctx, hook_res); + + /* http request is being freed by underlying layer */ +} + +static void +evrpc_reply_done_closure(void *arg, enum EVRPC_HOOK_RESULT hook_res) +{ + struct evrpc_request_wrapper *ctx = arg; + struct evhttp_request *req = ctx->req; + struct evrpc_pool *pool = ctx->pool; + struct evrpc_status status; + int res = -1; + + memset(&status, 0, sizeof(status)); + status.http_req = req; + + /* we need to get the reply now */ + if (req == NULL) { + status.error = EVRPC_STATUS_ERR_TIMEOUT; + } else if (hook_res == EVRPC_TERMINATE) { + status.error = EVRPC_STATUS_ERR_HOOKABORTED; + } else { + res = ctx->reply_unmarshal(ctx->reply, req->input_buffer); + if (res == -1) + status.error = EVRPC_STATUS_ERR_BADPAYLOAD; + } + + if (res == -1) { + /* clear everything that we might have written previously */ + ctx->reply_clear(ctx->reply); + } + + (*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg); + + evrpc_request_wrapper_free(ctx); + + /* the http layer owned the original request structure, but if we + * got paused, we asked for ownership and need to free it here. */ + if (req != NULL && evhttp_request_is_owned(req)) + evhttp_request_free(req); + + /* see if we can schedule another request */ + evrpc_pool_schedule(pool); +} + +static void +evrpc_pool_schedule(struct evrpc_pool *pool) +{ + struct evrpc_request_wrapper *ctx = TAILQ_FIRST(&pool->requests); + struct evhttp_connection *evcon; + + /* if no requests are pending, we have no work */ + if (ctx == NULL) + return; + + if ((evcon = evrpc_pool_find_connection(pool)) != NULL) { + TAILQ_REMOVE(&pool->requests, ctx, next); + evrpc_schedule_request(evcon, ctx); + } +} + +static void +evrpc_request_timeout(evutil_socket_t fd, short what, void *arg) +{ + struct evrpc_request_wrapper *ctx = arg; + struct evhttp_connection *evcon = ctx->evcon; + EVUTIL_ASSERT(evcon != NULL); + + evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT); +} + +/* + * frees potential meta data associated with a request. + */ + +static void +evrpc_meta_data_free(struct evrpc_meta_list *meta_data) +{ + struct evrpc_meta *entry; + EVUTIL_ASSERT(meta_data != NULL); + + while ((entry = TAILQ_FIRST(meta_data)) != NULL) { + TAILQ_REMOVE(meta_data, entry, next); + mm_free(entry->key); + mm_free(entry->data); + mm_free(entry); + } +} + +static struct evrpc_hook_meta * +evrpc_hook_meta_new(void) +{ + struct evrpc_hook_meta *ctx; + ctx = mm_malloc(sizeof(struct evrpc_hook_meta)); + EVUTIL_ASSERT(ctx != NULL); + + TAILQ_INIT(&ctx->meta_data); + ctx->evcon = NULL; + + return (ctx); +} + +static void +evrpc_hook_associate_meta(struct evrpc_hook_meta **pctx, + struct evhttp_connection *evcon) +{ + struct evrpc_hook_meta *ctx = *pctx; + if (ctx == NULL) + *pctx = ctx = evrpc_hook_meta_new(); + ctx->evcon = evcon; +} + +static void +evrpc_hook_context_free(struct evrpc_hook_meta *ctx) +{ + evrpc_meta_data_free(&ctx->meta_data); + mm_free(ctx); +} + +/* Adds meta data */ +void +evrpc_hook_add_meta(void *ctx, const char *key, + const void *data, size_t data_size) +{ + struct evrpc_request_wrapper *req = ctx; + struct evrpc_hook_meta *store = NULL; + struct evrpc_meta *meta = NULL; + + if ((store = req->hook_meta) == NULL) + store = req->hook_meta = evrpc_hook_meta_new(); + + meta = mm_malloc(sizeof(struct evrpc_meta)); + EVUTIL_ASSERT(meta != NULL); + meta->key = mm_strdup(key); + EVUTIL_ASSERT(meta->key != NULL); + meta->data_size = data_size; + meta->data = mm_malloc(data_size); + EVUTIL_ASSERT(meta->data != NULL); + memcpy(meta->data, data, data_size); + + TAILQ_INSERT_TAIL(&store->meta_data, meta, next); +} + +int +evrpc_hook_find_meta(void *ctx, const char *key, void **data, size_t *data_size) +{ + struct evrpc_request_wrapper *req = ctx; + struct evrpc_meta *meta = NULL; + + if (req->hook_meta == NULL) + return (-1); + + TAILQ_FOREACH(meta, &req->hook_meta->meta_data, next) { + if (strcmp(meta->key, key) == 0) { + *data = meta->data; + *data_size = meta->data_size; + return (0); + } + } + + return (-1); +} + +struct evhttp_connection * +evrpc_hook_get_connection(void *ctx) +{ + struct evrpc_request_wrapper *req = ctx; + return (req->hook_meta != NULL ? req->hook_meta->evcon : NULL); +} + +int +evrpc_send_request_generic(struct evrpc_pool *pool, + void *request, void *reply, + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cb_arg, + const char *rpcname, + void (*req_marshal)(struct evbuffer *, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *)) +{ + struct evrpc_status status; + struct evrpc_request_wrapper *ctx; + ctx = evrpc_make_request_ctx(pool, request, reply, + rpcname, req_marshal, rpl_clear, rpl_unmarshal, cb, cb_arg); + if (ctx == NULL) + goto error; + return (evrpc_make_request(ctx)); +error: + memset(&status, 0, sizeof(status)); + status.error = EVRPC_STATUS_ERR_UNSTARTED; + (*(cb))(&status, request, reply, cb_arg); + return (-1); +} + +/** Takes a request object and fills it in with the right magic */ +static struct evrpc * +evrpc_register_object(const char *name, + void *(*req_new)(void*), void *req_new_arg, void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void*), void *rpl_new_arg, void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)) +{ + struct evrpc* rpc = (struct evrpc *)mm_calloc(1, sizeof(struct evrpc)); + if (rpc == NULL) + return (NULL); + rpc->uri = mm_strdup(name); + if (rpc->uri == NULL) { + mm_free(rpc); + return (NULL); + } + rpc->request_new = req_new; + rpc->request_new_arg = req_new_arg; + rpc->request_free = req_free; + rpc->request_unmarshal = req_unmarshal; + rpc->reply_new = rpl_new; + rpc->reply_new_arg = rpl_new_arg; + rpc->reply_free = rpl_free; + rpc->reply_complete = rpl_complete; + rpc->reply_marshal = rpl_marshal; + return (rpc); +} + +int +evrpc_register_generic(struct evrpc_base *base, const char *name, + void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, + void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)) +{ + struct evrpc* rpc = + evrpc_register_object(name, req_new, req_new_arg, req_free, req_unmarshal, + rpl_new, rpl_new_arg, rpl_free, rpl_complete, rpl_marshal); + if (rpc == NULL) + return (-1); + evrpc_register_rpc(base, rpc, + (void (*)(struct evrpc_req_generic*, void *))callback, cbarg); + return (0); +} + +/** accessors for obscure and undocumented functionality */ +struct evrpc_pool * +evrpc_request_get_pool(struct evrpc_request_wrapper *ctx) +{ + return (ctx->pool); +} + +void +evrpc_request_set_pool(struct evrpc_request_wrapper *ctx, + struct evrpc_pool *pool) +{ + ctx->pool = pool; +} + +void +evrpc_request_set_cb(struct evrpc_request_wrapper *ctx, + void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg), + void *cb_arg) +{ + ctx->cb = cb; + ctx->cb_arg = cb_arg; +} diff --git a/libevent/evrpc.h b/libevent/evrpc.h new file mode 100644 index 0000000..5b88262 --- /dev/null +++ b/libevent/evrpc.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVRPC_H_ +#define _EVRPC_H_ + +/** @file evrpc.h + + An RPC system for Libevent. + + The header is deprecated in Libevent 2.0 and later; please + use instead. Depending on what functionality you + need, you may also want to include more of the other + headers. + */ + +#include +#include +#include +#include + +#endif /* _EVRPC_H_ */ diff --git a/libevent/evsignal-internal.h b/libevent/evsignal-internal.h new file mode 100644 index 0000000..426f4a4 --- /dev/null +++ b/libevent/evsignal-internal.h @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVSIGNAL_H_ +#define _EVSIGNAL_H_ + +#ifndef evutil_socket_t +#include "event2/util.h" +#endif +#include + +typedef void (*ev_sighandler_t)(int); + +/* Data structure for the default signal-handling implementation in signal.c + */ +struct evsig_info { + /* Event watching ev_signal_pair[1] */ + struct event ev_signal; + /* Socketpair used to send notifications from the signal handler */ + evutil_socket_t ev_signal_pair[2]; + /* True iff we've added the ev_signal event yet. */ + int ev_signal_added; + /* Count of the number of signals we're currently watching. */ + int ev_n_signals_added; + + /* Array of previous signal handler objects before Libevent started + * messing with them. Used to restore old signal handlers. */ +#ifdef _EVENT_HAVE_SIGACTION + struct sigaction **sh_old; +#else + ev_sighandler_t **sh_old; +#endif + /* Size of sh_old. */ + int sh_old_max; +}; +int evsig_init(struct event_base *); +void evsig_dealloc(struct event_base *); + +void evsig_set_base(struct event_base *base); + +#endif /* _EVSIGNAL_H_ */ diff --git a/libevent/evthread-internal.h b/libevent/evthread-internal.h new file mode 100644 index 0000000..ccfcdde --- /dev/null +++ b/libevent/evthread-internal.h @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2008-2012 Niels Provos, Nick Mathewson + * + * 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. + */ +#ifndef _EVTHREAD_INTERNAL_H_ +#define _EVTHREAD_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event2/thread.h" +#include "event2/event-config.h" +#include "util-internal.h" + +struct event_base; + +#ifndef WIN32 +/* On Windows, the way we currently make DLLs, it's not allowed for us to + * have shared global structures. Thus, we only do the direct-call-to-function + * code path if we know that the local shared library system supports it. + */ +#define EVTHREAD_EXPOSE_STRUCTS +#endif + +#if ! defined(_EVENT_DISABLE_THREAD_SUPPORT) && defined(EVTHREAD_EXPOSE_STRUCTS) +/* Global function pointers to lock-related functions. NULL if locking isn't + enabled. */ +extern struct evthread_lock_callbacks _evthread_lock_fns; +extern struct evthread_condition_callbacks _evthread_cond_fns; +extern unsigned long (*_evthread_id_fn)(void); +extern int _evthread_lock_debugging_enabled; + +/** Return the ID of the current thread, or 1 if threading isn't enabled. */ +#define EVTHREAD_GET_ID() \ + (_evthread_id_fn ? _evthread_id_fn() : 1) + +/** Return true iff we're in the thread that is currently (or most recently) + * running a given event_base's loop. Requires lock. */ +#define EVBASE_IN_THREAD(base) \ + (_evthread_id_fn == NULL || \ + (base)->th_owner_id == _evthread_id_fn()) + +/** Return true iff we need to notify the base's main thread about changes to + * its state, because it's currently running the main loop in another + * thread. Requires lock. */ +#define EVBASE_NEED_NOTIFY(base) \ + (_evthread_id_fn != NULL && \ + (base)->running_loop && \ + (base)->th_owner_id != _evthread_id_fn()) + +/** Allocate a new lock, and store it in lockvar, a void*. Sets lockvar to + NULL if locking is not enabled. */ +#define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \ + ((lockvar) = _evthread_lock_fns.alloc ? \ + _evthread_lock_fns.alloc(locktype) : NULL) + +/** Free a given lock, if it is present and locking is enabled. */ +#define EVTHREAD_FREE_LOCK(lockvar, locktype) \ + do { \ + void *_lock_tmp_ = (lockvar); \ + if (_lock_tmp_ && _evthread_lock_fns.free) \ + _evthread_lock_fns.free(_lock_tmp_, (locktype)); \ + } while (0) + +/** Acquire a lock. */ +#define EVLOCK_LOCK(lockvar,mode) \ + do { \ + if (lockvar) \ + _evthread_lock_fns.lock(mode, lockvar); \ + } while (0) + +/** Release a lock */ +#define EVLOCK_UNLOCK(lockvar,mode) \ + do { \ + if (lockvar) \ + _evthread_lock_fns.unlock(mode, lockvar); \ + } while (0) + +/** Helper: put lockvar1 and lockvar2 into pointerwise ascending order. */ +#define _EVLOCK_SORTLOCKS(lockvar1, lockvar2) \ + do { \ + if (lockvar1 && lockvar2 && lockvar1 > lockvar2) { \ + void *tmp = lockvar1; \ + lockvar1 = lockvar2; \ + lockvar2 = tmp; \ + } \ + } while (0) + +/** Lock an event_base, if it is set up for locking. Acquires the lock + in the base structure whose field is named 'lockvar'. */ +#define EVBASE_ACQUIRE_LOCK(base, lockvar) do { \ + EVLOCK_LOCK((base)->lockvar, 0); \ + } while (0) + +/** Unlock an event_base, if it is set up for locking. */ +#define EVBASE_RELEASE_LOCK(base, lockvar) do { \ + EVLOCK_UNLOCK((base)->lockvar, 0); \ + } while (0) + +/** If lock debugging is enabled, and lock is non-null, assert that 'lock' is + * locked and held by us. */ +#define EVLOCK_ASSERT_LOCKED(lock) \ + do { \ + if ((lock) && _evthread_lock_debugging_enabled) { \ + EVUTIL_ASSERT(_evthread_is_debug_lock_held(lock)); \ + } \ + } while (0) + +/** Try to grab the lock for 'lockvar' without blocking, and return 1 if we + * manage to get it. */ +static inline int EVLOCK_TRY_LOCK(void *lock); +static inline int +EVLOCK_TRY_LOCK(void *lock) +{ + if (lock && _evthread_lock_fns.lock) { + int r = _evthread_lock_fns.lock(EVTHREAD_TRY, lock); + return !r; + } else { + /* Locking is disabled either globally or for this thing; + * of course we count as having the lock. */ + return 1; + } +} + +/** Allocate a new condition variable and store it in the void *, condvar */ +#define EVTHREAD_ALLOC_COND(condvar) \ + do { \ + (condvar) = _evthread_cond_fns.alloc_condition ? \ + _evthread_cond_fns.alloc_condition(0) : NULL; \ + } while (0) +/** Deallocate and free a condition variable in condvar */ +#define EVTHREAD_FREE_COND(cond) \ + do { \ + if (cond) \ + _evthread_cond_fns.free_condition((cond)); \ + } while (0) +/** Signal one thread waiting on cond */ +#define EVTHREAD_COND_SIGNAL(cond) \ + ( (cond) ? _evthread_cond_fns.signal_condition((cond), 0) : 0 ) +/** Signal all threads waiting on cond */ +#define EVTHREAD_COND_BROADCAST(cond) \ + ( (cond) ? _evthread_cond_fns.signal_condition((cond), 1) : 0 ) +/** Wait until the condition 'cond' is signalled. Must be called while + * holding 'lock'. The lock will be released until the condition is + * signalled, at which point it will be acquired again. Returns 0 for + * success, -1 for failure. */ +#define EVTHREAD_COND_WAIT(cond, lock) \ + ( (cond) ? _evthread_cond_fns.wait_condition((cond), (lock), NULL) : 0 ) +/** As EVTHREAD_COND_WAIT, but gives up after 'tv' has elapsed. Returns 1 + * on timeout. */ +#define EVTHREAD_COND_WAIT_TIMED(cond, lock, tv) \ + ( (cond) ? _evthread_cond_fns.wait_condition((cond), (lock), (tv)) : 0 ) + +/** True iff locking functions have been configured. */ +#define EVTHREAD_LOCKING_ENABLED() \ + (_evthread_lock_fns.lock != NULL) + +#elif ! defined(_EVENT_DISABLE_THREAD_SUPPORT) + +unsigned long _evthreadimpl_get_id(void); +int _evthreadimpl_is_lock_debugging_enabled(void); +void *_evthreadimpl_lock_alloc(unsigned locktype); +void _evthreadimpl_lock_free(void *lock, unsigned locktype); +int _evthreadimpl_lock_lock(unsigned mode, void *lock); +int _evthreadimpl_lock_unlock(unsigned mode, void *lock); +void *_evthreadimpl_cond_alloc(unsigned condtype); +void _evthreadimpl_cond_free(void *cond); +int _evthreadimpl_cond_signal(void *cond, int broadcast); +int _evthreadimpl_cond_wait(void *cond, void *lock, const struct timeval *tv); +int _evthreadimpl_locking_enabled(void); + +#define EVTHREAD_GET_ID() _evthreadimpl_get_id() +#define EVBASE_IN_THREAD(base) \ + ((base)->th_owner_id == _evthreadimpl_get_id()) +#define EVBASE_NEED_NOTIFY(base) \ + ((base)->running_loop && \ + ((base)->th_owner_id != _evthreadimpl_get_id())) + +#define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \ + ((lockvar) = _evthreadimpl_lock_alloc(locktype)) + +#define EVTHREAD_FREE_LOCK(lockvar, locktype) \ + do { \ + void *_lock_tmp_ = (lockvar); \ + if (_lock_tmp_) \ + _evthreadimpl_lock_free(_lock_tmp_, (locktype)); \ + } while (0) + +/** Acquire a lock. */ +#define EVLOCK_LOCK(lockvar,mode) \ + do { \ + if (lockvar) \ + _evthreadimpl_lock_lock(mode, lockvar); \ + } while (0) + +/** Release a lock */ +#define EVLOCK_UNLOCK(lockvar,mode) \ + do { \ + if (lockvar) \ + _evthreadimpl_lock_unlock(mode, lockvar); \ + } while (0) + +/** Lock an event_base, if it is set up for locking. Acquires the lock + in the base structure whose field is named 'lockvar'. */ +#define EVBASE_ACQUIRE_LOCK(base, lockvar) do { \ + EVLOCK_LOCK((base)->lockvar, 0); \ + } while (0) + +/** Unlock an event_base, if it is set up for locking. */ +#define EVBASE_RELEASE_LOCK(base, lockvar) do { \ + EVLOCK_UNLOCK((base)->lockvar, 0); \ + } while (0) + +/** If lock debugging is enabled, and lock is non-null, assert that 'lock' is + * locked and held by us. */ +#define EVLOCK_ASSERT_LOCKED(lock) \ + do { \ + if ((lock) && _evthreadimpl_is_lock_debugging_enabled()) { \ + EVUTIL_ASSERT(_evthread_is_debug_lock_held(lock)); \ + } \ + } while (0) + +/** Try to grab the lock for 'lockvar' without blocking, and return 1 if we + * manage to get it. */ +static inline int EVLOCK_TRY_LOCK(void *lock); +static inline int +EVLOCK_TRY_LOCK(void *lock) +{ + if (lock) { + int r = _evthreadimpl_lock_lock(EVTHREAD_TRY, lock); + return !r; + } else { + /* Locking is disabled either globally or for this thing; + * of course we count as having the lock. */ + return 1; + } +} + +/** Allocate a new condition variable and store it in the void *, condvar */ +#define EVTHREAD_ALLOC_COND(condvar) \ + do { \ + (condvar) = _evthreadimpl_cond_alloc(0); \ + } while (0) +/** Deallocate and free a condition variable in condvar */ +#define EVTHREAD_FREE_COND(cond) \ + do { \ + if (cond) \ + _evthreadimpl_cond_free((cond)); \ + } while (0) +/** Signal one thread waiting on cond */ +#define EVTHREAD_COND_SIGNAL(cond) \ + ( (cond) ? _evthreadimpl_cond_signal((cond), 0) : 0 ) +/** Signal all threads waiting on cond */ +#define EVTHREAD_COND_BROADCAST(cond) \ + ( (cond) ? _evthreadimpl_cond_signal((cond), 1) : 0 ) +/** Wait until the condition 'cond' is signalled. Must be called while + * holding 'lock'. The lock will be released until the condition is + * signalled, at which point it will be acquired again. Returns 0 for + * success, -1 for failure. */ +#define EVTHREAD_COND_WAIT(cond, lock) \ + ( (cond) ? _evthreadimpl_cond_wait((cond), (lock), NULL) : 0 ) +/** As EVTHREAD_COND_WAIT, but gives up after 'tv' has elapsed. Returns 1 + * on timeout. */ +#define EVTHREAD_COND_WAIT_TIMED(cond, lock, tv) \ + ( (cond) ? _evthreadimpl_cond_wait((cond), (lock), (tv)) : 0 ) + +#define EVTHREAD_LOCKING_ENABLED() \ + (_evthreadimpl_locking_enabled()) + +#else /* _EVENT_DISABLE_THREAD_SUPPORT */ + +#define EVTHREAD_GET_ID() 1 +#define EVTHREAD_ALLOC_LOCK(lockvar, locktype) _EVUTIL_NIL_STMT +#define EVTHREAD_FREE_LOCK(lockvar, locktype) _EVUTIL_NIL_STMT + +#define EVLOCK_LOCK(lockvar, mode) _EVUTIL_NIL_STMT +#define EVLOCK_UNLOCK(lockvar, mode) _EVUTIL_NIL_STMT +#define EVLOCK_LOCK2(lock1,lock2,mode1,mode2) _EVUTIL_NIL_STMT +#define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) _EVUTIL_NIL_STMT + +#define EVBASE_IN_THREAD(base) 1 +#define EVBASE_NEED_NOTIFY(base) 0 +#define EVBASE_ACQUIRE_LOCK(base, lock) _EVUTIL_NIL_STMT +#define EVBASE_RELEASE_LOCK(base, lock) _EVUTIL_NIL_STMT +#define EVLOCK_ASSERT_LOCKED(lock) _EVUTIL_NIL_STMT + +#define EVLOCK_TRY_LOCK(lock) 1 + +#define EVTHREAD_ALLOC_COND(condvar) _EVUTIL_NIL_STMT +#define EVTHREAD_FREE_COND(cond) _EVUTIL_NIL_STMT +#define EVTHREAD_COND_SIGNAL(cond) _EVUTIL_NIL_STMT +#define EVTHREAD_COND_BROADCAST(cond) _EVUTIL_NIL_STMT +#define EVTHREAD_COND_WAIT(cond, lock) _EVUTIL_NIL_STMT +#define EVTHREAD_COND_WAIT_TIMED(cond, lock, howlong) _EVUTIL_NIL_STMT + +#define EVTHREAD_LOCKING_ENABLED() 0 + +#endif + +/* This code is shared between both lock impls */ +#if ! defined(_EVENT_DISABLE_THREAD_SUPPORT) +/** Helper: put lockvar1 and lockvar2 into pointerwise ascending order. */ +#define _EVLOCK_SORTLOCKS(lockvar1, lockvar2) \ + do { \ + if (lockvar1 && lockvar2 && lockvar1 > lockvar2) { \ + void *tmp = lockvar1; \ + lockvar1 = lockvar2; \ + lockvar2 = tmp; \ + } \ + } while (0) + +/** Acquire both lock1 and lock2. Always allocates locks in the same order, + * so that two threads locking two locks with LOCK2 will not deadlock. */ +#define EVLOCK_LOCK2(lock1,lock2,mode1,mode2) \ + do { \ + void *_lock1_tmplock = (lock1); \ + void *_lock2_tmplock = (lock2); \ + _EVLOCK_SORTLOCKS(_lock1_tmplock,_lock2_tmplock); \ + EVLOCK_LOCK(_lock1_tmplock,mode1); \ + if (_lock2_tmplock != _lock1_tmplock) \ + EVLOCK_LOCK(_lock2_tmplock,mode2); \ + } while (0) +/** Release both lock1 and lock2. */ +#define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) \ + do { \ + void *_lock1_tmplock = (lock1); \ + void *_lock2_tmplock = (lock2); \ + _EVLOCK_SORTLOCKS(_lock1_tmplock,_lock2_tmplock); \ + if (_lock2_tmplock != _lock1_tmplock) \ + EVLOCK_UNLOCK(_lock2_tmplock,mode2); \ + EVLOCK_UNLOCK(_lock1_tmplock,mode1); \ + } while (0) + +int _evthread_is_debug_lock_held(void *lock); +void *_evthread_debug_get_real_lock(void *lock); + +void *evthread_setup_global_lock_(void *lock_, unsigned locktype, + int enable_locks); + +#define EVTHREAD_SETUP_GLOBAL_LOCK(lockvar, locktype) \ + do { \ + lockvar = evthread_setup_global_lock_(lockvar, \ + (locktype), enable_locks); \ + if (!lockvar) { \ + event_warn("Couldn't allocate %s", #lockvar); \ + return -1; \ + } \ + } while (0); + +int event_global_setup_locks_(const int enable_locks); +int evsig_global_setup_locks_(const int enable_locks); +int evutil_secure_rng_global_setup_locks_(const int enable_locks); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _EVTHREAD_INTERNAL_H_ */ diff --git a/libevent/evthread.c b/libevent/evthread.c new file mode 100644 index 0000000..90e195d --- /dev/null +++ b/libevent/evthread.c @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2008-2012 Niels Provos, Nick Mathewson + * + * 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. + */ + +#include "event2/event-config.h" + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + +#include "event2/thread.h" + +#include +#include + +#include "log-internal.h" +#include "mm-internal.h" +#include "util-internal.h" +#include "evthread-internal.h" + +#ifdef EVTHREAD_EXPOSE_STRUCTS +#define GLOBAL +#else +#define GLOBAL static +#endif + +/* globals */ +GLOBAL int _evthread_lock_debugging_enabled = 0; +GLOBAL struct evthread_lock_callbacks _evthread_lock_fns = { + 0, 0, NULL, NULL, NULL, NULL +}; +GLOBAL unsigned long (*_evthread_id_fn)(void) = NULL; +GLOBAL struct evthread_condition_callbacks _evthread_cond_fns = { + 0, NULL, NULL, NULL, NULL +}; + +/* Used for debugging */ +static struct evthread_lock_callbacks _original_lock_fns = { + 0, 0, NULL, NULL, NULL, NULL +}; +static struct evthread_condition_callbacks _original_cond_fns = { + 0, NULL, NULL, NULL, NULL +}; + +void +evthread_set_id_callback(unsigned long (*id_fn)(void)) +{ + _evthread_id_fn = id_fn; +} + +int +evthread_set_lock_callbacks(const struct evthread_lock_callbacks *cbs) +{ + struct evthread_lock_callbacks *target = + _evthread_lock_debugging_enabled + ? &_original_lock_fns : &_evthread_lock_fns; + + if (!cbs) { + if (target->alloc) + event_warnx("Trying to disable lock functions after " + "they have been set up will probaby not work."); + memset(target, 0, sizeof(_evthread_lock_fns)); + return 0; + } + if (target->alloc) { + /* Uh oh; we already had locking callbacks set up.*/ + if (target->lock_api_version == cbs->lock_api_version && + target->supported_locktypes == cbs->supported_locktypes && + target->alloc == cbs->alloc && + target->free == cbs->free && + target->lock == cbs->lock && + target->unlock == cbs->unlock) { + /* no change -- allow this. */ + return 0; + } + event_warnx("Can't change lock callbacks once they have been " + "initialized."); + return -1; + } + if (cbs->alloc && cbs->free && cbs->lock && cbs->unlock) { + memcpy(target, cbs, sizeof(_evthread_lock_fns)); + return event_global_setup_locks_(1); + } else { + return -1; + } +} + +int +evthread_set_condition_callbacks(const struct evthread_condition_callbacks *cbs) +{ + struct evthread_condition_callbacks *target = + _evthread_lock_debugging_enabled + ? &_original_cond_fns : &_evthread_cond_fns; + + if (!cbs) { + if (target->alloc_condition) + event_warnx("Trying to disable condition functions " + "after they have been set up will probaby not " + "work."); + memset(target, 0, sizeof(_evthread_cond_fns)); + return 0; + } + if (target->alloc_condition) { + /* Uh oh; we already had condition callbacks set up.*/ + if (target->condition_api_version == cbs->condition_api_version && + target->alloc_condition == cbs->alloc_condition && + target->free_condition == cbs->free_condition && + target->signal_condition == cbs->signal_condition && + target->wait_condition == cbs->wait_condition) { + /* no change -- allow this. */ + return 0; + } + event_warnx("Can't change condition callbacks once they " + "have been initialized."); + return -1; + } + if (cbs->alloc_condition && cbs->free_condition && + cbs->signal_condition && cbs->wait_condition) { + memcpy(target, cbs, sizeof(_evthread_cond_fns)); + } + if (_evthread_lock_debugging_enabled) { + _evthread_cond_fns.alloc_condition = cbs->alloc_condition; + _evthread_cond_fns.free_condition = cbs->free_condition; + _evthread_cond_fns.signal_condition = cbs->signal_condition; + } + return 0; +} + +struct debug_lock { + unsigned locktype; + unsigned long held_by; + /* XXXX if we ever use read-write locks, we will need a separate + * lock to protect count. */ + int count; + void *lock; +}; + +static void * +debug_lock_alloc(unsigned locktype) +{ + struct debug_lock *result = mm_malloc(sizeof(struct debug_lock)); + if (!result) + return NULL; + if (_original_lock_fns.alloc) { + if (!(result->lock = _original_lock_fns.alloc( + locktype|EVTHREAD_LOCKTYPE_RECURSIVE))) { + mm_free(result); + return NULL; + } + } else { + result->lock = NULL; + } + result->locktype = locktype; + result->count = 0; + result->held_by = 0; + return result; +} + +static void +debug_lock_free(void *lock_, unsigned locktype) +{ + struct debug_lock *lock = lock_; + EVUTIL_ASSERT(lock->count == 0); + EVUTIL_ASSERT(locktype == lock->locktype); + if (_original_lock_fns.free) { + _original_lock_fns.free(lock->lock, + lock->locktype|EVTHREAD_LOCKTYPE_RECURSIVE); + } + lock->lock = NULL; + lock->count = -100; + mm_free(lock); +} + +static void +evthread_debug_lock_mark_locked(unsigned mode, struct debug_lock *lock) +{ + ++lock->count; + if (!(lock->locktype & EVTHREAD_LOCKTYPE_RECURSIVE)) + EVUTIL_ASSERT(lock->count == 1); + if (_evthread_id_fn) { + unsigned long me; + me = _evthread_id_fn(); + if (lock->count > 1) + EVUTIL_ASSERT(lock->held_by == me); + lock->held_by = me; + } +} + +static int +debug_lock_lock(unsigned mode, void *lock_) +{ + struct debug_lock *lock = lock_; + int res = 0; + if (lock->locktype & EVTHREAD_LOCKTYPE_READWRITE) + EVUTIL_ASSERT(mode & (EVTHREAD_READ|EVTHREAD_WRITE)); + else + EVUTIL_ASSERT((mode & (EVTHREAD_READ|EVTHREAD_WRITE)) == 0); + if (_original_lock_fns.lock) + res = _original_lock_fns.lock(mode, lock->lock); + if (!res) { + evthread_debug_lock_mark_locked(mode, lock); + } + return res; +} + +static void +evthread_debug_lock_mark_unlocked(unsigned mode, struct debug_lock *lock) +{ + if (lock->locktype & EVTHREAD_LOCKTYPE_READWRITE) + EVUTIL_ASSERT(mode & (EVTHREAD_READ|EVTHREAD_WRITE)); + else + EVUTIL_ASSERT((mode & (EVTHREAD_READ|EVTHREAD_WRITE)) == 0); + if (_evthread_id_fn) { + EVUTIL_ASSERT(lock->held_by == _evthread_id_fn()); + if (lock->count == 1) + lock->held_by = 0; + } + --lock->count; + EVUTIL_ASSERT(lock->count >= 0); +} + +static int +debug_lock_unlock(unsigned mode, void *lock_) +{ + struct debug_lock *lock = lock_; + int res = 0; + evthread_debug_lock_mark_unlocked(mode, lock); + if (_original_lock_fns.unlock) + res = _original_lock_fns.unlock(mode, lock->lock); + return res; +} + +static int +debug_cond_wait(void *_cond, void *_lock, const struct timeval *tv) +{ + int r; + struct debug_lock *lock = _lock; + EVUTIL_ASSERT(lock); + EVLOCK_ASSERT_LOCKED(_lock); + evthread_debug_lock_mark_unlocked(0, lock); + r = _original_cond_fns.wait_condition(_cond, lock->lock, tv); + evthread_debug_lock_mark_locked(0, lock); + return r; +} + +void +evthread_enable_lock_debuging(void) +{ + struct evthread_lock_callbacks cbs = { + EVTHREAD_LOCK_API_VERSION, + EVTHREAD_LOCKTYPE_RECURSIVE, + debug_lock_alloc, + debug_lock_free, + debug_lock_lock, + debug_lock_unlock + }; + if (_evthread_lock_debugging_enabled) + return; + memcpy(&_original_lock_fns, &_evthread_lock_fns, + sizeof(struct evthread_lock_callbacks)); + memcpy(&_evthread_lock_fns, &cbs, + sizeof(struct evthread_lock_callbacks)); + + memcpy(&_original_cond_fns, &_evthread_cond_fns, + sizeof(struct evthread_condition_callbacks)); + _evthread_cond_fns.wait_condition = debug_cond_wait; + _evthread_lock_debugging_enabled = 1; + + /* XXX return value should get checked. */ + event_global_setup_locks_(0); +} + +int +_evthread_is_debug_lock_held(void *lock_) +{ + struct debug_lock *lock = lock_; + if (! lock->count) + return 0; + if (_evthread_id_fn) { + unsigned long me = _evthread_id_fn(); + if (lock->held_by != me) + return 0; + } + return 1; +} + +void * +_evthread_debug_get_real_lock(void *lock_) +{ + struct debug_lock *lock = lock_; + return lock->lock; +} + +void * +evthread_setup_global_lock_(void *lock_, unsigned locktype, int enable_locks) +{ + /* there are four cases here: + 1) we're turning on debugging; locking is not on. + 2) we're turning on debugging; locking is on. + 3) we're turning on locking; debugging is not on. + 4) we're turning on locking; debugging is on. */ + + if (!enable_locks && _original_lock_fns.alloc == NULL) { + /* Case 1: allocate a debug lock. */ + EVUTIL_ASSERT(lock_ == NULL); + return debug_lock_alloc(locktype); + } else if (!enable_locks && _original_lock_fns.alloc != NULL) { + /* Case 2: wrap the lock in a debug lock. */ + struct debug_lock *lock; + EVUTIL_ASSERT(lock_ != NULL); + + if (!(locktype & EVTHREAD_LOCKTYPE_RECURSIVE)) { + /* We can't wrap it: We need a recursive lock */ + _original_lock_fns.free(lock_, locktype); + return debug_lock_alloc(locktype); + } + lock = mm_malloc(sizeof(struct debug_lock)); + if (!lock) { + _original_lock_fns.free(lock_, locktype); + return NULL; + } + lock->lock = lock_; + lock->locktype = locktype; + lock->count = 0; + lock->held_by = 0; + return lock; + } else if (enable_locks && ! _evthread_lock_debugging_enabled) { + /* Case 3: allocate a regular lock */ + EVUTIL_ASSERT(lock_ == NULL); + return _evthread_lock_fns.alloc(locktype); + } else { + /* Case 4: Fill in a debug lock with a real lock */ + struct debug_lock *lock = lock_; + EVUTIL_ASSERT(enable_locks && + _evthread_lock_debugging_enabled); + EVUTIL_ASSERT(lock->locktype == locktype); + EVUTIL_ASSERT(lock->lock == NULL); + lock->lock = _original_lock_fns.alloc( + locktype|EVTHREAD_LOCKTYPE_RECURSIVE); + if (!lock->lock) { + lock->count = -200; + mm_free(lock); + return NULL; + } + return lock; + } +} + + +#ifndef EVTHREAD_EXPOSE_STRUCTS +unsigned long +_evthreadimpl_get_id() +{ + return _evthread_id_fn ? _evthread_id_fn() : 1; +} +void * +_evthreadimpl_lock_alloc(unsigned locktype) +{ + return _evthread_lock_fns.alloc ? + _evthread_lock_fns.alloc(locktype) : NULL; +} +void +_evthreadimpl_lock_free(void *lock, unsigned locktype) +{ + if (_evthread_lock_fns.free) + _evthread_lock_fns.free(lock, locktype); +} +int +_evthreadimpl_lock_lock(unsigned mode, void *lock) +{ + if (_evthread_lock_fns.lock) + return _evthread_lock_fns.lock(mode, lock); + else + return 0; +} +int +_evthreadimpl_lock_unlock(unsigned mode, void *lock) +{ + if (_evthread_lock_fns.unlock) + return _evthread_lock_fns.unlock(mode, lock); + else + return 0; +} +void * +_evthreadimpl_cond_alloc(unsigned condtype) +{ + return _evthread_cond_fns.alloc_condition ? + _evthread_cond_fns.alloc_condition(condtype) : NULL; +} +void +_evthreadimpl_cond_free(void *cond) +{ + if (_evthread_cond_fns.free_condition) + _evthread_cond_fns.free_condition(cond); +} +int +_evthreadimpl_cond_signal(void *cond, int broadcast) +{ + if (_evthread_cond_fns.signal_condition) + return _evthread_cond_fns.signal_condition(cond, broadcast); + else + return 0; +} +int +_evthreadimpl_cond_wait(void *cond, void *lock, const struct timeval *tv) +{ + if (_evthread_cond_fns.wait_condition) + return _evthread_cond_fns.wait_condition(cond, lock, tv); + else + return 0; +} +int +_evthreadimpl_is_lock_debugging_enabled(void) +{ + return _evthread_lock_debugging_enabled; +} + +int +_evthreadimpl_locking_enabled(void) +{ + return _evthread_lock_fns.lock != NULL; +} +#endif + +#endif diff --git a/libevent/evthread_pthread.c b/libevent/evthread_pthread.c new file mode 100644 index 0000000..c4d06ea --- /dev/null +++ b/libevent/evthread_pthread.c @@ -0,0 +1,189 @@ +/* + * Copyright 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +/* With glibc we need to define this to get PTHREAD_MUTEX_RECURSIVE. */ +#define _GNU_SOURCE +#include + +struct event_base; +#include "event2/thread.h" + +#include +#include +#include "mm-internal.h" +#include "evthread-internal.h" + +static pthread_mutexattr_t attr_recursive; + +static void * +evthread_posix_lock_alloc(unsigned locktype) +{ + pthread_mutexattr_t *attr = NULL; + pthread_mutex_t *lock = mm_malloc(sizeof(pthread_mutex_t)); + if (!lock) + return NULL; + if (locktype & EVTHREAD_LOCKTYPE_RECURSIVE) + attr = &attr_recursive; + if (pthread_mutex_init(lock, attr)) { + mm_free(lock); + return NULL; + } + return lock; +} + +static void +evthread_posix_lock_free(void *_lock, unsigned locktype) +{ + pthread_mutex_t *lock = _lock; + pthread_mutex_destroy(lock); + mm_free(lock); +} + +static int +evthread_posix_lock(unsigned mode, void *_lock) +{ + pthread_mutex_t *lock = _lock; + if (mode & EVTHREAD_TRY) + return pthread_mutex_trylock(lock); + else + return pthread_mutex_lock(lock); +} + +static int +evthread_posix_unlock(unsigned mode, void *_lock) +{ + pthread_mutex_t *lock = _lock; + return pthread_mutex_unlock(lock); +} + +static unsigned long +evthread_posix_get_id(void) +{ + union { + pthread_t thr; +#if _EVENT_SIZEOF_PTHREAD_T > _EVENT_SIZEOF_LONG + ev_uint64_t id; +#else + unsigned long id; +#endif + } r; +#if _EVENT_SIZEOF_PTHREAD_T < _EVENT_SIZEOF_LONG + memset(&r, 0, sizeof(r)); +#endif + r.thr = pthread_self(); + return (unsigned long)r.id; +} + +static void * +evthread_posix_cond_alloc(unsigned condflags) +{ + pthread_cond_t *cond = mm_malloc(sizeof(pthread_cond_t)); + if (!cond) + return NULL; + if (pthread_cond_init(cond, NULL)) { + mm_free(cond); + return NULL; + } + return cond; +} + +static void +evthread_posix_cond_free(void *_cond) +{ + pthread_cond_t *cond = _cond; + pthread_cond_destroy(cond); + mm_free(cond); +} + +static int +evthread_posix_cond_signal(void *_cond, int broadcast) +{ + pthread_cond_t *cond = _cond; + int r; + if (broadcast) + r = pthread_cond_broadcast(cond); + else + r = pthread_cond_signal(cond); + return r ? -1 : 0; +} + +static int +evthread_posix_cond_wait(void *_cond, void *_lock, const struct timeval *tv) +{ + int r; + pthread_cond_t *cond = _cond; + pthread_mutex_t *lock = _lock; + + if (tv) { + struct timeval now, abstime; + struct timespec ts; + evutil_gettimeofday(&now, NULL); + evutil_timeradd(&now, tv, &abstime); + ts.tv_sec = abstime.tv_sec; + ts.tv_nsec = abstime.tv_usec*1000; + r = pthread_cond_timedwait(cond, lock, &ts); + if (r == ETIMEDOUT) + return 1; + else if (r) + return -1; + else + return 0; + } else { + r = pthread_cond_wait(cond, lock); + return r ? -1 : 0; + } +} + +int +evthread_use_pthreads(void) +{ + struct evthread_lock_callbacks cbs = { + EVTHREAD_LOCK_API_VERSION, + EVTHREAD_LOCKTYPE_RECURSIVE, + evthread_posix_lock_alloc, + evthread_posix_lock_free, + evthread_posix_lock, + evthread_posix_unlock + }; + struct evthread_condition_callbacks cond_cbs = { + EVTHREAD_CONDITION_API_VERSION, + evthread_posix_cond_alloc, + evthread_posix_cond_free, + evthread_posix_cond_signal, + evthread_posix_cond_wait + }; + /* Set ourselves up to get recursive locks. */ + if (pthread_mutexattr_init(&attr_recursive)) + return -1; + if (pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE)) + return -1; + + evthread_set_lock_callbacks(&cbs); + evthread_set_condition_callbacks(&cond_cbs); + evthread_set_id_callback(evthread_posix_get_id); + return 0; +} diff --git a/libevent/evthread_win32.c b/libevent/evthread_win32.c new file mode 100644 index 0000000..2389d72 --- /dev/null +++ b/libevent/evthread_win32.c @@ -0,0 +1,339 @@ +/* + * Copyright 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#ifdef WIN32 +#ifndef _WIN32_WINNT +/* Minimum required for InitializeCriticalSectionAndSpinCount */ +#define _WIN32_WINNT 0x0403 +#endif +#include +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include +#endif + +struct event_base; +#include "event2/thread.h" + +#include "mm-internal.h" +#include "evthread-internal.h" + +#define SPIN_COUNT 2000 + +static void * +evthread_win32_lock_create(unsigned locktype) +{ + CRITICAL_SECTION *lock = mm_malloc(sizeof(CRITICAL_SECTION)); + if (!lock) + return NULL; + if (InitializeCriticalSectionAndSpinCount(lock, SPIN_COUNT) == 0) { + mm_free(lock); + return NULL; + } + return lock; +} + +static void +evthread_win32_lock_free(void *_lock, unsigned locktype) +{ + CRITICAL_SECTION *lock = _lock; + DeleteCriticalSection(lock); + mm_free(lock); +} + +static int +evthread_win32_lock(unsigned mode, void *_lock) +{ + CRITICAL_SECTION *lock = _lock; + if ((mode & EVTHREAD_TRY)) { + return ! TryEnterCriticalSection(lock); + } else { + EnterCriticalSection(lock); + return 0; + } +} + +static int +evthread_win32_unlock(unsigned mode, void *_lock) +{ + CRITICAL_SECTION *lock = _lock; + LeaveCriticalSection(lock); + return 0; +} + +static unsigned long +evthread_win32_get_id(void) +{ + return (unsigned long) GetCurrentThreadId(); +} + +#ifdef WIN32_HAVE_CONDITION_VARIABLES +static void WINAPI (*InitializeConditionVariable_fn)(PCONDITION_VARIABLE) + = NULL; +static BOOL WINAPI (*SleepConditionVariableCS_fn)( + PCONDITION_VARIABLE, PCRITICAL_SECTION, DWORD) = NULL; +static void WINAPI (*WakeAllConditionVariable_fn)(PCONDITION_VARIABLE) = NULL; +static void WINAPI (*WakeConditionVariable_fn)(PCONDITION_VARIABLE) = NULL; + +static int +evthread_win32_condvar_init(void) +{ + HANDLE lib; + + lib = GetModuleHandle(TEXT("kernel32.dll")); + if (lib == NULL) + return 0; + +#define LOAD(name) \ + name##_fn = GetProcAddress(lib, #name) + LOAD(InitializeConditionVariable); + LOAD(SleepConditionVariable); + LOAD(WakeAllConditionVariable); + LOAD(WakeConditionVariable); + + return InitializeConditionVariable_fn && SleepConditionVariableCS_fn && + WakeAllConditionVariable_fn && WakeConditionVariable_fn; +} + +/* XXXX Even if we can build this, we don't necessarily want to: the functions + * in question didn't exist before Vista, so we'd better LoadProc them. */ +static void * +evthread_win32_condvar_alloc(unsigned condflags) +{ + CONDITION_VARIABLE *cond = mm_malloc(sizeof(CONDITION_VARIABLE)); + if (!cond) + return NULL; + InitializeConditionVariable_fn(cond); + return cond; +} + +static void +evthread_win32_condvar_free(void *_cond) +{ + CONDITION_VARIABLE *cond = _cond; + /* There doesn't _seem_ to be a cleaup fn here... */ + mm_free(cond); +} + +static int +evthread_win32_condvar_signal(void *_cond, int broadcast) +{ + CONDITION_VARIABLE *cond = _cond; + if (broadcast) + WakeAllConditionVariable_fn(cond); + else + WakeConditionVariable_fn(cond); + return 0; +} + +static int +evthread_win32_condvar_wait(void *_cond, void *_lock, const struct timeval *tv) +{ + CONDITION_VARIABLE *cond = _cond; + CRITICAL_SECTION *lock = _lock; + DWORD ms, err; + BOOL result; + + if (tv) + ms = evutil_tv_to_msec(tv); + else + ms = INFINITE; + result = SleepConditionVariableCS_fn(cond, lock, ms); + if (result) { + if (GetLastError() == WAIT_TIMEOUT) + return 1; + else + return -1; + } else { + return 0; + } +} +#endif + +struct evthread_win32_cond { + HANDLE event; + + CRITICAL_SECTION lock; + int n_waiting; + int n_to_wake; + int generation; +}; + +static void * +evthread_win32_cond_alloc(unsigned flags) +{ + struct evthread_win32_cond *cond; + if (!(cond = mm_malloc(sizeof(struct evthread_win32_cond)))) + return NULL; + if (InitializeCriticalSectionAndSpinCount(&cond->lock, SPIN_COUNT)==0) { + mm_free(cond); + return NULL; + } + if ((cond->event = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) { + DeleteCriticalSection(&cond->lock); + mm_free(cond); + return NULL; + } + cond->n_waiting = cond->n_to_wake = cond->generation = 0; + return cond; +} + +static void +evthread_win32_cond_free(void *_cond) +{ + struct evthread_win32_cond *cond = _cond; + DeleteCriticalSection(&cond->lock); + CloseHandle(cond->event); + mm_free(cond); +} + +static int +evthread_win32_cond_signal(void *_cond, int broadcast) +{ + struct evthread_win32_cond *cond = _cond; + EnterCriticalSection(&cond->lock); + if (broadcast) + cond->n_to_wake = cond->n_waiting; + else + ++cond->n_to_wake; + cond->generation++; + SetEvent(cond->event); + LeaveCriticalSection(&cond->lock); + return 0; +} + +static int +evthread_win32_cond_wait(void *_cond, void *_lock, const struct timeval *tv) +{ + struct evthread_win32_cond *cond = _cond; + CRITICAL_SECTION *lock = _lock; + int generation_at_start; + int waiting = 1; + int result = -1; + DWORD ms = INFINITE, ms_orig = INFINITE, startTime, endTime; + if (tv) + ms_orig = ms = evutil_tv_to_msec(tv); + + EnterCriticalSection(&cond->lock); + ++cond->n_waiting; + generation_at_start = cond->generation; + LeaveCriticalSection(&cond->lock); + + LeaveCriticalSection(lock); + + startTime = GetTickCount(); + do { + DWORD res; + res = WaitForSingleObject(cond->event, ms); + EnterCriticalSection(&cond->lock); + if (cond->n_to_wake && + cond->generation != generation_at_start) { + --cond->n_to_wake; + --cond->n_waiting; + result = 0; + waiting = 0; + goto out; + } else if (res != WAIT_OBJECT_0) { + result = (res==WAIT_TIMEOUT) ? 1 : -1; + --cond->n_waiting; + waiting = 0; + goto out; + } else if (ms != INFINITE) { + endTime = GetTickCount(); + if (startTime + ms_orig <= endTime) { + result = 1; /* Timeout */ + --cond->n_waiting; + waiting = 0; + goto out; + } else { + ms = startTime + ms_orig - endTime; + } + } + /* If we make it here, we are still waiting. */ + if (cond->n_to_wake == 0) { + /* There is nobody else who should wake up; reset + * the event. */ + ResetEvent(cond->event); + } + out: + LeaveCriticalSection(&cond->lock); + } while (waiting); + + EnterCriticalSection(lock); + + EnterCriticalSection(&cond->lock); + if (!cond->n_waiting) + ResetEvent(cond->event); + LeaveCriticalSection(&cond->lock); + + return result; +} + +int +evthread_use_windows_threads(void) +{ + struct evthread_lock_callbacks cbs = { + EVTHREAD_LOCK_API_VERSION, + EVTHREAD_LOCKTYPE_RECURSIVE, + evthread_win32_lock_create, + evthread_win32_lock_free, + evthread_win32_lock, + evthread_win32_unlock + }; + + + struct evthread_condition_callbacks cond_cbs = { + EVTHREAD_CONDITION_API_VERSION, + evthread_win32_cond_alloc, + evthread_win32_cond_free, + evthread_win32_cond_signal, + evthread_win32_cond_wait + }; +#ifdef WIN32_HAVE_CONDITION_VARIABLES + struct evthread_condition_callbacks condvar_cbs = { + EVTHREAD_CONDITION_API_VERSION, + evthread_win32_condvar_alloc, + evthread_win32_condvar_free, + evthread_win32_condvar_signal, + evthread_win32_condvar_wait + }; +#endif + + evthread_set_lock_callbacks(&cbs); + evthread_set_id_callback(evthread_win32_get_id); +#ifdef WIN32_HAVE_CONDITION_VARIABLES + if (evthread_win32_condvar_init()) { + evthread_set_condition_callbacks(&condvar_cbs); + return 0; + } +#endif + evthread_set_condition_callbacks(&cond_cbs); + + return 0; +} + diff --git a/libevent/evutil.c b/libevent/evutil.c new file mode 100644 index 0000000..b663459 --- /dev/null +++ b/libevent/evutil.c @@ -0,0 +1,2177 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#include "event2/event-config.h" + +#define _GNU_SOURCE + +#ifdef WIN32 +#include +#include +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include +#include +#endif + +#include +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#ifdef _EVENT_HAVE_FCNTL_H +#include +#endif +#ifdef _EVENT_HAVE_STDLIB_H +#include +#endif +#include +#include +#include +#include +#ifdef _EVENT_HAVE_NETINET_IN_H +#include +#endif +#ifdef _EVENT_HAVE_NETINET_IN6_H +#include +#endif +#ifdef _EVENT_HAVE_ARPA_INET_H +#include +#endif + +#ifndef _EVENT_HAVE_GETTIMEOFDAY +#include +#include +#endif +#include + +#include "event2/util.h" +#include "util-internal.h" +#include "log-internal.h" +#include "mm-internal.h" + +#include "strlcpy-internal.h" +#include "ipv6-internal.h" + +#ifdef WIN32 +#define open _open +#define read _read +#define close _close +#define fstat _fstati64 +#define stat _stati64 +#endif + +int +evutil_open_closeonexec(const char *pathname, int flags, unsigned mode) +{ + int fd; + +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + + if (flags & O_CREAT) + fd = open(pathname, flags, (mode_t)mode); + else + fd = open(pathname, flags); + if (fd < 0) + return -1; + +#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC) + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) + return -1; +#endif + + return fd; +} + +/** + Read the contents of 'filename' into a newly allocated NUL-terminated + string. Set *content_out to hold this string, and *len_out to hold its + length (not including the appended NUL). If 'is_binary', open the file in + binary mode. + + Returns 0 on success, -1 if the open fails, and -2 for all other failures. + + Used internally only; may go away in a future version. + */ +int +evutil_read_file(const char *filename, char **content_out, size_t *len_out, + int is_binary) +{ + int fd, r; + struct stat st; + char *mem; + size_t read_so_far=0; + int mode = O_RDONLY; + + EVUTIL_ASSERT(content_out); + EVUTIL_ASSERT(len_out); + *content_out = NULL; + *len_out = 0; + +#ifdef O_BINARY + if (is_binary) + mode |= O_BINARY; +#endif + + fd = evutil_open_closeonexec(filename, mode, 0); + if (fd < 0) + return -1; + if (fstat(fd, &st) || st.st_size < 0 || + st.st_size > EV_SSIZE_MAX-1 ) { + close(fd); + return -2; + } + mem = mm_malloc((size_t)st.st_size + 1); + if (!mem) { + close(fd); + return -2; + } + read_so_far = 0; +#ifdef WIN32 +#define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x)) +#else +#define N_TO_READ(x) (x) +#endif + while ((r = read(fd, mem+read_so_far, N_TO_READ(st.st_size - read_so_far))) > 0) { + read_so_far += r; + if (read_so_far >= (size_t)st.st_size) + break; + EVUTIL_ASSERT(read_so_far < (size_t)st.st_size); + } + close(fd); + if (r < 0) { + mm_free(mem); + return -2; + } + mem[read_so_far] = 0; + + *len_out = read_so_far; + *content_out = mem; + return 0; +} + +int +evutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2]) +{ +#ifndef WIN32 + return socketpair(family, type, protocol, fd); +#else + return evutil_ersatz_socketpair(family, type, protocol, fd); +#endif +} + +int +evutil_ersatz_socketpair(int family, int type, int protocol, + evutil_socket_t fd[2]) +{ + /* This code is originally from Tor. Used with permission. */ + + /* This socketpair does not work when localhost is down. So + * it's really not the same thing at all. But it's close enough + * for now, and really, when localhost is down sometimes, we + * have other problems too. + */ +#ifdef WIN32 +#define ERR(e) WSA##e +#else +#define ERR(e) e +#endif + evutil_socket_t listener = -1; + evutil_socket_t connector = -1; + evutil_socket_t acceptor = -1; + struct sockaddr_in listen_addr; + struct sockaddr_in connect_addr; + ev_socklen_t size; + int saved_errno = -1; + + if (protocol + || (family != AF_INET +#ifdef AF_UNIX + && family != AF_UNIX +#endif + )) { + EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT)); + return -1; + } + if (!fd) { + EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL)); + return -1; + } + + listener = socket(AF_INET, type, 0); + if (listener < 0) + return -1; + memset(&listen_addr, 0, sizeof(listen_addr)); + listen_addr.sin_family = AF_INET; + listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + listen_addr.sin_port = 0; /* kernel chooses port. */ + if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) + == -1) + goto tidy_up_and_fail; + if (listen(listener, 1) == -1) + goto tidy_up_and_fail; + + connector = socket(AF_INET, type, 0); + if (connector < 0) + goto tidy_up_and_fail; + /* We want to find out the port number to connect to. */ + size = sizeof(connect_addr); + if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) + goto tidy_up_and_fail; + if (size != sizeof (connect_addr)) + goto abort_tidy_up_and_fail; + if (connect(connector, (struct sockaddr *) &connect_addr, + sizeof(connect_addr)) == -1) + goto tidy_up_and_fail; + + size = sizeof(listen_addr); + acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); + if (acceptor < 0) + goto tidy_up_and_fail; + if (size != sizeof(listen_addr)) + goto abort_tidy_up_and_fail; + evutil_closesocket(listener); + /* Now check we are talking to ourself by matching port and host on the + two sockets. */ + if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) + goto tidy_up_and_fail; + if (size != sizeof (connect_addr) + || listen_addr.sin_family != connect_addr.sin_family + || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr + || listen_addr.sin_port != connect_addr.sin_port) + goto abort_tidy_up_and_fail; + fd[0] = connector; + fd[1] = acceptor; + + return 0; + + abort_tidy_up_and_fail: + saved_errno = ERR(ECONNABORTED); + tidy_up_and_fail: + if (saved_errno < 0) + saved_errno = EVUTIL_SOCKET_ERROR(); + if (listener != -1) + evutil_closesocket(listener); + if (connector != -1) + evutil_closesocket(connector); + if (acceptor != -1) + evutil_closesocket(acceptor); + + EVUTIL_SET_SOCKET_ERROR(saved_errno); + return -1; +#undef ERR +} + +int +evutil_make_socket_nonblocking(evutil_socket_t fd) +{ +#ifdef WIN32 + { + u_long nonblocking = 1; + if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) { + event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd); + return -1; + } + } +#else + { + int flags; + if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { + event_warn("fcntl(%d, F_GETFL)", fd); + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { + event_warn("fcntl(%d, F_SETFL)", fd); + return -1; + } + } +#endif + return 0; +} + +int +evutil_make_listen_socket_reuseable(evutil_socket_t sock) +{ +#ifndef WIN32 + int one = 1; + /* REUSEADDR on Unix means, "don't hang on to this address after the + * listener is closed." On Windows, though, it means "don't keep other + * processes from binding to this address while we're using it. */ + return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, + (ev_socklen_t)sizeof(one)); +#else + return 0; +#endif +} + +int +evutil_make_socket_closeonexec(evutil_socket_t fd) +{ +#if !defined(WIN32) && defined(_EVENT_HAVE_SETFD) + int flags; + if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) { + event_warn("fcntl(%d, F_GETFD)", fd); + return -1; + } + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { + event_warn("fcntl(%d, F_SETFD)", fd); + return -1; + } +#endif + return 0; +} + +int +evutil_closesocket(evutil_socket_t sock) +{ +#ifndef WIN32 + return close(sock); +#else + return closesocket(sock); +#endif +} + +ev_int64_t +evutil_strtoll(const char *s, char **endptr, int base) +{ +#ifdef _EVENT_HAVE_STRTOLL + return (ev_int64_t)strtoll(s, endptr, base); +#elif _EVENT_SIZEOF_LONG == 8 + return (ev_int64_t)strtol(s, endptr, base); +#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 + /* XXXX on old versions of MS APIs, we only support base + * 10. */ + ev_int64_t r; + if (base != 10) + return 0; + r = (ev_int64_t) _atoi64(s); + while (isspace(*s)) + ++s; + if (*s == '-') + ++s; + while (isdigit(*s)) + ++s; + if (endptr) + *endptr = (char*) s; + return r; +#elif defined(WIN32) + return (ev_int64_t) _strtoi64(s, endptr, base); +#elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8 + long long r; + int n; + if (base != 10 && base != 16) + return 0; + if (base == 10) { + n = sscanf(s, "%lld", &r); + } else { + unsigned long long ru=0; + n = sscanf(s, "%llx", &ru); + if (ru > EV_INT64_MAX) + return 0; + r = (long long) ru; + } + if (n != 1) + return 0; + while (EVUTIL_ISSPACE(*s)) + ++s; + if (*s == '-') + ++s; + if (base == 10) { + while (EVUTIL_ISDIGIT(*s)) + ++s; + } else { + while (EVUTIL_ISXDIGIT(*s)) + ++s; + } + if (endptr) + *endptr = (char*) s; + return r; +#else +#error "I don't know how to parse 64-bit integers." +#endif +} + +#ifndef _EVENT_HAVE_GETTIMEOFDAY +/* No gettimeofday; this muse be windows. */ +int +evutil_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + struct _timeb tb; + + if (tv == NULL) + return -1; + + /* XXXX + * _ftime is not the greatest interface here; GetSystemTimeAsFileTime + * would give us better resolution, whereas something cobbled together + * with GetTickCount could maybe give us monotonic behavior. + * + * Either way, I think this value might be skewed to ignore the + * timezone, and just return local time. That's not so good. + */ + _ftime(&tb); + tv->tv_sec = (long) tb.time; + tv->tv_usec = ((int) tb.millitm) * 1000; + return 0; +} +#endif + +#ifdef WIN32 +int +evutil_socket_geterror(evutil_socket_t sock) +{ + int optval, optvallen=sizeof(optval); + int err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK && sock >= 0) { + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, + &optvallen)) + return err; + if (optval) + return optval; + } + return err; +} +#endif + +/* XXX we should use an enum here. */ +/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */ +int +evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen) +{ + int made_fd = 0; + + if (*fd_ptr < 0) { + if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) + goto err; + made_fd = 1; + if (evutil_make_socket_nonblocking(*fd_ptr) < 0) { + goto err; + } + } + + if (connect(*fd_ptr, sa, socklen) < 0) { + int e = evutil_socket_geterror(*fd_ptr); + if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) + return 0; + if (EVUTIL_ERR_CONNECT_REFUSED(e)) + return 2; + goto err; + } else { + return 1; + } + +err: + if (made_fd) { + evutil_closesocket(*fd_ptr); + *fd_ptr = -1; + } + return -1; +} + +/* Check whether a socket on which we called connect() is done + connecting. Return 1 for connected, 0 for not yet, -1 for error. In the + error case, set the current socket errno to the error that happened during + the connect operation. */ +int +evutil_socket_finished_connecting(evutil_socket_t fd) +{ + int e; + ev_socklen_t elen = sizeof(e); + + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0) + return -1; + + if (e) { + if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) + return 0; + EVUTIL_SET_SOCKET_ERROR(e); + return -1; + } + + return 1; +} + +#if (EVUTIL_AI_PASSIVE|EVUTIL_AI_CANONNAME|EVUTIL_AI_NUMERICHOST| \ + EVUTIL_AI_NUMERICSERV|EVUTIL_AI_V4MAPPED|EVUTIL_AI_ALL| \ + EVUTIL_AI_ADDRCONFIG) != \ + (EVUTIL_AI_PASSIVE^EVUTIL_AI_CANONNAME^EVUTIL_AI_NUMERICHOST^ \ + EVUTIL_AI_NUMERICSERV^EVUTIL_AI_V4MAPPED^EVUTIL_AI_ALL^ \ + EVUTIL_AI_ADDRCONFIG) +#error "Some of our EVUTIL_AI_* flags seem to overlap with system AI_* flags" +#endif + +/* We sometimes need to know whether we have an ipv4 address and whether we + have an ipv6 address. If 'have_checked_interfaces', then we've already done + the test. If 'had_ipv4_address', then it turns out we had an ipv4 address. + If 'had_ipv6_address', then it turns out we had an ipv6 address. These are + set by evutil_check_interfaces. */ +static int have_checked_interfaces, had_ipv4_address, had_ipv6_address; + +/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 + */ +#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127) + +/* Macro: True iff the IPv4 address 'addr', in host order, is a class D + * (multiclass) address. + */ +#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0) + +/* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if + * the test seemed successful. */ +static int +evutil_check_interfaces(int force_recheck) +{ + const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00"; + evutil_socket_t fd = -1; + struct sockaddr_in sin, sin_out; + struct sockaddr_in6 sin6, sin6_out; + ev_socklen_t sin_out_len = sizeof(sin_out); + ev_socklen_t sin6_out_len = sizeof(sin6_out); + int r; + char buf[128]; + if (have_checked_interfaces && !force_recheck) + return 0; + + /* To check whether we have an interface open for a given protocol, we + * try to make a UDP 'connection' to a remote host on the internet. + * We don't actually use it, so the address doesn't matter, but we + * want to pick one that keep us from using a host- or link-local + * interface. */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(53); + r = evutil_inet_pton(AF_INET, "18.244.0.188", &sin.sin_addr); + EVUTIL_ASSERT(r); + + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(53); + r = evutil_inet_pton(AF_INET6, "2001:4860:b002::68", &sin6.sin6_addr); + EVUTIL_ASSERT(r); + + memset(&sin_out, 0, sizeof(sin_out)); + memset(&sin6_out, 0, sizeof(sin6_out)); + + /* XXX some errnos mean 'no address'; some mean 'not enough sockets'. */ + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && + connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == 0 && + getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) { + /* We might have an IPv4 interface. */ + ev_uint32_t addr = ntohl(sin_out.sin_addr.s_addr); + if (addr == 0 || + EVUTIL_V4ADDR_IS_LOCALHOST(addr) || + EVUTIL_V4ADDR_IS_CLASSD(addr)) { + evutil_inet_ntop(AF_INET, &sin_out.sin_addr, + buf, sizeof(buf)); + /* This is a reserved, ipv4compat, ipv4map, loopback, + * link-local or unspecified address. The host should + * never have given it to us; it could never connect + * to sin. */ + event_warnx("Got a strange local ipv4 address %s",buf); + } else { + event_debug(("Detected an IPv4 interface")); + had_ipv4_address = 1; + } + } + if (fd >= 0) + evutil_closesocket(fd); + + if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && + connect(fd, (struct sockaddr*)&sin6, sizeof(sin6)) == 0 && + getsockname(fd, (struct sockaddr*)&sin6_out, &sin6_out_len) == 0) { + /* We might have an IPv6 interface. */ + const unsigned char *addr = + (unsigned char*)sin6_out.sin6_addr.s6_addr; + if (!memcmp(addr, ZEROES, 8) || + (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80)) { + /* This is a reserved, ipv4compat, ipv4map, loopback, + * link-local or unspecified address. The host should + * never have given it to us; it could never connect + * to sin6. */ + evutil_inet_ntop(AF_INET6, &sin6_out.sin6_addr, + buf, sizeof(buf)); + event_warnx("Got a strange local ipv6 address %s",buf); + } else { + event_debug(("Detected an IPv4 interface")); + had_ipv6_address = 1; + } + } + + if (fd >= 0) + evutil_closesocket(fd); + + return 0; +} + +/* Internal addrinfo flag. This one is set when we allocate the addrinfo from + * inside libevent. Otherwise, the built-in getaddrinfo() function allocated + * it, and we should trust what they said. + **/ +#define EVUTIL_AI_LIBEVENT_ALLOCATED 0x80000000 + +/* Helper: construct a new addrinfo containing the socket address in + * 'sa', which must be a sockaddr_in or a sockaddr_in6. Take the + * socktype and protocol info from hints. If they weren't set, then + * allocate both a TCP and a UDP addrinfo. + */ +struct evutil_addrinfo * +evutil_new_addrinfo(struct sockaddr *sa, ev_socklen_t socklen, + const struct evutil_addrinfo *hints) +{ + struct evutil_addrinfo *res; + EVUTIL_ASSERT(hints); + + if (hints->ai_socktype == 0 && hints->ai_protocol == 0) { + /* Indecisive user! Give them a UDP and a TCP. */ + struct evutil_addrinfo *r1, *r2; + struct evutil_addrinfo tmp; + memcpy(&tmp, hints, sizeof(tmp)); + tmp.ai_socktype = SOCK_STREAM; tmp.ai_protocol = IPPROTO_TCP; + r1 = evutil_new_addrinfo(sa, socklen, &tmp); + if (!r1) + return NULL; + tmp.ai_socktype = SOCK_DGRAM; tmp.ai_protocol = IPPROTO_UDP; + r2 = evutil_new_addrinfo(sa, socklen, &tmp); + if (!r2) { + evutil_freeaddrinfo(r1); + return NULL; + } + r1->ai_next = r2; + return r1; + } + + /* We're going to allocate extra space to hold the sockaddr. */ + res = mm_calloc(1,sizeof(struct evutil_addrinfo)+socklen); + if (!res) + return NULL; + res->ai_addr = (struct sockaddr*) + (((char*)res) + sizeof(struct evutil_addrinfo)); + memcpy(res->ai_addr, sa, socklen); + res->ai_addrlen = socklen; + res->ai_family = sa->sa_family; /* Same or not? XXX */ + res->ai_flags = EVUTIL_AI_LIBEVENT_ALLOCATED; + res->ai_socktype = hints->ai_socktype; + res->ai_protocol = hints->ai_protocol; + + return res; +} + +/* Append the addrinfo 'append' to the end of 'first', and return the start of + * the list. Either element can be NULL, in which case we return the element + * that is not NULL. */ +struct evutil_addrinfo * +evutil_addrinfo_append(struct evutil_addrinfo *first, + struct evutil_addrinfo *append) +{ + struct evutil_addrinfo *ai = first; + if (!ai) + return append; + while (ai->ai_next) + ai = ai->ai_next; + ai->ai_next = append; + + return first; +} + +static int +parse_numeric_servname(const char *servname) +{ + int n; + char *endptr=NULL; + n = (int) strtol(servname, &endptr, 10); + if (n>=0 && n <= 65535 && servname[0] && endptr && !endptr[0]) + return n; + else + return -1; +} + +/** Parse a service name in 'servname', which can be a decimal port. + * Return the port number, or -1 on error. + */ +static int +evutil_parse_servname(const char *servname, const char *protocol, + const struct evutil_addrinfo *hints) +{ + int n = parse_numeric_servname(servname); + if (n>=0) + return n; +#if defined(_EVENT_HAVE_GETSERVBYNAME) || defined(WIN32) + if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) { + struct servent *ent = getservbyname(servname, protocol); + if (ent) { + return ntohs(ent->s_port); + } + } +#endif + return -1; +} + +/* Return a string corresponding to a protocol number that we can pass to + * getservyname. */ +static const char * +evutil_unparse_protoname(int proto) +{ + switch (proto) { + case 0: + return NULL; + case IPPROTO_TCP: + return "tcp"; + case IPPROTO_UDP: + return "udp"; +#ifdef IPPROTO_SCTP + case IPPROTO_SCTP: + return "sctp"; +#endif + default: +#ifdef _EVENT_HAVE_GETPROTOBYNUMBER + { + struct protoent *ent = getprotobynumber(proto); + if (ent) + return ent->p_name; + } +#endif + return NULL; + } +} + +static void +evutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints) +{ + /* If we can guess the protocol from the socktype, do so. */ + if (!hints->ai_protocol && hints->ai_socktype) { + if (hints->ai_socktype == SOCK_DGRAM) + hints->ai_protocol = IPPROTO_UDP; + else if (hints->ai_socktype == SOCK_STREAM) + hints->ai_protocol = IPPROTO_TCP; + } + + /* Set the socktype if it isn't set. */ + if (!hints->ai_socktype && hints->ai_protocol) { + if (hints->ai_protocol == IPPROTO_UDP) + hints->ai_socktype = SOCK_DGRAM; + else if (hints->ai_protocol == IPPROTO_TCP) + hints->ai_socktype = SOCK_STREAM; +#ifdef IPPROTO_SCTP + else if (hints->ai_protocol == IPPROTO_SCTP) + hints->ai_socktype = SOCK_STREAM; +#endif + } +} + +#if AF_UNSPEC != PF_UNSPEC +#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC" +#endif + +/** Implements the part of looking up hosts by name that's common to both + * the blocking and nonblocking resolver: + * - Adjust 'hints' to have a reasonable socktype and protocol. + * - Look up the port based on 'servname', and store it in *portnum, + * - Handle the nodename==NULL case + * - Handle some invalid arguments cases. + * - Handle the cases where nodename is an IPv4 or IPv6 address. + * + * If we need the resolver to look up the hostname, we return + * EVUTIL_EAI_NEED_RESOLVE. Otherwise, we can completely implement + * getaddrinfo: we return 0 or an appropriate EVUTIL_EAI_* error, and + * set *res as getaddrinfo would. + */ +int +evutil_getaddrinfo_common(const char *nodename, const char *servname, + struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum) +{ + int port = 0; + const char *pname; + + if (nodename == NULL && servname == NULL) + return EVUTIL_EAI_NONAME; + + /* We only understand 3 families */ + if (hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET && + hints->ai_family != PF_INET6) + return EVUTIL_EAI_FAMILY; + + evutil_getaddrinfo_infer_protocols(hints); + + /* Look up the port number and protocol, if possible. */ + pname = evutil_unparse_protoname(hints->ai_protocol); + if (servname) { + /* XXXX We could look at the protocol we got back from + * getservbyname, but it doesn't seem too useful. */ + port = evutil_parse_servname(servname, pname, hints); + if (port < 0) { + return EVUTIL_EAI_NONAME; + } + } + + /* If we have no node name, then we're supposed to bind to 'any' and + * connect to localhost. */ + if (nodename == NULL) { + struct evutil_addrinfo *res4=NULL, *res6=NULL; + if (hints->ai_family != PF_INET) { /* INET6 or UNSPEC. */ + struct sockaddr_in6 sin6; + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(port); + if (hints->ai_flags & EVUTIL_AI_PASSIVE) { + /* Bind to :: */ + } else { + /* connect to ::1 */ + sin6.sin6_addr.s6_addr[15] = 1; + } + res6 = evutil_new_addrinfo((struct sockaddr*)&sin6, + sizeof(sin6), hints); + if (!res6) + return EVUTIL_EAI_MEMORY; + } + + if (hints->ai_family != PF_INET6) { /* INET or UNSPEC */ + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + if (hints->ai_flags & EVUTIL_AI_PASSIVE) { + /* Bind to 0.0.0.0 */ + } else { + /* connect to 127.0.0.1 */ + sin.sin_addr.s_addr = htonl(0x7f000001); + } + res4 = evutil_new_addrinfo((struct sockaddr*)&sin, + sizeof(sin), hints); + if (!res4) { + if (res6) + evutil_freeaddrinfo(res6); + return EVUTIL_EAI_MEMORY; + } + } + *res = evutil_addrinfo_append(res4, res6); + return 0; + } + + /* If we can, we should try to parse the hostname without resolving + * it. */ + /* Try ipv6. */ + if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) { + struct sockaddr_in6 sin6; + memset(&sin6, 0, sizeof(sin6)); + if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) { + /* Got an ipv6 address. */ + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(port); + *res = evutil_new_addrinfo((struct sockaddr*)&sin6, + sizeof(sin6), hints); + if (!*res) + return EVUTIL_EAI_MEMORY; + return 0; + } + } + + /* Try ipv4. */ + if (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC) { + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) { + /* Got an ipv6 address. */ + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + *res = evutil_new_addrinfo((struct sockaddr*)&sin, + sizeof(sin), hints); + if (!*res) + return EVUTIL_EAI_MEMORY; + return 0; + } + } + + + /* If we have reached this point, we definitely need to do a DNS + * lookup. */ + if ((hints->ai_flags & EVUTIL_AI_NUMERICHOST)) { + /* If we're not allowed to do one, then say so. */ + return EVUTIL_EAI_NONAME; + } + *portnum = port; + return EVUTIL_EAI_NEED_RESOLVE; +} + +#ifdef _EVENT_HAVE_GETADDRINFO +#define USE_NATIVE_GETADDRINFO +#endif + +#ifdef USE_NATIVE_GETADDRINFO +/* A mask of all the flags that we declare, so we can clear them before calling + * the native getaddrinfo */ +static const unsigned int ALL_NONNATIVE_AI_FLAGS = +#ifndef AI_PASSIVE + EVUTIL_AI_PASSIVE | +#endif +#ifndef AI_CANONNAME + EVUTIL_AI_CANONNAME | +#endif +#ifndef AI_NUMERICHOST + EVUTIL_AI_NUMERICHOST | +#endif +#ifndef AI_NUMERICSERV + EVUTIL_AI_NUMERICSERV | +#endif +#ifndef AI_ADDRCONFIG + EVUTIL_AI_ADDRCONFIG | +#endif +#ifndef AI_ALL + EVUTIL_AI_ALL | +#endif +#ifndef AI_V4MAPPED + EVUTIL_AI_V4MAPPED | +#endif + EVUTIL_AI_LIBEVENT_ALLOCATED; + +static const unsigned int ALL_NATIVE_AI_FLAGS = +#ifdef AI_PASSIVE + AI_PASSIVE | +#endif +#ifdef AI_CANONNAME + AI_CANONNAME | +#endif +#ifdef AI_NUMERICHOST + AI_NUMERICHOST | +#endif +#ifdef AI_NUMERICSERV + AI_NUMERICSERV | +#endif +#ifdef AI_ADDRCONFIG + AI_ADDRCONFIG | +#endif +#ifdef AI_ALL + AI_ALL | +#endif +#ifdef AI_V4MAPPED + AI_V4MAPPED | +#endif + 0; +#endif + +#ifndef USE_NATIVE_GETADDRINFO +/* Helper for systems with no getaddrinfo(): make one or more addrinfos out of + * a struct hostent. + */ +static struct evutil_addrinfo * +addrinfo_from_hostent(const struct hostent *ent, + int port, const struct evutil_addrinfo *hints) +{ + int i; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr *sa; + int socklen; + struct evutil_addrinfo *res=NULL, *ai; + void *addrp; + + if (ent->h_addrtype == PF_INET) { + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sa = (struct sockaddr *)&sin; + socklen = sizeof(struct sockaddr_in); + addrp = &sin.sin_addr; + if (ent->h_length != sizeof(sin.sin_addr)) { + event_warnx("Weird h_length from gethostbyname"); + return NULL; + } + } else if (ent->h_addrtype == PF_INET6) { + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(port); + sa = (struct sockaddr *)&sin6; + socklen = sizeof(struct sockaddr_in); + addrp = &sin6.sin6_addr; + if (ent->h_length != sizeof(sin6.sin6_addr)) { + event_warnx("Weird h_length from gethostbyname"); + return NULL; + } + } else + return NULL; + + for (i = 0; ent->h_addr_list[i]; ++i) { + memcpy(addrp, ent->h_addr_list[i], ent->h_length); + ai = evutil_new_addrinfo(sa, socklen, hints); + if (!ai) { + evutil_freeaddrinfo(res); + return NULL; + } + res = evutil_addrinfo_append(res, ai); + } + + if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) { + res->ai_canonname = mm_strdup(ent->h_name); + if (res->ai_canonname == NULL) { + evutil_freeaddrinfo(res); + return NULL; + } + } + + return res; +} +#endif + +/* If the EVUTIL_AI_ADDRCONFIG flag is set on hints->ai_flags, and + * hints->ai_family is PF_UNSPEC, then revise the value of hints->ai_family so + * that we'll only get addresses we could maybe connect to. + */ +void +evutil_adjust_hints_for_addrconfig(struct evutil_addrinfo *hints) +{ + if (!(hints->ai_flags & EVUTIL_AI_ADDRCONFIG)) + return; + if (hints->ai_family != PF_UNSPEC) + return; + if (!have_checked_interfaces) + evutil_check_interfaces(0); + if (had_ipv4_address && !had_ipv6_address) { + hints->ai_family = PF_INET; + } else if (!had_ipv4_address && had_ipv6_address) { + hints->ai_family = PF_INET6; + } +} + +#ifdef USE_NATIVE_GETADDRINFO +static int need_numeric_port_hack_=0; +static int need_socktype_protocol_hack_=0; +static int tested_for_getaddrinfo_hacks=0; + +/* Some older BSDs (like OpenBSD up to 4.6) used to believe that + giving a numeric port without giving an ai_socktype was verboten. + We test for this so we can apply an appropriate workaround. If it + turns out that the bug is present, then: + + - If nodename==NULL and servname is numeric, we build an answer + ourselves using evutil_getaddrinfo_common(). + + - If nodename!=NULL and servname is numeric, then we set + servname=NULL when calling getaddrinfo, and post-process the + result to set the ports on it. + + We test for this bug at runtime, since otherwise we can't have the + same binary run on multiple BSD versions. + + - Some versions of Solaris believe that it's nice to leave to protocol + field set to 0. We test for this so we can apply an appropriate + workaround. +*/ +static void +test_for_getaddrinfo_hacks(void) +{ + int r, r2; + struct evutil_addrinfo *ai=NULL, *ai2=NULL; + struct evutil_addrinfo hints; + + memset(&hints,0,sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = +#ifdef AI_NUMERICHOST + AI_NUMERICHOST | +#endif +#ifdef AI_NUMERICSERV + AI_NUMERICSERV | +#endif + 0; + r = getaddrinfo("1.2.3.4", "80", &hints, &ai); + hints.ai_socktype = SOCK_STREAM; + r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2); + if (r2 == 0 && r != 0) { + need_numeric_port_hack_=1; + } + if (ai2 && ai2->ai_protocol == 0) { + need_socktype_protocol_hack_=1; + } + + if (ai) + freeaddrinfo(ai); + if (ai2) + freeaddrinfo(ai2); + tested_for_getaddrinfo_hacks=1; +} + +static inline int +need_numeric_port_hack(void) +{ + if (!tested_for_getaddrinfo_hacks) + test_for_getaddrinfo_hacks(); + return need_numeric_port_hack_; +} + +static inline int +need_socktype_protocol_hack(void) +{ + if (!tested_for_getaddrinfo_hacks) + test_for_getaddrinfo_hacks(); + return need_socktype_protocol_hack_; +} + +static void +apply_numeric_port_hack(int port, struct evutil_addrinfo **ai) +{ + /* Now we run through the list and set the ports on all of the + * results where ports would make sense. */ + for ( ; *ai; ai = &(*ai)->ai_next) { + struct sockaddr *sa = (*ai)->ai_addr; + if (sa && sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in*)sa; + sin->sin_port = htons(port); + } else if (sa && sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; + sin6->sin6_port = htons(port); + } else { + /* A numeric port makes no sense here; remove this one + * from the list. */ + struct evutil_addrinfo *victim = *ai; + *ai = victim->ai_next; + victim->ai_next = NULL; + freeaddrinfo(victim); + } + } +} + +static int +apply_socktype_protocol_hack(struct evutil_addrinfo *ai) +{ + struct evutil_addrinfo *ai_new; + for (; ai; ai = ai->ai_next) { + evutil_getaddrinfo_infer_protocols(ai); + if (ai->ai_socktype || ai->ai_protocol) + continue; + ai_new = mm_malloc(sizeof(*ai_new)); + if (!ai_new) + return -1; + memcpy(ai_new, ai, sizeof(*ai_new)); + ai->ai_socktype = SOCK_STREAM; + ai->ai_protocol = IPPROTO_TCP; + ai_new->ai_socktype = SOCK_DGRAM; + ai_new->ai_protocol = IPPROTO_UDP; + + ai_new->ai_next = ai->ai_next; + ai->ai_next = ai_new; + } + return 0; +} +#endif + +int +evutil_getaddrinfo(const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res) +{ +#ifdef USE_NATIVE_GETADDRINFO + struct evutil_addrinfo hints; + int portnum=-1, need_np_hack, err; + + if (hints_in) { + memcpy(&hints, hints_in, sizeof(hints)); + } else { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + } + +#ifndef AI_ADDRCONFIG + /* Not every system has AI_ADDRCONFIG, so fake it. */ + if (hints.ai_family == PF_UNSPEC && + (hints.ai_flags & EVUTIL_AI_ADDRCONFIG)) { + evutil_adjust_hints_for_addrconfig(&hints); + } +#endif + +#ifndef AI_NUMERICSERV + /* Not every system has AI_NUMERICSERV, so fake it. */ + if (hints.ai_flags & EVUTIL_AI_NUMERICSERV) { + if (servname && parse_numeric_servname(servname)<0) + return EVUTIL_EAI_NONAME; + } +#endif + + /* Enough operating systems handle enough common non-resolve + * cases here weirdly enough that we are better off just + * overriding them. For example: + * + * - Windows doesn't like to infer the protocol from the + * socket type, or fill in socket or protocol types much at + * all. It also seems to do its own broken implicit + * always-on version of AI_ADDRCONFIG that keeps it from + * ever resolving even a literal IPv6 address when + * ai_addrtype is PF_UNSPEC. + */ +#ifdef WIN32 + { + int tmp_port; + err = evutil_getaddrinfo_common(nodename,servname,&hints, + res, &tmp_port); + if (err == 0 || + err == EVUTIL_EAI_MEMORY || + err == EVUTIL_EAI_NONAME) + return err; + /* If we make it here, the system getaddrinfo can + * have a crack at it. */ + } +#endif + + /* See documentation for need_numeric_port_hack above.*/ + need_np_hack = need_numeric_port_hack() && servname && !hints.ai_socktype + && ((portnum=parse_numeric_servname(servname)) >= 0); + if (need_np_hack) { + if (!nodename) + return evutil_getaddrinfo_common( + NULL,servname,&hints, res, &portnum); + servname = NULL; + } + + if (need_socktype_protocol_hack()) { + evutil_getaddrinfo_infer_protocols(&hints); + } + + /* Make sure that we didn't actually steal any AI_FLAGS values that + * the system is using. (This is a constant expression, and should ge + * optimized out.) + * + * XXXX Turn this into a compile-time failure rather than a run-time + * failure. + */ + EVUTIL_ASSERT((ALL_NONNATIVE_AI_FLAGS & ALL_NATIVE_AI_FLAGS) == 0); + + /* Clear any flags that only libevent understands. */ + hints.ai_flags &= ~ALL_NONNATIVE_AI_FLAGS; + + err = getaddrinfo(nodename, servname, &hints, res); + if (need_np_hack) + apply_numeric_port_hack(portnum, res); + + if (need_socktype_protocol_hack()) { + if (apply_socktype_protocol_hack(*res) < 0) { + evutil_freeaddrinfo(*res); + *res = NULL; + return EVUTIL_EAI_MEMORY; + } + } + return err; +#else + int port=0, err; + struct hostent *ent = NULL; + struct evutil_addrinfo hints; + + if (hints_in) { + memcpy(&hints, hints_in, sizeof(hints)); + } else { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + } + + evutil_adjust_hints_for_addrconfig(&hints); + + err = evutil_getaddrinfo_common(nodename, servname, &hints, res, &port); + if (err != EVUTIL_EAI_NEED_RESOLVE) { + /* We either succeeded or failed. No need to continue */ + return err; + } + + err = 0; + /* Use any of the various gethostbyname_r variants as available. */ + { +#ifdef _EVENT_HAVE_GETHOSTBYNAME_R_6_ARG + /* This one is what glibc provides. */ + char buf[2048]; + struct hostent hostent; + int r; + r = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), &ent, + &err); +#elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_5_ARG) + char buf[2048]; + struct hostent hostent; + ent = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), + &err); +#elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_3_ARG) + struct hostent_data data; + struct hostent hostent; + memset(&data, 0, sizeof(data)); + err = gethostbyname_r(nodename, &hostent, &data); + ent = err ? NULL : &hostent; +#else + /* fall back to gethostbyname. */ + /* XXXX This needs a lock everywhere but Windows. */ + ent = gethostbyname(nodename); +#ifdef WIN32 + err = WSAGetLastError(); +#else + err = h_errno; +#endif +#endif + + /* Now we have either ent or err set. */ + if (!ent) { + /* XXX is this right for windows ? */ + switch (err) { + case TRY_AGAIN: + return EVUTIL_EAI_AGAIN; + case NO_RECOVERY: + default: + return EVUTIL_EAI_FAIL; + case HOST_NOT_FOUND: + return EVUTIL_EAI_NONAME; + case NO_ADDRESS: +#if NO_DATA != NO_ADDRESS + case NO_DATA: +#endif + return EVUTIL_EAI_NODATA; + } + } + + if (ent->h_addrtype != hints.ai_family && + hints.ai_family != PF_UNSPEC) { + /* This wasn't the type we were hoping for. Too bad + * we never had a chance to ask gethostbyname for what + * we wanted. */ + return EVUTIL_EAI_NONAME; + } + + /* Make sure we got _some_ answers. */ + if (ent->h_length == 0) + return EVUTIL_EAI_NODATA; + + /* If we got an address type we don't know how to make a + sockaddr for, give up. */ + if (ent->h_addrtype != PF_INET && ent->h_addrtype != PF_INET6) + return EVUTIL_EAI_FAMILY; + + *res = addrinfo_from_hostent(ent, port, &hints); + if (! *res) + return EVUTIL_EAI_MEMORY; + } + + return 0; +#endif +} + +void +evutil_freeaddrinfo(struct evutil_addrinfo *ai) +{ +#ifdef _EVENT_HAVE_GETADDRINFO + if (!(ai->ai_flags & EVUTIL_AI_LIBEVENT_ALLOCATED)) { + freeaddrinfo(ai); + return; + } +#endif + while (ai) { + struct evutil_addrinfo *next = ai->ai_next; + if (ai->ai_canonname) + mm_free(ai->ai_canonname); + mm_free(ai); + ai = next; + } +} + +static evdns_getaddrinfo_fn evdns_getaddrinfo_impl = NULL; + +void +evutil_set_evdns_getaddrinfo_fn(evdns_getaddrinfo_fn fn) +{ + if (!evdns_getaddrinfo_impl) + evdns_getaddrinfo_impl = fn; +} + +/* Internal helper function: act like evdns_getaddrinfo if dns_base is set; + * otherwise do a blocking resolve and pass the result to the callback in the + * way that evdns_getaddrinfo would. + */ +int +evutil_getaddrinfo_async(struct evdns_base *dns_base, + const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, + void (*cb)(int, struct evutil_addrinfo *, void *), void *arg) +{ + if (dns_base && evdns_getaddrinfo_impl) { + evdns_getaddrinfo_impl( + dns_base, nodename, servname, hints_in, cb, arg); + } else { + struct evutil_addrinfo *ai=NULL; + int err; + err = evutil_getaddrinfo(nodename, servname, hints_in, &ai); + cb(err, ai, arg); + } + return 0; +} + +const char * +evutil_gai_strerror(int err) +{ + /* As a sneaky side-benefit, this case statement will get most + * compilers to tell us if any of the error codes we defined + * conflict with the platform's native error codes. */ + switch (err) { + case EVUTIL_EAI_CANCEL: + return "Request canceled"; + case 0: + return "No error"; + + case EVUTIL_EAI_ADDRFAMILY: + return "address family for nodename not supported"; + case EVUTIL_EAI_AGAIN: + return "temporary failure in name resolution"; + case EVUTIL_EAI_BADFLAGS: + return "invalid value for ai_flags"; + case EVUTIL_EAI_FAIL: + return "non-recoverable failure in name resolution"; + case EVUTIL_EAI_FAMILY: + return "ai_family not supported"; + case EVUTIL_EAI_MEMORY: + return "memory allocation failure"; + case EVUTIL_EAI_NODATA: + return "no address associated with nodename"; + case EVUTIL_EAI_NONAME: + return "nodename nor servname provided, or not known"; + case EVUTIL_EAI_SERVICE: + return "servname not supported for ai_socktype"; + case EVUTIL_EAI_SOCKTYPE: + return "ai_socktype not supported"; + case EVUTIL_EAI_SYSTEM: + return "system error"; + default: +#if defined(USE_NATIVE_GETADDRINFO) && defined(WIN32) + return gai_strerrorA(err); +#elif defined(USE_NATIVE_GETADDRINFO) + return gai_strerror(err); +#else + return "Unknown error code"; +#endif + } +} + +#ifdef WIN32 +#define E(code, s) { code, (s " [" #code " ]") } +static struct { int code; const char *msg; } windows_socket_errors[] = { + E(WSAEINTR, "Interrupted function call"), + E(WSAEACCES, "Permission denied"), + E(WSAEFAULT, "Bad address"), + E(WSAEINVAL, "Invalid argument"), + E(WSAEMFILE, "Too many open files"), + E(WSAEWOULDBLOCK, "Resource temporarily unavailable"), + E(WSAEINPROGRESS, "Operation now in progress"), + E(WSAEALREADY, "Operation already in progress"), + E(WSAENOTSOCK, "Socket operation on nonsocket"), + E(WSAEDESTADDRREQ, "Destination address required"), + E(WSAEMSGSIZE, "Message too long"), + E(WSAEPROTOTYPE, "Protocol wrong for socket"), + E(WSAENOPROTOOPT, "Bad protocol option"), + E(WSAEPROTONOSUPPORT, "Protocol not supported"), + E(WSAESOCKTNOSUPPORT, "Socket type not supported"), + /* What's the difference between NOTSUPP and NOSUPPORT? :) */ + E(WSAEOPNOTSUPP, "Operation not supported"), + E(WSAEPFNOSUPPORT, "Protocol family not supported"), + E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"), + E(WSAEADDRINUSE, "Address already in use"), + E(WSAEADDRNOTAVAIL, "Cannot assign requested address"), + E(WSAENETDOWN, "Network is down"), + E(WSAENETUNREACH, "Network is unreachable"), + E(WSAENETRESET, "Network dropped connection on reset"), + E(WSAECONNABORTED, "Software caused connection abort"), + E(WSAECONNRESET, "Connection reset by peer"), + E(WSAENOBUFS, "No buffer space available"), + E(WSAEISCONN, "Socket is already connected"), + E(WSAENOTCONN, "Socket is not connected"), + E(WSAESHUTDOWN, "Cannot send after socket shutdown"), + E(WSAETIMEDOUT, "Connection timed out"), + E(WSAECONNREFUSED, "Connection refused"), + E(WSAEHOSTDOWN, "Host is down"), + E(WSAEHOSTUNREACH, "No route to host"), + E(WSAEPROCLIM, "Too many processes"), + + /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */ + E(WSASYSNOTREADY, "Network subsystem is unavailable"), + E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"), + E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"), + E(WSAEDISCON, "Graceful shutdown now in progress"), +#ifdef WSATYPE_NOT_FOUND + E(WSATYPE_NOT_FOUND, "Class type not found"), +#endif + E(WSAHOST_NOT_FOUND, "Host not found"), + E(WSATRY_AGAIN, "Nonauthoritative host not found"), + E(WSANO_RECOVERY, "This is a nonrecoverable error"), + E(WSANO_DATA, "Valid name, no data record of requested type)"), + + /* There are some more error codes whose numeric values are marked + * OS dependent. They start with WSA_, apparently for the same + * reason that practitioners of some craft traditions deliberately + * introduce imperfections into their baskets and rugs "to allow the + * evil spirits to escape." If we catch them, then our binaries + * might not report consistent results across versions of Windows. + * Thus, I'm going to let them all fall through. + */ + { -1, NULL }, +}; +#undef E +/** Equivalent to strerror, but for windows socket errors. */ +const char * +evutil_socket_error_to_string(int errcode) +{ + /* XXXX Is there really no built-in function to do this? */ + int i; + for (i=0; windows_socket_errors[i].code >= 0; ++i) { + if (errcode == windows_socket_errors[i].code) + return windows_socket_errors[i].msg; + } + return strerror(errcode); +} +#endif + +int +evutil_snprintf(char *buf, size_t buflen, const char *format, ...) +{ + int r; + va_list ap; + va_start(ap, format); + r = evutil_vsnprintf(buf, buflen, format, ap); + va_end(ap); + return r; +} + +int +evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) +{ + int r; + if (!buflen) + return 0; +#ifdef _MSC_VER + r = _vsnprintf(buf, buflen, format, ap); + if (r < 0) + r = _vscprintf(format, ap); +#elif defined(sgi) + /* Make sure we always use the correct vsnprintf on IRIX */ + extern int _xpg5_vsnprintf(char * __restrict, + __SGI_LIBC_NAMESPACE_QUALIFIER size_t, + const char * __restrict, /* va_list */ char *); + + r = _xpg5_vsnprintf(buf, buflen, format, ap); +#else + r = vsnprintf(buf, buflen, format, ap); +#endif + buf[buflen-1] = '\0'; + return r; +} + +#define USE_INTERNAL_NTOP +#define USE_INTERNAL_PTON + +const char * +evutil_inet_ntop(int af, const void *src, char *dst, size_t len) +{ +#if defined(_EVENT_HAVE_INET_NTOP) && !defined(USE_INTERNAL_NTOP) + return inet_ntop(af, src, dst, len); +#else + if (af == AF_INET) { + const struct in_addr *in = src; + const ev_uint32_t a = ntohl(in->s_addr); + int r; + r = evutil_snprintf(dst, len, "%d.%d.%d.%d", + (int)(ev_uint8_t)((a>>24)&0xff), + (int)(ev_uint8_t)((a>>16)&0xff), + (int)(ev_uint8_t)((a>>8 )&0xff), + (int)(ev_uint8_t)((a )&0xff)); + if (r<0||(size_t)r>=len) + return NULL; + else + return dst; +#ifdef AF_INET6 + } else if (af == AF_INET6) { + const struct in6_addr *addr = src; + char buf[64], *cp; + int longestGapLen = 0, longestGapPos = -1, i, + curGapPos = -1, curGapLen = 0; + ev_uint16_t words[8]; + for (i = 0; i < 8; ++i) { + words[i] = + (((ev_uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1]; + } + if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && + words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) || + (words[5] == 0xffff))) { + /* This is an IPv4 address. */ + if (words[5] == 0) { + evutil_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d", + addr->s6_addr[12], addr->s6_addr[13], + addr->s6_addr[14], addr->s6_addr[15]); + } else { + evutil_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5], + addr->s6_addr[12], addr->s6_addr[13], + addr->s6_addr[14], addr->s6_addr[15]); + } + if (strlen(buf) > len) + return NULL; + strlcpy(dst, buf, len); + return dst; + } + i = 0; + while (i < 8) { + if (words[i] == 0) { + curGapPos = i++; + curGapLen = 1; + while (i<8 && words[i] == 0) { + ++i; ++curGapLen; + } + if (curGapLen > longestGapLen) { + longestGapPos = curGapPos; + longestGapLen = curGapLen; + } + } else { + ++i; + } + } + if (longestGapLen<=1) + longestGapPos = -1; + + cp = buf; + for (i = 0; i < 8; ++i) { + if (words[i] == 0 && longestGapPos == i) { + if (i == 0) + *cp++ = ':'; + *cp++ = ':'; + while (i < 8 && words[i] == 0) + ++i; + --i; /* to compensate for loop increment. */ + } else { + evutil_snprintf(cp, + sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]); + cp += strlen(cp); + if (i != 7) + *cp++ = ':'; + } + } + *cp = '\0'; + if (strlen(buf) > len) + return NULL; + strlcpy(dst, buf, len); + return dst; +#endif + } else { + return NULL; + } +#endif +} + +int +evutil_inet_pton(int af, const char *src, void *dst) +{ +#if defined(_EVENT_HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON) + return inet_pton(af, src, dst); +#else + if (af == AF_INET) { + int a,b,c,d; + char more; + struct in_addr *addr = dst; + if (sscanf(src, "%d.%d.%d.%d%c", &a,&b,&c,&d,&more) != 4) + return 0; + if (a < 0 || a > 255) return 0; + if (b < 0 || b > 255) return 0; + if (c < 0 || c > 255) return 0; + if (d < 0 || d > 255) return 0; + addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d); + return 1; +#ifdef AF_INET6 + } else if (af == AF_INET6) { + struct in6_addr *out = dst; + ev_uint16_t words[8]; + int gapPos = -1, i, setWords=0; + const char *dot = strchr(src, '.'); + const char *eow; /* end of words. */ + if (dot == src) + return 0; + else if (!dot) + eow = src+strlen(src); + else { + int byte1,byte2,byte3,byte4; + char more; + for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT(*eow); --eow) + ; + ++eow; + + /* We use "scanf" because some platform inet_aton()s are too lax + * about IPv4 addresses of the form "1.2.3" */ + if (sscanf(eow, "%d.%d.%d.%d%c", + &byte1,&byte2,&byte3,&byte4,&more) != 4) + return 0; + + if (byte1 > 255 || byte1 < 0 || + byte2 > 255 || byte2 < 0 || + byte3 > 255 || byte3 < 0 || + byte4 > 255 || byte4 < 0) + return 0; + + words[6] = (byte1<<8) | byte2; + words[7] = (byte3<<8) | byte4; + setWords += 2; + } + + i = 0; + while (src < eow) { + if (i > 7) + return 0; + if (EVUTIL_ISXDIGIT(*src)) { + char *next; + long r = strtol(src, &next, 16); + if (next > 4+src) + return 0; + if (next == src) + return 0; + if (r<0 || r>65536) + return 0; + + words[i++] = (ev_uint16_t)r; + setWords++; + src = next; + if (*src != ':' && src != eow) + return 0; + ++src; + } else if (*src == ':' && i > 0 && gapPos==-1) { + gapPos = i; + ++src; + } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) { + gapPos = i; + src += 2; + } else { + return 0; + } + } + + if (setWords > 8 || + (setWords == 8 && gapPos != -1) || + (setWords < 8 && gapPos == -1)) + return 0; + + if (gapPos >= 0) { + int nToMove = setWords - (dot ? 2 : 0) - gapPos; + int gapLen = 8 - setWords; + /* assert(nToMove >= 0); */ + if (nToMove < 0) + return -1; /* should be impossible */ + memmove(&words[gapPos+gapLen], &words[gapPos], + sizeof(ev_uint16_t)*nToMove); + memset(&words[gapPos], 0, sizeof(ev_uint16_t)*gapLen); + } + for (i = 0; i < 8; ++i) { + out->s6_addr[2*i ] = words[i] >> 8; + out->s6_addr[2*i+1] = words[i] & 0xff; + } + + return 1; +#endif + } else { + return -1; + } +#endif +} + +int +evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen) +{ + int port; + char buf[128]; + const char *cp, *addr_part, *port_part; + int is_ipv6; + /* recognized formats are: + * [ipv6]:port + * ipv6 + * [ipv6] + * ipv4:port + * ipv4 + */ + + cp = strchr(ip_as_string, ':'); + if (*ip_as_string == '[') { + int len; + if (!(cp = strchr(ip_as_string, ']'))) { + return -1; + } + len = (int) ( cp-(ip_as_string + 1) ); + if (len > (int)sizeof(buf)-1) { + return -1; + } + memcpy(buf, ip_as_string+1, len); + buf[len] = '\0'; + addr_part = buf; + if (cp[1] == ':') + port_part = cp+2; + else + port_part = NULL; + is_ipv6 = 1; + } else if (cp && strchr(cp+1, ':')) { + is_ipv6 = 1; + addr_part = ip_as_string; + port_part = NULL; + } else if (cp) { + is_ipv6 = 0; + if (cp - ip_as_string > (int)sizeof(buf)-1) { + return -1; + } + memcpy(buf, ip_as_string, cp-ip_as_string); + buf[cp-ip_as_string] = '\0'; + addr_part = buf; + port_part = cp+1; + } else { + addr_part = ip_as_string; + port_part = NULL; + is_ipv6 = 0; + } + + if (port_part == NULL) { + port = 0; + } else { + port = atoi(port_part); + if (port <= 0 || port > 65535) { + return -1; + } + } + + if (!addr_part) + return -1; /* Should be impossible. */ +#ifdef AF_INET6 + if (is_ipv6) + { + struct sockaddr_in6 sin6; + memset(&sin6, 0, sizeof(sin6)); +#ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN + sin6.sin6_len = sizeof(sin6); +#endif + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(port); + if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr)) + return -1; + if ((int)sizeof(sin6) > *outlen) + return -1; + memset(out, 0, *outlen); + memcpy(out, &sin6, sizeof(sin6)); + *outlen = sizeof(sin6); + return 0; + } + else +#endif + { + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); +#ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + sin.sin_len = sizeof(sin); +#endif + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + if (1 != evutil_inet_pton(AF_INET, addr_part, &sin.sin_addr)) + return -1; + if ((int)sizeof(sin) > *outlen) + return -1; + memset(out, 0, *outlen); + memcpy(out, &sin, sizeof(sin)); + *outlen = sizeof(sin); + return 0; + } +} + +const char * +evutil_format_sockaddr_port(const struct sockaddr *sa, char *out, size_t outlen) +{ + char b[128]; + const char *res=NULL; + int port; + if (sa->sa_family == AF_INET) { + const struct sockaddr_in *sin = (const struct sockaddr_in*)sa; + res = evutil_inet_ntop(AF_INET, &sin->sin_addr,b,sizeof(b)); + port = ntohs(sin->sin_port); + if (res) { + evutil_snprintf(out, outlen, "%s:%d", b, port); + return out; + } + } else if (sa->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)sa; + res = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr,b,sizeof(b)); + port = ntohs(sin6->sin6_port); + if (res) { + evutil_snprintf(out, outlen, "[%s]:%d", b, port); + return out; + } + } + + evutil_snprintf(out, outlen, "", + (int)sa->sa_family); + return out; +} + +int +evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, + int include_port) +{ + int r; + if (0 != (r = (sa1->sa_family - sa2->sa_family))) + return r; + + if (sa1->sa_family == AF_INET) { + const struct sockaddr_in *sin1, *sin2; + sin1 = (const struct sockaddr_in *)sa1; + sin2 = (const struct sockaddr_in *)sa2; + if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr) + return -1; + else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr) + return 1; + else if (include_port && + (r = ((int)sin1->sin_port - (int)sin2->sin_port))) + return r; + else + return 0; + } +#ifdef AF_INET6 + else if (sa1->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin1, *sin2; + sin1 = (const struct sockaddr_in6 *)sa1; + sin2 = (const struct sockaddr_in6 *)sa2; + if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))) + return r; + else if (include_port && + (r = ((int)sin1->sin6_port - (int)sin2->sin6_port))) + return r; + else + return 0; + } +#endif + return 1; +} + +/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table + * has 256 bits to look up whether a character is in some set or not. This + * fails on non-ASCII platforms, but so does every other place where we + * take a char and write it onto the network. + **/ +static const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] = + { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; +static const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] = + { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; +static const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }; +static const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] = + { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }; +static const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }; +static const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] = + { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }; +static const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }; +static const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }; +/* Upper-casing and lowercasing tables to map characters to upper/lowercase + * equivalents. */ +static const unsigned char EVUTIL_TOUPPER_TABLE[256] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, +}; +static const unsigned char EVUTIL_TOLOWER_TABLE[256] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, +}; + +#define IMPL_CTYPE_FN(name) \ + int EVUTIL_##name(char c) { \ + ev_uint8_t u = c; \ + return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ + } +IMPL_CTYPE_FN(ISALPHA) +IMPL_CTYPE_FN(ISALNUM) +IMPL_CTYPE_FN(ISSPACE) +IMPL_CTYPE_FN(ISDIGIT) +IMPL_CTYPE_FN(ISXDIGIT) +IMPL_CTYPE_FN(ISPRINT) +IMPL_CTYPE_FN(ISLOWER) +IMPL_CTYPE_FN(ISUPPER) + +char EVUTIL_TOLOWER(char c) +{ + return ((char)EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]); +} +char EVUTIL_TOUPPER(char c) +{ + return ((char)EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]); +} +int +evutil_ascii_strcasecmp(const char *s1, const char *s2) +{ + char c1, c2; + while (1) { + c1 = EVUTIL_TOLOWER(*s1++); + c2 = EVUTIL_TOLOWER(*s2++); + if (c1 < c2) + return -1; + else if (c1 > c2) + return 1; + else if (c1 == 0) + return 0; + } +} +int evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n) +{ + char c1, c2; + while (n--) { + c1 = EVUTIL_TOLOWER(*s1++); + c2 = EVUTIL_TOLOWER(*s2++); + if (c1 < c2) + return -1; + else if (c1 > c2) + return 1; + else if (c1 == 0) + return 0; + } + return 0; +} + +static int +evutil_issetugid(void) +{ +#ifdef _EVENT_HAVE_ISSETUGID + return issetugid(); +#else + +#ifdef _EVENT_HAVE_GETEUID + if (getuid() != geteuid()) + return 1; +#endif +#ifdef _EVENT_HAVE_GETEGID + if (getgid() != getegid()) + return 1; +#endif + return 0; +#endif +} + +const char * +evutil_getenv(const char *varname) +{ + if (evutil_issetugid()) + return NULL; + + return getenv(varname); +} + +long +_evutil_weakrand(void) +{ +#ifdef WIN32 + return rand(); +#else + return random(); +#endif +} + +int +evutil_sockaddr_is_loopback(const struct sockaddr *addr) +{ + static const char LOOPBACK_S6[16] = + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"; + if (addr->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)addr; + return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; + } else if (addr->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; + return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); + } + return 0; +} + +#define MAX_SECONDS_IN_MSEC_LONG \ + (((LONG_MAX) - 999) / 1000) + +long +evutil_tv_to_msec(const struct timeval *tv) +{ + if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG) + return -1; + + return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); +} + +int +evutil_hex_char_to_int(char c) +{ + switch(c) + { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'A': case 'a': return 10; + case 'B': case 'b': return 11; + case 'C': case 'c': return 12; + case 'D': case 'd': return 13; + case 'E': case 'e': return 14; + case 'F': case 'f': return 15; + } + return -1; +} + +#ifdef WIN32 +HANDLE +evutil_load_windows_system_library(const TCHAR *library_name) +{ + TCHAR path[MAX_PATH]; + unsigned n; + n = GetSystemDirectory(path, MAX_PATH); + if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH) + return 0; + _tcscat(path, TEXT("\\")); + _tcscat(path, library_name); + return LoadLibrary(path); +} +#endif + diff --git a/libevent/evutil.h b/libevent/evutil.h new file mode 100644 index 0000000..02bca89 --- /dev/null +++ b/libevent/evutil.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVUTIL_H_ +#define _EVUTIL_H_ + +/** @file evutil.h + + Utility and compatibility functions for Libevent. + + The header is deprecated in Libevent 2.0 and later; please + use instead. +*/ + +#include + +#endif /* _EVUTIL_H_ */ diff --git a/libevent/evutil_rand.c b/libevent/evutil_rand.c new file mode 100644 index 0000000..3cc163d --- /dev/null +++ b/libevent/evutil_rand.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +/* This file has our secure PRNG code. On platforms that have arc4random(), + * we just use that. Otherwise, we include arc4random.c as a bunch of static + * functions, and wrap it lightly. We don't expose the arc4random*() APIs + * because A) they aren't in our namespace, and B) it's not nice to name your + * APIs after their implementations. We keep them in a separate file + * so that other people can rip it out and use it for whatever. + */ + +#include "event2/event-config.h" + +#include + +#include "util-internal.h" +#include "evthread-internal.h" + +#ifdef _EVENT_HAVE_ARC4RANDOM +#include +#include +int +evutil_secure_rng_init(void) +{ + /* call arc4random() now to force it to self-initialize */ + (void) arc4random(); + return 0; +} +int +evutil_secure_rng_global_setup_locks_(const int enable_locks) +{ + return 0; +} + +static void +ev_arc4random_buf(void *buf, size_t n) +{ +#ifdef _EVENT_HAVE_ARC4RANDOM_BUF + return arc4random_buf(buf, n); +#else + unsigned char *b = buf; + /* Make sure that we start out with b at a 4-byte alignment; plenty + * of CPUs care about this for 32-bit access. */ + if (n >= 4 && ((ev_uintptr_t)b) & 3) { + ev_uint32_t u = arc4random(); + int n_bytes = 4 - (((ev_uintptr_t)b) & 3); + memcpy(b, &u, n_bytes); + b += n_bytes; + n -= n_bytes; + } + while (n >= 4) { + *(ev_uint32_t*)b = arc4random(); + b += 4; + n -= 4; + } + if (n) { + ev_uint32_t u = arc4random(); + memcpy(b, &u, n); + } +#endif +} + +#else /* !_EVENT_HAVE_ARC4RANDOM { */ + +#ifdef _EVENT_ssize_t +#define ssize_t _EVENT_SSIZE_t +#endif +#define ARC4RANDOM_EXPORT static +#define _ARC4_LOCK() EVLOCK_LOCK(arc4rand_lock, 0) +#define _ARC4_UNLOCK() EVLOCK_UNLOCK(arc4rand_lock, 0) +#ifndef _EVENT_DISABLE_THREAD_SUPPORT +static void *arc4rand_lock; +#endif + +#define ARC4RANDOM_UINT32 ev_uint32_t +#define ARC4RANDOM_NOSTIR +#define ARC4RANDOM_NORANDOM +#define ARC4RANDOM_NOUNIFORM + +#include "./arc4random.c" + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT +int +evutil_secure_rng_global_setup_locks_(const int enable_locks) +{ + EVTHREAD_SETUP_GLOBAL_LOCK(arc4rand_lock, 0); + return 0; +} +#endif + +int +evutil_secure_rng_init(void) +{ + int val; + + _ARC4_LOCK(); + if (!arc4_seeded_ok) + arc4_stir(); + val = arc4_seeded_ok ? 0 : -1; + _ARC4_UNLOCK(); + return val; +} + +static void +ev_arc4random_buf(void *buf, size_t n) +{ + arc4random_buf(buf, n); +} + +#endif /* } !_EVENT_HAVE_ARC4RANDOM */ + +void +evutil_secure_rng_get_bytes(void *buf, size_t n) +{ + ev_arc4random_buf(buf, n); +} + +void +evutil_secure_rng_add_bytes(const char *buf, size_t n) +{ + arc4random_addrandom((unsigned char*)buf, + n>(size_t)INT_MAX ? INT_MAX : (int)n); +} + diff --git a/libevent/ht-internal.h b/libevent/ht-internal.h new file mode 100644 index 0000000..4673825 --- /dev/null +++ b/libevent/ht-internal.h @@ -0,0 +1,484 @@ +/* Based on work Copyright 2002 Christopher Clark */ +/* Copyright 2005-2012 Nick Mathewson */ +/* Copyright 2009-2012 Niels Provos and Nick Mathewson */ +/* See license at end. */ + +/* Based on ideas by Christopher Clark and interfaces from Niels Provos. */ + +#ifndef _EVENT_HT_H +#define _EVENT_HT_H + +#define HT_HEAD(name, type) \ + struct name { \ + /* The hash table itself. */ \ + struct type **hth_table; \ + /* How long is the hash table? */ \ + unsigned hth_table_length; \ + /* How many elements does the table contain? */ \ + unsigned hth_n_entries; \ + /* How many elements will we allow in the table before resizing it? */ \ + unsigned hth_load_limit; \ + /* Position of hth_table_length in the primes table. */ \ + int hth_prime_idx; \ + } + +#define HT_INITIALIZER() \ + { NULL, 0, 0, 0, -1 } + +#ifdef HT_CACHE_HASH_VALUES +#define HT_ENTRY(type) \ + struct { \ + struct type *hte_next; \ + unsigned hte_hash; \ + } +#else +#define HT_ENTRY(type) \ + struct { \ + struct type *hte_next; \ + } +#endif + +#define HT_EMPTY(head) \ + ((head)->hth_n_entries == 0) + +/* How many elements in 'head'? */ +#define HT_SIZE(head) \ + ((head)->hth_n_entries) + +#define HT_FIND(name, head, elm) name##_HT_FIND((head), (elm)) +#define HT_INSERT(name, head, elm) name##_HT_INSERT((head), (elm)) +#define HT_REPLACE(name, head, elm) name##_HT_REPLACE((head), (elm)) +#define HT_REMOVE(name, head, elm) name##_HT_REMOVE((head), (elm)) +#define HT_START(name, head) name##_HT_START(head) +#define HT_NEXT(name, head, elm) name##_HT_NEXT((head), (elm)) +#define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm)) +#define HT_CLEAR(name, head) name##_HT_CLEAR(head) +#define HT_INIT(name, head) name##_HT_INIT(head) +/* Helper: */ +static inline unsigned +ht_improve_hash(unsigned h) +{ + /* Aim to protect against poor hash functions by adding logic here + * - logic taken from java 1.4 hashtable source */ + h += ~(h << 9); + h ^= ((h >> 14) | (h << 18)); /* >>> */ + h += (h << 4); + h ^= ((h >> 10) | (h << 22)); /* >>> */ + return h; +} + +#if 0 +/** Basic string hash function, from Java standard String.hashCode(). */ +static inline unsigned +ht_string_hash(const char *s) +{ + unsigned h = 0; + int m = 1; + while (*s) { + h += ((signed char)*s++)*m; + m = (m<<5)-1; /* m *= 31 */ + } + return h; +} +#endif + +/** Basic string hash function, from Python's str.__hash__() */ +static inline unsigned +ht_string_hash(const char *s) +{ + unsigned h; + const unsigned char *cp = (const unsigned char *)s; + h = *cp << 7; + while (*cp) { + h = (1000003*h) ^ *cp++; + } + /* This conversion truncates the length of the string, but that's ok. */ + h ^= (unsigned)(cp-(const unsigned char*)s); + return h; +} + +#ifdef HT_CACHE_HASH_VALUES +#define _HT_SET_HASH(elm, field, hashfn) \ + do { (elm)->field.hte_hash = hashfn(elm); } while (0) +#define _HT_SET_HASHVAL(elm, field, val) \ + do { (elm)->field.hte_hash = (val); } while (0) +#define _HT_ELT_HASH(elm, field, hashfn) \ + ((elm)->field.hte_hash) +#else +#define _HT_SET_HASH(elm, field, hashfn) \ + ((void)0) +#define _HT_ELT_HASH(elm, field, hashfn) \ + (hashfn(elm)) +#define _HT_SET_HASHVAL(elm, field, val) \ + ((void)0) +#endif + +/* Helper: alias for the bucket containing 'elm'. */ +#define _HT_BUCKET(head, field, elm, hashfn) \ + ((head)->hth_table[_HT_ELT_HASH(elm,field,hashfn) % head->hth_table_length]) + +#define HT_FOREACH(x, name, head) \ + for ((x) = HT_START(name, head); \ + (x) != NULL; \ + (x) = HT_NEXT(name, head, x)) + +#define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \ + int name##_HT_GROW(struct name *ht, unsigned min_capacity); \ + void name##_HT_CLEAR(struct name *ht); \ + int _##name##_HT_REP_IS_BAD(const struct name *ht); \ + static inline void \ + name##_HT_INIT(struct name *head) { \ + head->hth_table_length = 0; \ + head->hth_table = NULL; \ + head->hth_n_entries = 0; \ + head->hth_load_limit = 0; \ + head->hth_prime_idx = -1; \ + } \ + /* Helper: returns a pointer to the right location in the table \ + * 'head' to find or insert the element 'elm'. */ \ + static inline struct type ** \ + _##name##_HT_FIND_P(struct name *head, struct type *elm) \ + { \ + struct type **p; \ + if (!head->hth_table) \ + return NULL; \ + p = &_HT_BUCKET(head, field, elm, hashfn); \ + while (*p) { \ + if (eqfn(*p, elm)) \ + return p; \ + p = &(*p)->field.hte_next; \ + } \ + return p; \ + } \ + /* Return a pointer to the element in the table 'head' matching 'elm', \ + * or NULL if no such element exists */ \ + static inline struct type * \ + name##_HT_FIND(const struct name *head, struct type *elm) \ + { \ + struct type **p; \ + struct name *h = (struct name *) head; \ + _HT_SET_HASH(elm, field, hashfn); \ + p = _##name##_HT_FIND_P(h, elm); \ + return p ? *p : NULL; \ + } \ + /* Insert the element 'elm' into the table 'head'. Do not call this \ + * function if the table might already contain a matching element. */ \ + static inline void \ + name##_HT_INSERT(struct name *head, struct type *elm) \ + { \ + struct type **p; \ + if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \ + name##_HT_GROW(head, head->hth_n_entries+1); \ + ++head->hth_n_entries; \ + _HT_SET_HASH(elm, field, hashfn); \ + p = &_HT_BUCKET(head, field, elm, hashfn); \ + elm->field.hte_next = *p; \ + *p = elm; \ + } \ + /* Insert the element 'elm' into the table 'head'. If there already \ + * a matching element in the table, replace that element and return \ + * it. */ \ + static inline struct type * \ + name##_HT_REPLACE(struct name *head, struct type *elm) \ + { \ + struct type **p, *r; \ + if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \ + name##_HT_GROW(head, head->hth_n_entries+1); \ + _HT_SET_HASH(elm, field, hashfn); \ + p = _##name##_HT_FIND_P(head, elm); \ + r = *p; \ + *p = elm; \ + if (r && (r!=elm)) { \ + elm->field.hte_next = r->field.hte_next; \ + r->field.hte_next = NULL; \ + return r; \ + } else { \ + ++head->hth_n_entries; \ + return NULL; \ + } \ + } \ + /* Remove any element matching 'elm' from the table 'head'. If such \ + * an element is found, return it; otherwise return NULL. */ \ + static inline struct type * \ + name##_HT_REMOVE(struct name *head, struct type *elm) \ + { \ + struct type **p, *r; \ + _HT_SET_HASH(elm, field, hashfn); \ + p = _##name##_HT_FIND_P(head,elm); \ + if (!p || !*p) \ + return NULL; \ + r = *p; \ + *p = r->field.hte_next; \ + r->field.hte_next = NULL; \ + --head->hth_n_entries; \ + return r; \ + } \ + /* Invoke the function 'fn' on every element of the table 'head', \ + * using 'data' as its second argument. If the function returns \ + * nonzero, remove the most recently examined element before invoking \ + * the function again. */ \ + static inline void \ + name##_HT_FOREACH_FN(struct name *head, \ + int (*fn)(struct type *, void *), \ + void *data) \ + { \ + unsigned idx; \ + struct type **p, **nextp, *next; \ + if (!head->hth_table) \ + return; \ + for (idx=0; idx < head->hth_table_length; ++idx) { \ + p = &head->hth_table[idx]; \ + while (*p) { \ + nextp = &(*p)->field.hte_next; \ + next = *nextp; \ + if (fn(*p, data)) { \ + --head->hth_n_entries; \ + *p = next; \ + } else { \ + p = nextp; \ + } \ + } \ + } \ + } \ + /* Return a pointer to the first element in the table 'head', under \ + * an arbitrary order. This order is stable under remove operations, \ + * but not under others. If the table is empty, return NULL. */ \ + static inline struct type ** \ + name##_HT_START(struct name *head) \ + { \ + unsigned b = 0; \ + while (b < head->hth_table_length) { \ + if (head->hth_table[b]) \ + return &head->hth_table[b]; \ + ++b; \ + } \ + return NULL; \ + } \ + /* Return the next element in 'head' after 'elm', under the arbitrary \ + * order used by HT_START. If there are no more elements, return \ + * NULL. If 'elm' is to be removed from the table, you must call \ + * this function for the next value before you remove it. \ + */ \ + static inline struct type ** \ + name##_HT_NEXT(struct name *head, struct type **elm) \ + { \ + if ((*elm)->field.hte_next) { \ + return &(*elm)->field.hte_next; \ + } else { \ + unsigned b = (_HT_ELT_HASH(*elm, field, hashfn) % head->hth_table_length)+1; \ + while (b < head->hth_table_length) { \ + if (head->hth_table[b]) \ + return &head->hth_table[b]; \ + ++b; \ + } \ + return NULL; \ + } \ + } \ + static inline struct type ** \ + name##_HT_NEXT_RMV(struct name *head, struct type **elm) \ + { \ + unsigned h = _HT_ELT_HASH(*elm, field, hashfn); \ + *elm = (*elm)->field.hte_next; \ + --head->hth_n_entries; \ + if (*elm) { \ + return elm; \ + } else { \ + unsigned b = (h % head->hth_table_length)+1; \ + while (b < head->hth_table_length) { \ + if (head->hth_table[b]) \ + return &head->hth_table[b]; \ + ++b; \ + } \ + return NULL; \ + } \ + } + +#define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \ + reallocfn, freefn) \ + static unsigned name##_PRIMES[] = { \ + 53, 97, 193, 389, \ + 769, 1543, 3079, 6151, \ + 12289, 24593, 49157, 98317, \ + 196613, 393241, 786433, 1572869, \ + 3145739, 6291469, 12582917, 25165843, \ + 50331653, 100663319, 201326611, 402653189, \ + 805306457, 1610612741 \ + }; \ + static unsigned name##_N_PRIMES = \ + (unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0])); \ + /* Expand the internal table of 'head' until it is large enough to \ + * hold 'size' elements. Return 0 on success, -1 on allocation \ + * failure. */ \ + int \ + name##_HT_GROW(struct name *head, unsigned size) \ + { \ + unsigned new_len, new_load_limit; \ + int prime_idx; \ + struct type **new_table; \ + if (head->hth_prime_idx == (int)name##_N_PRIMES - 1) \ + return 0; \ + if (head->hth_load_limit > size) \ + return 0; \ + prime_idx = head->hth_prime_idx; \ + do { \ + new_len = name##_PRIMES[++prime_idx]; \ + new_load_limit = (unsigned)(load*new_len); \ + } while (new_load_limit <= size && \ + prime_idx < (int)name##_N_PRIMES); \ + if ((new_table = mallocfn(new_len*sizeof(struct type*)))) { \ + unsigned b; \ + memset(new_table, 0, new_len*sizeof(struct type*)); \ + for (b = 0; b < head->hth_table_length; ++b) { \ + struct type *elm, *next; \ + unsigned b2; \ + elm = head->hth_table[b]; \ + while (elm) { \ + next = elm->field.hte_next; \ + b2 = _HT_ELT_HASH(elm, field, hashfn) % new_len; \ + elm->field.hte_next = new_table[b2]; \ + new_table[b2] = elm; \ + elm = next; \ + } \ + } \ + if (head->hth_table) \ + freefn(head->hth_table); \ + head->hth_table = new_table; \ + } else { \ + unsigned b, b2; \ + new_table = reallocfn(head->hth_table, new_len*sizeof(struct type*)); \ + if (!new_table) return -1; \ + memset(new_table + head->hth_table_length, 0, \ + (new_len - head->hth_table_length)*sizeof(struct type*)); \ + for (b=0; b < head->hth_table_length; ++b) { \ + struct type *e, **pE; \ + for (pE = &new_table[b], e = *pE; e != NULL; e = *pE) { \ + b2 = _HT_ELT_HASH(e, field, hashfn) % new_len; \ + if (b2 == b) { \ + pE = &e->field.hte_next; \ + } else { \ + *pE = e->field.hte_next; \ + e->field.hte_next = new_table[b2]; \ + new_table[b2] = e; \ + } \ + } \ + } \ + head->hth_table = new_table; \ + } \ + head->hth_table_length = new_len; \ + head->hth_prime_idx = prime_idx; \ + head->hth_load_limit = new_load_limit; \ + return 0; \ + } \ + /* Free all storage held by 'head'. Does not free 'head' itself, or \ + * individual elements. */ \ + void \ + name##_HT_CLEAR(struct name *head) \ + { \ + if (head->hth_table) \ + freefn(head->hth_table); \ + head->hth_table_length = 0; \ + name##_HT_INIT(head); \ + } \ + /* Debugging helper: return false iff the representation of 'head' is \ + * internally consistent. */ \ + int \ + _##name##_HT_REP_IS_BAD(const struct name *head) \ + { \ + unsigned n, i; \ + struct type *elm; \ + if (!head->hth_table_length) { \ + if (!head->hth_table && !head->hth_n_entries && \ + !head->hth_load_limit && head->hth_prime_idx == -1) \ + return 0; \ + else \ + return 1; \ + } \ + if (!head->hth_table || head->hth_prime_idx < 0 || \ + !head->hth_load_limit) \ + return 2; \ + if (head->hth_n_entries > head->hth_load_limit) \ + return 3; \ + if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx]) \ + return 4; \ + if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \ + return 5; \ + for (n = i = 0; i < head->hth_table_length; ++i) { \ + for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) { \ + if (_HT_ELT_HASH(elm, field, hashfn) != hashfn(elm)) \ + return 1000 + i; \ + if ((_HT_ELT_HASH(elm, field, hashfn) % head->hth_table_length) != i) \ + return 10000 + i; \ + ++n; \ + } \ + } \ + if (n != head->hth_n_entries) \ + return 6; \ + return 0; \ + } + +/** Implements an over-optimized "find and insert if absent" block; + * not meant for direct usage by typical code, or usage outside the critical + * path.*/ +#define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \ + { \ + struct name *_##var##_head = head; \ + struct eltype **var; \ + if (!_##var##_head->hth_table || \ + _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \ + name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \ + _HT_SET_HASH((elm), field, hashfn); \ + var = _##name##_HT_FIND_P(_##var##_head, (elm)); \ + if (*var) { \ + y; \ + } else { \ + n; \ + } \ + } +#define _HT_FOI_INSERT(field, head, elm, newent, var) \ + { \ + _HT_SET_HASHVAL(newent, field, (elm)->field.hte_hash); \ + newent->field.hte_next = NULL; \ + *var = newent; \ + ++((head)->hth_n_entries); \ + } + +/* + * Copyright 2005, Nick Mathewson. Implementation logic is adapted from code + * by Cristopher Clark, retrofit to allow drop-in memory management, and to + * use the same interface as Niels Provos's tree.h. This is probably still + * a derived work, so the original license below still applies. + * + * Copyright (c) 2002, Christopher Clark + * 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 of the original author; nor the names of any 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. +*/ + +#endif + diff --git a/libevent/http-internal.h b/libevent/http-internal.h new file mode 100644 index 0000000..5f66673 --- /dev/null +++ b/libevent/http-internal.h @@ -0,0 +1,195 @@ +/* + * Copyright 2001-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * This header file contains definitions for dealing with HTTP requests + * that are internal to libevent. As user of the library, you should not + * need to know about these. + */ + +#ifndef _HTTP_INTERNAL_H_ +#define _HTTP_INTERNAL_H_ + +#include "event2/event_struct.h" +#include "util-internal.h" +#include "defer-internal.h" + +#define HTTP_CONNECT_TIMEOUT 45 +#define HTTP_WRITE_TIMEOUT 50 +#define HTTP_READ_TIMEOUT 50 + +#define HTTP_PREFIX "http://" +#define HTTP_DEFAULTPORT 80 + +enum message_read_status { + ALL_DATA_READ = 1, + MORE_DATA_EXPECTED = 0, + DATA_CORRUPTED = -1, + REQUEST_CANCELED = -2, + DATA_TOO_LONG = -3 +}; + +enum evhttp_connection_error { + EVCON_HTTP_TIMEOUT, + EVCON_HTTP_EOF, + EVCON_HTTP_INVALID_HEADER, + EVCON_HTTP_BUFFER_ERROR, + EVCON_HTTP_REQUEST_CANCEL +}; + +struct evbuffer; +struct addrinfo; +struct evhttp_request; + +/* Indicates an unknown request method. */ +#define _EVHTTP_REQ_UNKNOWN (1<<15) + +enum evhttp_connection_state { + EVCON_DISCONNECTED, /**< not currently connected not trying either*/ + EVCON_CONNECTING, /**< tries to currently connect */ + EVCON_IDLE, /**< connection is established */ + EVCON_READING_FIRSTLINE,/**< reading Request-Line (incoming conn) or + **< Status-Line (outgoing conn) */ + EVCON_READING_HEADERS, /**< reading request/response headers */ + EVCON_READING_BODY, /**< reading request/response body */ + EVCON_READING_TRAILER, /**< reading request/response chunked trailer */ + EVCON_WRITING /**< writing request/response headers/body */ +}; + +struct event_base; + +/* A client or server connection. */ +struct evhttp_connection { + /* we use this tailq only if this connection was created for an http + * server */ + TAILQ_ENTRY(evhttp_connection) next; + + evutil_socket_t fd; + struct bufferevent *bufev; + + struct event retry_ev; /* for retrying connects */ + + char *bind_address; /* address to use for binding the src */ + u_short bind_port; /* local port for binding the src */ + + char *address; /* address to connect to */ + u_short port; + + size_t max_headers_size; + ev_uint64_t max_body_size; + + int flags; +#define EVHTTP_CON_INCOMING 0x0001 /* only one request on it ever */ +#define EVHTTP_CON_OUTGOING 0x0002 /* multiple requests possible */ +#define EVHTTP_CON_CLOSEDETECT 0x0004 /* detecting if persistent close */ + + int timeout; /* timeout in seconds for events */ + int retry_cnt; /* retry count */ + int retry_max; /* maximum number of retries */ + + enum evhttp_connection_state state; + + /* for server connections, the http server they are connected with */ + struct evhttp *http_server; + + TAILQ_HEAD(evcon_requestq, evhttp_request) requests; + + void (*cb)(struct evhttp_connection *, void *); + void *cb_arg; + + void (*closecb)(struct evhttp_connection *, void *); + void *closecb_arg; + + struct deferred_cb read_more_deferred_cb; + + struct event_base *base; + struct evdns_base *dns_base; +}; + +/* A callback for an http server */ +struct evhttp_cb { + TAILQ_ENTRY(evhttp_cb) next; + + char *what; + + void (*cb)(struct evhttp_request *req, void *); + void *cbarg; +}; + +/* both the http server as well as the rpc system need to queue connections */ +TAILQ_HEAD(evconq, evhttp_connection); + +/* each bound socket is stored in one of these */ +struct evhttp_bound_socket { + TAILQ_ENTRY(evhttp_bound_socket) next; + + struct evconnlistener *listener; +}; + +/* server alias list item. */ +struct evhttp_server_alias { + TAILQ_ENTRY(evhttp_server_alias) next; + + char *alias; /* the server alias. */ +}; + +struct evhttp { + /* Next vhost, if this is a vhost. */ + TAILQ_ENTRY(evhttp) next_vhost; + + /* All listeners for this host */ + TAILQ_HEAD(boundq, evhttp_bound_socket) sockets; + + TAILQ_HEAD(httpcbq, evhttp_cb) callbacks; + + /* All live connections on this host. */ + struct evconq connections; + + TAILQ_HEAD(vhostsq, evhttp) virtualhosts; + + TAILQ_HEAD(aliasq, evhttp_server_alias) aliases; + + /* NULL if this server is not a vhost */ + char *vhost_pattern; + + int timeout; + + size_t default_max_headers_size; + ev_uint64_t default_max_body_size; + + /* Bitmask of all HTTP methods that we accept and pass to user + * callbacks. */ + ev_uint16_t allowed_methods; + + /* Fallback callback if all the other callbacks for this connection + don't match. */ + void (*gencb)(struct evhttp_request *req, void *); + void *gencbarg; + + struct event_base *base; +}; + +/* XXX most of these functions could be static. */ + +/* resets the connection; can be reused for more requests */ +void evhttp_connection_reset(struct evhttp_connection *); + +/* connects if necessary */ +int evhttp_connection_connect(struct evhttp_connection *); + +/* notifies the current request that it failed; resets connection */ +void evhttp_connection_fail(struct evhttp_connection *, + enum evhttp_connection_error error); + +enum message_read_status; + +enum message_read_status evhttp_parse_firstline(struct evhttp_request *, struct evbuffer*); +enum message_read_status evhttp_parse_headers(struct evhttp_request *, struct evbuffer*); + +void evhttp_start_read(struct evhttp_connection *); + +/* response sending HTML the data in the buffer */ +void evhttp_response_code(struct evhttp_request *, int, const char *); +void evhttp_send_page(struct evhttp_request *, struct evbuffer *); + +#endif /* _HTTP_H */ diff --git a/libevent/http.c b/libevent/http.c new file mode 100644 index 0000000..b9687df --- /dev/null +++ b/libevent/http.c @@ -0,0 +1,4515 @@ +/* + * Copyright (c) 2002-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#include "event2/event-config.h" + +#ifdef _EVENT_HAVE_SYS_PARAM_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_IOCCOM_H +#include +#endif + +#ifndef WIN32 +#include +#include +#include +#include +#else +#include +#include +#endif + +#include + +#ifdef _EVENT_HAVE_NETINET_IN_H +#include +#endif +#ifdef _EVENT_HAVE_ARPA_INET_H +#include +#endif +#ifdef _EVENT_HAVE_NETDB_H +#include +#endif + +#ifdef WIN32 +#include +#endif + +#include +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#ifdef _EVENT_HAVE_FCNTL_H +#include +#endif + +#undef timeout_pending +#undef timeout_initialized + +#include "strlcpy-internal.h" +#include "event2/http.h" +#include "event2/event.h" +#include "event2/buffer.h" +#include "event2/bufferevent.h" +#include "event2/bufferevent_compat.h" +#include "event2/http_struct.h" +#include "event2/http_compat.h" +#include "event2/util.h" +#include "event2/listener.h" +#include "log-internal.h" +#include "util-internal.h" +#include "http-internal.h" +#include "mm-internal.h" +#include "bufferevent-internal.h" + +#ifndef _EVENT_HAVE_GETNAMEINFO +#define NI_MAXSERV 32 +#define NI_MAXHOST 1025 + +#ifndef NI_NUMERICHOST +#define NI_NUMERICHOST 1 +#endif + +#ifndef NI_NUMERICSERV +#define NI_NUMERICSERV 2 +#endif + +static int +fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + + if (serv != NULL) { + char tmpserv[16]; + evutil_snprintf(tmpserv, sizeof(tmpserv), + "%d", ntohs(sin->sin_port)); + if (strlcpy(serv, tmpserv, servlen) >= servlen) + return (-1); + } + + if (host != NULL) { + if (flags & NI_NUMERICHOST) { + if (strlcpy(host, inet_ntoa(sin->sin_addr), + hostlen) >= hostlen) + return (-1); + else + return (0); + } else { + struct hostent *hp; + hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(struct in_addr), AF_INET); + if (hp == NULL) + return (-2); + + if (strlcpy(host, hp->h_name, hostlen) >= hostlen) + return (-1); + else + return (0); + } + } + return (0); +} + +#endif + +#define REQ_VERSION_BEFORE(req, major_v, minor_v) \ + ((req)->major < (major_v) || \ + ((req)->major == (major_v) && (req)->minor < (minor_v))) + +#define REQ_VERSION_ATLEAST(req, major_v, minor_v) \ + ((req)->major > (major_v) || \ + ((req)->major == (major_v) && (req)->minor >= (minor_v))) + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +extern int debug; + +static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse); +static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse); +static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **); +static int evhttp_associate_new_request_with_connection( + struct evhttp_connection *evcon); +static void evhttp_connection_start_detectclose( + struct evhttp_connection *evcon); +static void evhttp_connection_stop_detectclose( + struct evhttp_connection *evcon); +static void evhttp_request_dispatch(struct evhttp_connection* evcon); +static void evhttp_read_firstline(struct evhttp_connection *evcon, + struct evhttp_request *req); +static void evhttp_read_header(struct evhttp_connection *evcon, + struct evhttp_request *req); +static int evhttp_add_header_internal(struct evkeyvalq *headers, + const char *key, const char *value); +static const char *evhttp_response_phrase_internal(int code); +static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t); +static void evhttp_write_buffer(struct evhttp_connection *, + void (*)(struct evhttp_connection *, void *), void *); +static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *); + +/* callbacks for bufferevent */ +static void evhttp_read_cb(struct bufferevent *, void *); +static void evhttp_write_cb(struct bufferevent *, void *); +static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg); +static int evhttp_decode_uri_internal(const char *uri, size_t length, + char *ret, int decode_plus); +static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp, + const char *hostname); + +#ifndef _EVENT_HAVE_STRSEP +/* strsep replacement for platforms that lack it. Only works if + * del is one character long. */ +static char * +strsep(char **s, const char *del) +{ + char *d, *tok; + EVUTIL_ASSERT(strlen(del) == 1); + if (!s || !*s) + return NULL; + tok = *s; + d = strstr(tok, del); + if (d) { + *d = '\0'; + *s = d + 1; + } else + *s = NULL; + return tok; +} +#endif + +static size_t +html_replace(const char ch, const char **escaped) +{ + switch (ch) { + case '<': + *escaped = "<"; + return 4; + case '>': + *escaped = ">"; + return 4; + case '"': + *escaped = """; + return 6; + case '\'': + *escaped = "'"; + return 6; + case '&': + *escaped = "&"; + return 5; + default: + break; + } + + return 1; +} + +/* + * Replaces <, >, ", ' and & with <, >, ", + * ' and & correspondingly. + * + * The returned string needs to be freed by the caller. + */ + +char * +evhttp_htmlescape(const char *html) +{ + size_t i; + size_t new_size = 0, old_size = 0; + char *escaped_html, *p; + + if (html == NULL) + return (NULL); + + old_size = strlen(html); + for (i = 0; i < old_size; ++i) { + const char *replaced = NULL; + const size_t replace_size = html_replace(html[i], &replaced); + if (replace_size > EV_SIZE_MAX - new_size) { + event_warn("%s: html_replace overflow", __func__); + return (NULL); + } + new_size += replace_size; + } + + if (new_size == EV_SIZE_MAX) + return (NULL); + p = escaped_html = mm_malloc(new_size + 1); + if (escaped_html == NULL) { + event_warn("%s: malloc(%lu)", __func__, + (unsigned long)(new_size + 1)); + return (NULL); + } + for (i = 0; i < old_size; ++i) { + const char *replaced = &html[i]; + const size_t len = html_replace(html[i], &replaced); + memcpy(p, replaced, len); + p += len; + } + + *p = '\0'; + + return (escaped_html); +} + +/** Given an evhttp_cmd_type, returns a constant string containing the + * equivalent HTTP command, or NULL if the evhttp_command_type is + * unrecognized. */ +static const char * +evhttp_method(enum evhttp_cmd_type type) +{ + const char *method; + + switch (type) { + case EVHTTP_REQ_GET: + method = "GET"; + break; + case EVHTTP_REQ_POST: + method = "POST"; + break; + case EVHTTP_REQ_HEAD: + method = "HEAD"; + break; + case EVHTTP_REQ_PUT: + method = "PUT"; + break; + case EVHTTP_REQ_DELETE: + method = "DELETE"; + break; + case EVHTTP_REQ_OPTIONS: + method = "OPTIONS"; + break; + case EVHTTP_REQ_TRACE: + method = "TRACE"; + break; + case EVHTTP_REQ_CONNECT: + method = "CONNECT"; + break; + case EVHTTP_REQ_PATCH: + method = "PATCH"; + break; + default: + method = NULL; + break; + } + + return (method); +} + +/** + * Determines if a response should have a body. + * Follows the rules in RFC 2616 section 4.3. + * @return 1 if the response MUST have a body; 0 if the response MUST NOT have + * a body. + */ +static int +evhttp_response_needs_body(struct evhttp_request *req) +{ + return (req->response_code != HTTP_NOCONTENT && + req->response_code != HTTP_NOTMODIFIED && + (req->response_code < 100 || req->response_code >= 200) && + req->type != EVHTTP_REQ_HEAD); +} + +/** Helper: adds the event 'ev' with the timeout 'timeout', or with + * default_timeout if timeout is -1. + */ +static int +evhttp_add_event(struct event *ev, int timeout, int default_timeout) +{ + if (timeout != 0) { + struct timeval tv; + + evutil_timerclear(&tv); + tv.tv_sec = timeout != -1 ? timeout : default_timeout; + return event_add(ev, &tv); + } else { + return event_add(ev, NULL); + } +} + +/** Helper: called after we've added some data to an evcon's bufferevent's + * output buffer. Sets the evconn's writing-is-done callback, and puts + * the bufferevent into writing mode. + */ +static void +evhttp_write_buffer(struct evhttp_connection *evcon, + void (*cb)(struct evhttp_connection *, void *), void *arg) +{ + event_debug(("%s: preparing to write buffer\n", __func__)); + + /* Set call back */ + evcon->cb = cb; + evcon->cb_arg = arg; + + bufferevent_enable(evcon->bufev, EV_WRITE); + + /* Disable the read callback: we don't actually care about data; + * we only care about close detection. (We don't disable reading, + * since we *do* want to learn about any close events.) */ + bufferevent_setcb(evcon->bufev, + NULL, /*read*/ + evhttp_write_cb, + evhttp_error_cb, + evcon); +} + +static void +evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg) +{ + bufferevent_disable(evcon->bufev, EV_WRITE); +} + +static void +evhttp_send_continue(struct evhttp_connection *evcon, + struct evhttp_request *req) +{ + bufferevent_enable(evcon->bufev, EV_WRITE); + evbuffer_add_printf(bufferevent_get_output(evcon->bufev), + "HTTP/%d.%d 100 Continue\r\n\r\n", + req->major, req->minor); + evcon->cb = evhttp_send_continue_done; + evcon->cb_arg = NULL; + bufferevent_setcb(evcon->bufev, + evhttp_read_cb, + evhttp_write_cb, + evhttp_error_cb, + evcon); +} + +/** Helper: returns true iff evconn is in any connected state. */ +static int +evhttp_connected(struct evhttp_connection *evcon) +{ + switch (evcon->state) { + case EVCON_DISCONNECTED: + case EVCON_CONNECTING: + return (0); + case EVCON_IDLE: + case EVCON_READING_FIRSTLINE: + case EVCON_READING_HEADERS: + case EVCON_READING_BODY: + case EVCON_READING_TRAILER: + case EVCON_WRITING: + default: + return (1); + } +} + +/* Create the headers needed for an outgoing HTTP request, adds them to + * the request's header list, and writes the request line to the + * connection's output buffer. + */ +static void +evhttp_make_header_request(struct evhttp_connection *evcon, + struct evhttp_request *req) +{ + const char *method; + + evhttp_remove_header(req->output_headers, "Proxy-Connection"); + + /* Generate request line */ + method = evhttp_method(req->type); + evbuffer_add_printf(bufferevent_get_output(evcon->bufev), + "%s %s HTTP/%d.%d\r\n", + method, req->uri, req->major, req->minor); + + /* Add the content length on a post or put request if missing */ + if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) && + evhttp_find_header(req->output_headers, "Content-Length") == NULL){ + char size[22]; + evutil_snprintf(size, sizeof(size), EV_SIZE_FMT, + EV_SIZE_ARG(evbuffer_get_length(req->output_buffer))); + evhttp_add_header(req->output_headers, "Content-Length", size); + } +} + +/** Return true if the list of headers in 'headers', intepreted with respect + * to flags, means that we should send a "connection: close" when the request + * is done. */ +static int +evhttp_is_connection_close(int flags, struct evkeyvalq* headers) +{ + if (flags & EVHTTP_PROXY_REQUEST) { + /* proxy connection */ + const char *connection = evhttp_find_header(headers, "Proxy-Connection"); + return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0); + } else { + const char *connection = evhttp_find_header(headers, "Connection"); + return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0); + } +} + +/* Return true iff 'headers' contains 'Connection: keep-alive' */ +static int +evhttp_is_connection_keepalive(struct evkeyvalq* headers) +{ + const char *connection = evhttp_find_header(headers, "Connection"); + return (connection != NULL + && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0); +} + +/* Add a correct "Date" header to headers, unless it already has one. */ +static void +evhttp_maybe_add_date_header(struct evkeyvalq *headers) +{ + if (evhttp_find_header(headers, "Date") == NULL) { + char date[50]; +#ifndef WIN32 + struct tm cur; +#endif + struct tm *cur_p; + time_t t = time(NULL); +#ifdef WIN32 + cur_p = gmtime(&t); +#else + gmtime_r(&t, &cur); + cur_p = &cur; +#endif + if (strftime(date, sizeof(date), + "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) { + evhttp_add_header(headers, "Date", date); + } + } +} + +/* Add a "Content-Length" header with value 'content_length' to headers, + * unless it already has a content-length or transfer-encoding header. */ +static void +evhttp_maybe_add_content_length_header(struct evkeyvalq *headers, + size_t content_length) +{ + if (evhttp_find_header(headers, "Transfer-Encoding") == NULL && + evhttp_find_header(headers, "Content-Length") == NULL) { + char len[22]; + evutil_snprintf(len, sizeof(len), EV_SIZE_FMT, + EV_SIZE_ARG(content_length)); + evhttp_add_header(headers, "Content-Length", len); + } +} + +/* + * Create the headers needed for an HTTP reply in req->output_headers, + * and write the first HTTP response for req line to evcon. + */ +static void +evhttp_make_header_response(struct evhttp_connection *evcon, + struct evhttp_request *req) +{ + int is_keepalive = evhttp_is_connection_keepalive(req->input_headers); + evbuffer_add_printf(bufferevent_get_output(evcon->bufev), + "HTTP/%d.%d %d %s\r\n", + req->major, req->minor, req->response_code, + req->response_code_line); + + if (req->major == 1) { + if (req->minor >= 1) + evhttp_maybe_add_date_header(req->output_headers); + + /* + * if the protocol is 1.0; and the connection was keep-alive + * we need to add a keep-alive header, too. + */ + if (req->minor == 0 && is_keepalive) + evhttp_add_header(req->output_headers, + "Connection", "keep-alive"); + + if ((req->minor >= 1 || is_keepalive) && + evhttp_response_needs_body(req)) { + /* + * we need to add the content length if the + * user did not give it, this is required for + * persistent connections to work. + */ + evhttp_maybe_add_content_length_header( + req->output_headers, + evbuffer_get_length(req->output_buffer)); + } + } + + /* Potentially add headers for unidentified content. */ + if (evhttp_response_needs_body(req)) { + if (evhttp_find_header(req->output_headers, + "Content-Type") == NULL) { + evhttp_add_header(req->output_headers, + "Content-Type", "text/html; charset=ISO-8859-1"); + } + } + + /* if the request asked for a close, we send a close, too */ + if (evhttp_is_connection_close(req->flags, req->input_headers)) { + evhttp_remove_header(req->output_headers, "Connection"); + if (!(req->flags & EVHTTP_PROXY_REQUEST)) + evhttp_add_header(req->output_headers, "Connection", "close"); + evhttp_remove_header(req->output_headers, "Proxy-Connection"); + } +} + +/** Generate all headers appropriate for sending the http request in req (or + * the response, if we're sending a response), and write them to evcon's + * bufferevent. Also writes all data from req->output_buffer */ +static void +evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req) +{ + struct evkeyval *header; + struct evbuffer *output = bufferevent_get_output(evcon->bufev); + + /* + * Depending if this is a HTTP request or response, we might need to + * add some new headers or remove existing headers. + */ + if (req->kind == EVHTTP_REQUEST) { + evhttp_make_header_request(evcon, req); + } else { + evhttp_make_header_response(evcon, req); + } + + TAILQ_FOREACH(header, req->output_headers, next) { + evbuffer_add_printf(output, "%s: %s\r\n", + header->key, header->value); + } + evbuffer_add(output, "\r\n", 2); + + if (evbuffer_get_length(req->output_buffer) > 0) { + /* + * For a request, we add the POST data, for a reply, this + * is the regular data. + */ + /* XXX We might want to support waiting (a limited amount of + time) for a continue status line from the server before + sending POST/PUT message bodies. */ + evbuffer_add_buffer(output, req->output_buffer); + } +} + +void +evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon, + ev_ssize_t new_max_headers_size) +{ + if (new_max_headers_size<0) + evcon->max_headers_size = EV_SIZE_MAX; + else + evcon->max_headers_size = new_max_headers_size; +} +void +evhttp_connection_set_max_body_size(struct evhttp_connection* evcon, + ev_ssize_t new_max_body_size) +{ + if (new_max_body_size<0) + evcon->max_body_size = EV_UINT64_MAX; + else + evcon->max_body_size = new_max_body_size; +} + +static int +evhttp_connection_incoming_fail(struct evhttp_request *req, + enum evhttp_connection_error error) +{ + switch (error) { + case EVCON_HTTP_TIMEOUT: + case EVCON_HTTP_EOF: + /* + * these are cases in which we probably should just + * close the connection and not send a reply. this + * case may happen when a browser keeps a persistent + * connection open and we timeout on the read. when + * the request is still being used for sending, we + * need to disassociated it from the connection here. + */ + if (!req->userdone) { + /* remove it so that it will not be freed */ + TAILQ_REMOVE(&req->evcon->requests, req, next); + /* indicate that this request no longer has a + * connection object + */ + req->evcon = NULL; + } + return (-1); + case EVCON_HTTP_INVALID_HEADER: + case EVCON_HTTP_BUFFER_ERROR: + case EVCON_HTTP_REQUEST_CANCEL: + default: /* xxx: probably should just error on default */ + /* the callback looks at the uri to determine errors */ + if (req->uri) { + mm_free(req->uri); + req->uri = NULL; + } + if (req->uri_elems) { + evhttp_uri_free(req->uri_elems); + req->uri_elems = NULL; + } + + /* + * the callback needs to send a reply, once the reply has + * been send, the connection should get freed. + */ + (*req->cb)(req, req->cb_arg); + } + + return (0); +} + +/* Called when evcon has experienced a (non-recoverable? -NM) error, as + * given in error. If it's an outgoing connection, reset the connection, + * retry any pending requests, and inform the user. If it's incoming, + * delegates to evhttp_connection_incoming_fail(). */ +void +evhttp_connection_fail(struct evhttp_connection *evcon, + enum evhttp_connection_error error) +{ + struct evhttp_request* req = TAILQ_FIRST(&evcon->requests); + void (*cb)(struct evhttp_request *, void *); + void *cb_arg; + EVUTIL_ASSERT(req != NULL); + + bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE); + + if (evcon->flags & EVHTTP_CON_INCOMING) { + /* + * for incoming requests, there are two different + * failure cases. it's either a network level error + * or an http layer error. for problems on the network + * layer like timeouts we just drop the connections. + * For HTTP problems, we might have to send back a + * reply before the connection can be freed. + */ + if (evhttp_connection_incoming_fail(req, error) == -1) + evhttp_connection_free(evcon); + return; + } + + /* when the request was canceled, the callback is not executed */ + if (error != EVCON_HTTP_REQUEST_CANCEL) { + /* save the callback for later; the cb might free our object */ + cb = req->cb; + cb_arg = req->cb_arg; + } else { + cb = NULL; + cb_arg = NULL; + } + + /* do not fail all requests; the next request is going to get + * send over a new connection. when a user cancels a request, + * all other pending requests should be processed as normal + */ + TAILQ_REMOVE(&evcon->requests, req, next); + evhttp_request_free(req); + + /* reset the connection */ + evhttp_connection_reset(evcon); + + /* We are trying the next request that was queued on us */ + if (TAILQ_FIRST(&evcon->requests) != NULL) + evhttp_connection_connect(evcon); + + /* inform the user */ + if (cb != NULL) + (*cb)(NULL, cb_arg); +} + +/* Bufferevent callback: invoked when any data has been written from an + * http connection's bufferevent */ +static void +evhttp_write_cb(struct bufferevent *bufev, void *arg) +{ + struct evhttp_connection *evcon = arg; + + /* Activate our call back */ + if (evcon->cb != NULL) + (*evcon->cb)(evcon, evcon->cb_arg); +} + +/** + * Advance the connection state. + * - If this is an outgoing connection, we've just processed the response; + * idle or close the connection. + * - If this is an incoming connection, we've just processed the request; + * respond. + */ +static void +evhttp_connection_done(struct evhttp_connection *evcon) +{ + struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); + int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING; + + if (con_outgoing) { + /* idle or close the connection */ + int need_close; + TAILQ_REMOVE(&evcon->requests, req, next); + req->evcon = NULL; + + evcon->state = EVCON_IDLE; + + need_close = + evhttp_is_connection_close(req->flags, req->input_headers)|| + evhttp_is_connection_close(req->flags, req->output_headers); + + /* check if we got asked to close the connection */ + if (need_close) + evhttp_connection_reset(evcon); + + if (TAILQ_FIRST(&evcon->requests) != NULL) { + /* + * We have more requests; reset the connection + * and deal with the next request. + */ + if (!evhttp_connected(evcon)) + evhttp_connection_connect(evcon); + else + evhttp_request_dispatch(evcon); + } else if (!need_close) { + /* + * The connection is going to be persistent, but we + * need to detect if the other side closes it. + */ + evhttp_connection_start_detectclose(evcon); + } + } else { + /* + * incoming connection - we need to leave the request on the + * connection so that we can reply to it. + */ + evcon->state = EVCON_WRITING; + } + + /* notify the user of the request */ + (*req->cb)(req, req->cb_arg); + + /* if this was an outgoing request, we own and it's done. so free it. + * unless the callback specifically requested to own the request. + */ + if (con_outgoing && ((req->flags & EVHTTP_USER_OWNED) == 0)) { + evhttp_request_free(req); + } +} + +/* + * Handles reading from a chunked request. + * return ALL_DATA_READ: + * all data has been read + * return MORE_DATA_EXPECTED: + * more data is expected + * return DATA_CORRUPTED: + * data is corrupted + * return REQUEST_CANCELED: + * request was canceled by the user calling evhttp_cancel_request + * return DATA_TOO_LONG: + * ran over the maximum limit + */ + +static enum message_read_status +evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf) +{ + if (req == NULL || buf == NULL) { + return DATA_CORRUPTED; + } + + while (1) { + size_t buflen; + + if ((buflen = evbuffer_get_length(buf)) == 0) { + break; + } + + /* evbuffer_get_length returns size_t, but len variable is ssize_t, + * check for overflow conditions */ + if (buflen > EV_SSIZE_MAX) { + return DATA_CORRUPTED; + } + + if (req->ntoread < 0) { + /* Read chunk size */ + ev_int64_t ntoread; + char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF); + char *endp; + int error; + if (p == NULL) + break; + /* the last chunk is on a new line? */ + if (strlen(p) == 0) { + mm_free(p); + continue; + } + ntoread = evutil_strtoll(p, &endp, 16); + error = (*p == '\0' || + (*endp != '\0' && *endp != ' ') || + ntoread < 0); + mm_free(p); + if (error) { + /* could not get chunk size */ + return (DATA_CORRUPTED); + } + + /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */ + if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) { + return DATA_CORRUPTED; + } + + if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) { + /* failed body length test */ + event_debug(("Request body is too long")); + return (DATA_TOO_LONG); + } + + req->body_size += (size_t)ntoread; + req->ntoread = ntoread; + if (req->ntoread == 0) { + /* Last chunk */ + return (ALL_DATA_READ); + } + continue; + } + + /* req->ntoread is signed int64, len is ssize_t, based on arch, + * ssize_t could only be 32b, check for these conditions */ + if (req->ntoread > EV_SSIZE_MAX) { + return DATA_CORRUPTED; + } + + /* don't have enough to complete a chunk; wait for more */ + if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread) + return (MORE_DATA_EXPECTED); + + /* Completed chunk */ + evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread); + req->ntoread = -1; + if (req->chunk_cb != NULL) { + req->flags |= EVHTTP_REQ_DEFER_FREE; + (*req->chunk_cb)(req, req->cb_arg); + evbuffer_drain(req->input_buffer, + evbuffer_get_length(req->input_buffer)); + req->flags &= ~EVHTTP_REQ_DEFER_FREE; + if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) { + return (REQUEST_CANCELED); + } + } + } + + return (MORE_DATA_EXPECTED); +} + +static void +evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req) +{ + struct evbuffer *buf = bufferevent_get_input(evcon->bufev); + + switch (evhttp_parse_headers(req, buf)) { + case DATA_CORRUPTED: + case DATA_TOO_LONG: + evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); + break; + case ALL_DATA_READ: + bufferevent_disable(evcon->bufev, EV_READ); + evhttp_connection_done(evcon); + break; + case MORE_DATA_EXPECTED: + case REQUEST_CANCELED: /* ??? */ + default: + bufferevent_enable(evcon->bufev, EV_READ); + break; + } +} + +static void +evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req) +{ + struct evbuffer *buf = bufferevent_get_input(evcon->bufev); + + if (req->chunked) { + switch (evhttp_handle_chunked_read(req, buf)) { + case ALL_DATA_READ: + /* finished last chunk */ + evcon->state = EVCON_READING_TRAILER; + evhttp_read_trailer(evcon, req); + return; + case DATA_CORRUPTED: + case DATA_TOO_LONG:/*separate error for this? XXX */ + /* corrupted data */ + evhttp_connection_fail(evcon, + EVCON_HTTP_INVALID_HEADER); + return; + case REQUEST_CANCELED: + /* request canceled */ + evhttp_request_free(req); + return; + case MORE_DATA_EXPECTED: + default: + break; + } + } else if (req->ntoread < 0) { + /* Read until connection close. */ + if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) { + evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); + return; + } + + req->body_size += evbuffer_get_length(buf); + evbuffer_add_buffer(req->input_buffer, buf); + } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) { + /* XXX: the above get_length comparison has to be fixed for overflow conditions! */ + /* We've postponed moving the data until now, but we're + * about to use it. */ + size_t n = evbuffer_get_length(buf); + + if (n > (size_t) req->ntoread) + n = (size_t) req->ntoread; + req->ntoread -= n; + req->body_size += n; + evbuffer_remove_buffer(buf, req->input_buffer, n); + } + + if (req->body_size > req->evcon->max_body_size || + (!req->chunked && req->ntoread >= 0 && + (size_t)req->ntoread > req->evcon->max_body_size)) { + /* XXX: The above casted comparison must checked for overflow */ + /* failed body length test */ + event_debug(("Request body is too long")); + evhttp_connection_fail(evcon, + EVCON_HTTP_INVALID_HEADER); + return; + } + + if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) { + req->flags |= EVHTTP_REQ_DEFER_FREE; + (*req->chunk_cb)(req, req->cb_arg); + req->flags &= ~EVHTTP_REQ_DEFER_FREE; + evbuffer_drain(req->input_buffer, + evbuffer_get_length(req->input_buffer)); + if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) { + evhttp_request_free(req); + return; + } + } + + if (req->ntoread == 0) { + bufferevent_disable(evcon->bufev, EV_READ); + /* Completed content length */ + evhttp_connection_done(evcon); + return; + } + + /* Read more! */ + bufferevent_enable(evcon->bufev, EV_READ); +} + +#define get_deferred_queue(evcon) \ + (event_base_get_deferred_cb_queue((evcon)->base)) + +/* + * Gets called when more data becomes available + */ + +static void +evhttp_read_cb(struct bufferevent *bufev, void *arg) +{ + struct evhttp_connection *evcon = arg; + struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); + + /* Cancel if it's pending. */ + event_deferred_cb_cancel(get_deferred_queue(evcon), + &evcon->read_more_deferred_cb); + + switch (evcon->state) { + case EVCON_READING_FIRSTLINE: + evhttp_read_firstline(evcon, req); + /* note the request may have been freed in + * evhttp_read_body */ + break; + case EVCON_READING_HEADERS: + evhttp_read_header(evcon, req); + /* note the request may have been freed in + * evhttp_read_body */ + break; + case EVCON_READING_BODY: + evhttp_read_body(evcon, req); + /* note the request may have been freed in + * evhttp_read_body */ + break; + case EVCON_READING_TRAILER: + evhttp_read_trailer(evcon, req); + break; + case EVCON_IDLE: + { +#ifdef USE_DEBUG + struct evbuffer *input; + size_t total_len; + + input = bufferevent_get_input(evcon->bufev); + total_len = evbuffer_get_length(input); + event_debug(("%s: read "EV_SIZE_FMT + " bytes in EVCON_IDLE state," + " resetting connection", + __func__, EV_SIZE_ARG(total_len))); +#endif + + evhttp_connection_reset(evcon); + } + break; + case EVCON_DISCONNECTED: + case EVCON_CONNECTING: + case EVCON_WRITING: + default: + event_errx(1, "%s: illegal connection state %d", + __func__, evcon->state); + } +} + +static void +evhttp_deferred_read_cb(struct deferred_cb *cb, void *data) +{ + struct evhttp_connection *evcon = data; + evhttp_read_cb(evcon->bufev, evcon); +} + +static void +evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg) +{ + /* This is after writing the request to the server */ + struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); + EVUTIL_ASSERT(req != NULL); + + EVUTIL_ASSERT(evcon->state == EVCON_WRITING); + + /* We are done writing our header and are now expecting the response */ + req->kind = EVHTTP_RESPONSE; + + evhttp_start_read(evcon); +} + +/* + * Clean up a connection object + */ + +void +evhttp_connection_free(struct evhttp_connection *evcon) +{ + struct evhttp_request *req; + + /* notify interested parties that this connection is going down */ + if (evcon->fd != -1) { + if (evhttp_connected(evcon) && evcon->closecb != NULL) + (*evcon->closecb)(evcon, evcon->closecb_arg); + } + + /* remove all requests that might be queued on this + * connection. for server connections, this should be empty. + * because it gets dequeued either in evhttp_connection_done or + * evhttp_connection_fail. + */ + while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) { + TAILQ_REMOVE(&evcon->requests, req, next); + evhttp_request_free(req); + } + + if (evcon->http_server != NULL) { + struct evhttp *http = evcon->http_server; + TAILQ_REMOVE(&http->connections, evcon, next); + } + + if (event_initialized(&evcon->retry_ev)) { + event_del(&evcon->retry_ev); + event_debug_unassign(&evcon->retry_ev); + } + + if (evcon->bufev != NULL) + bufferevent_free(evcon->bufev); + + event_deferred_cb_cancel(get_deferred_queue(evcon), + &evcon->read_more_deferred_cb); + + if (evcon->fd != -1) { + shutdown(evcon->fd, EVUTIL_SHUT_WR); + evutil_closesocket(evcon->fd); + } + + if (evcon->bind_address != NULL) + mm_free(evcon->bind_address); + + if (evcon->address != NULL) + mm_free(evcon->address); + + mm_free(evcon); +} + +void +evhttp_connection_set_local_address(struct evhttp_connection *evcon, + const char *address) +{ + EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED); + if (evcon->bind_address) + mm_free(evcon->bind_address); + if ((evcon->bind_address = mm_strdup(address)) == NULL) + event_warn("%s: strdup", __func__); +} + +void +evhttp_connection_set_local_port(struct evhttp_connection *evcon, + ev_uint16_t port) +{ + EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED); + evcon->bind_port = port; +} + +static void +evhttp_request_dispatch(struct evhttp_connection* evcon) +{ + struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); + + /* this should not usually happy but it's possible */ + if (req == NULL) + return; + + /* delete possible close detection events */ + evhttp_connection_stop_detectclose(evcon); + + /* we assume that the connection is connected already */ + EVUTIL_ASSERT(evcon->state == EVCON_IDLE); + + evcon->state = EVCON_WRITING; + + /* Create the header from the store arguments */ + evhttp_make_header(evcon, req); + + evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL); +} + +/* Reset our connection state: disables reading/writing, closes our fd (if +* any), clears out buffers, and puts us in state DISCONNECTED. */ +void +evhttp_connection_reset(struct evhttp_connection *evcon) +{ + struct evbuffer *tmp; + + /* XXXX This is not actually an optimal fix. Instead we ought to have + an API for "stop connecting", or use bufferevent_setfd to turn off + connecting. But for Libevent 2.0, this seems like a minimal change + least likely to disrupt the rest of the bufferevent and http code. + + Why is this here? If the fd is set in the bufferevent, and the + bufferevent is connecting, then you can't actually stop the + bufferevent from trying to connect with bufferevent_disable(). The + connect will never trigger, since we close the fd, but the timeout + might. That caused an assertion failure in evhttp_connection_fail. + */ + bufferevent_disable_hard(evcon->bufev, EV_READ|EV_WRITE); + + if (evcon->fd != -1) { + /* inform interested parties about connection close */ + if (evhttp_connected(evcon) && evcon->closecb != NULL) + (*evcon->closecb)(evcon, evcon->closecb_arg); + + shutdown(evcon->fd, EVUTIL_SHUT_WR); + evutil_closesocket(evcon->fd); + evcon->fd = -1; + } + + /* we need to clean up any buffered data */ + tmp = bufferevent_get_output(evcon->bufev); + evbuffer_drain(tmp, evbuffer_get_length(tmp)); + tmp = bufferevent_get_input(evcon->bufev); + evbuffer_drain(tmp, evbuffer_get_length(tmp)); + + evcon->state = EVCON_DISCONNECTED; +} + +static void +evhttp_connection_start_detectclose(struct evhttp_connection *evcon) +{ + evcon->flags |= EVHTTP_CON_CLOSEDETECT; + + bufferevent_enable(evcon->bufev, EV_READ); +} + +static void +evhttp_connection_stop_detectclose(struct evhttp_connection *evcon) +{ + evcon->flags &= ~EVHTTP_CON_CLOSEDETECT; + + bufferevent_disable(evcon->bufev, EV_READ); +} + +static void +evhttp_connection_retry(evutil_socket_t fd, short what, void *arg) +{ + struct evhttp_connection *evcon = arg; + + evcon->state = EVCON_DISCONNECTED; + evhttp_connection_connect(evcon); +} + +static void +evhttp_connection_cb_cleanup(struct evhttp_connection *evcon) +{ + struct evcon_requestq requests; + + if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) { + evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon); + /* XXXX handle failure from evhttp_add_event */ + evhttp_add_event(&evcon->retry_ev, + MIN(3600, 2 << evcon->retry_cnt), + HTTP_CONNECT_TIMEOUT); + evcon->retry_cnt++; + return; + } + evhttp_connection_reset(evcon); + + /* + * User callback can do evhttp_make_request() on the same + * evcon so new request will be added to evcon->requests. To + * avoid freeing it prematurely we iterate over the copy of + * the queue. + */ + TAILQ_INIT(&requests); + while (TAILQ_FIRST(&evcon->requests) != NULL) { + struct evhttp_request *request = TAILQ_FIRST(&evcon->requests); + TAILQ_REMOVE(&evcon->requests, request, next); + TAILQ_INSERT_TAIL(&requests, request, next); + } + + /* for now, we just signal all requests by executing their callbacks */ + while (TAILQ_FIRST(&requests) != NULL) { + struct evhttp_request *request = TAILQ_FIRST(&requests); + TAILQ_REMOVE(&requests, request, next); + request->evcon = NULL; + + /* we might want to set an error here */ + request->cb(request, request->cb_arg); + evhttp_request_free(request); + } +} + +static void +evhttp_error_cb(struct bufferevent *bufev, short what, void *arg) +{ + struct evhttp_connection *evcon = arg; + struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); + + switch (evcon->state) { + case EVCON_CONNECTING: + if (what & BEV_EVENT_TIMEOUT) { + event_debug(("%s: connection timeout for \"%s:%d\" on %d", + __func__, evcon->address, evcon->port, + evcon->fd)); + evhttp_connection_cb_cleanup(evcon); + return; + } + break; + + case EVCON_READING_BODY: + if (!req->chunked && req->ntoread < 0 + && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) { + /* EOF on read can be benign */ + evhttp_connection_done(evcon); + return; + } + break; + + case EVCON_DISCONNECTED: + case EVCON_IDLE: + case EVCON_READING_FIRSTLINE: + case EVCON_READING_HEADERS: + case EVCON_READING_TRAILER: + case EVCON_WRITING: + default: + break; + } + + /* when we are in close detect mode, a read error means that + * the other side closed their connection. + */ + if (evcon->flags & EVHTTP_CON_CLOSEDETECT) { + evcon->flags &= ~EVHTTP_CON_CLOSEDETECT; + EVUTIL_ASSERT(evcon->http_server == NULL); + /* For connections from the client, we just + * reset the connection so that it becomes + * disconnected. + */ + EVUTIL_ASSERT(evcon->state == EVCON_IDLE); + evhttp_connection_reset(evcon); + return; + } + + if (what & BEV_EVENT_TIMEOUT) { + evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT); + } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) { + evhttp_connection_fail(evcon, EVCON_HTTP_EOF); + } else { + evhttp_connection_fail(evcon, EVCON_HTTP_BUFFER_ERROR); + } +} + +/* + * Event callback for asynchronous connection attempt. + */ +static void +evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg) +{ + struct evhttp_connection *evcon = arg; + int error; + ev_socklen_t errsz = sizeof(error); + + if (!(what & BEV_EVENT_CONNECTED)) { + /* some operating systems return ECONNREFUSED immediately + * when connecting to a local address. the cleanup is going + * to reschedule this function call. + */ +#ifndef WIN32 + if (errno == ECONNREFUSED) + goto cleanup; +#endif + evhttp_error_cb(bufev, what, arg); + return; + } + + /* Check if the connection completed */ + if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error, + &errsz) == -1) { + event_debug(("%s: getsockopt for \"%s:%d\" on %d", + __func__, evcon->address, evcon->port, evcon->fd)); + goto cleanup; + } + + if (error) { + event_debug(("%s: connect failed for \"%s:%d\" on %d: %s", + __func__, evcon->address, evcon->port, evcon->fd, + evutil_socket_error_to_string(error))); + goto cleanup; + } + + /* We are connected to the server now */ + event_debug(("%s: connected to \"%s:%d\" on %d\n", + __func__, evcon->address, evcon->port, evcon->fd)); + + /* Reset the retry count as we were successful in connecting */ + evcon->retry_cnt = 0; + evcon->state = EVCON_IDLE; + + /* reset the bufferevent cbs */ + bufferevent_setcb(evcon->bufev, + evhttp_read_cb, + evhttp_write_cb, + evhttp_error_cb, + evcon); + + if (evcon->timeout == -1) + bufferevent_settimeout(evcon->bufev, + HTTP_READ_TIMEOUT, HTTP_WRITE_TIMEOUT); + else { + struct timeval tv; + tv.tv_sec = evcon->timeout; + tv.tv_usec = 0; + bufferevent_set_timeouts(evcon->bufev, &tv, &tv); + } + + /* try to start requests that have queued up on this connection */ + evhttp_request_dispatch(evcon); + return; + + cleanup: + evhttp_connection_cb_cleanup(evcon); +} + +/* + * Check if we got a valid response code. + */ + +static int +evhttp_valid_response_code(int code) +{ + if (code == 0) + return (0); + + return (1); +} + +static int +evhttp_parse_http_version(const char *version, struct evhttp_request *req) +{ + int major, minor; + char ch; + int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch); + if (n != 2 || major > 1) { + event_debug(("%s: bad version %s on message %p from %s", + __func__, version, req, req->remote_host)); + return (-1); + } + req->major = major; + req->minor = minor; + return (0); +} + +/* Parses the status line of a web server */ + +static int +evhttp_parse_response_line(struct evhttp_request *req, char *line) +{ + char *protocol; + char *number; + const char *readable = ""; + + protocol = strsep(&line, " "); + if (line == NULL) + return (-1); + number = strsep(&line, " "); + if (line != NULL) + readable = line; + + if (evhttp_parse_http_version(protocol, req) < 0) + return (-1); + + req->response_code = atoi(number); + if (!evhttp_valid_response_code(req->response_code)) { + event_debug(("%s: bad response code \"%s\"", + __func__, number)); + return (-1); + } + + if ((req->response_code_line = mm_strdup(readable)) == NULL) { + event_warn("%s: strdup", __func__); + return (-1); + } + + return (0); +} + +/* Parse the first line of a HTTP request */ + +static int +evhttp_parse_request_line(struct evhttp_request *req, char *line) +{ + char *method; + char *uri; + char *version; + const char *hostname; + const char *scheme; + + /* Parse the request line */ + method = strsep(&line, " "); + if (line == NULL) + return (-1); + uri = strsep(&line, " "); + if (line == NULL) + return (-1); + version = strsep(&line, " "); + if (line != NULL) + return (-1); + + /* First line */ + if (strcmp(method, "GET") == 0) { + req->type = EVHTTP_REQ_GET; + } else if (strcmp(method, "POST") == 0) { + req->type = EVHTTP_REQ_POST; + } else if (strcmp(method, "HEAD") == 0) { + req->type = EVHTTP_REQ_HEAD; + } else if (strcmp(method, "PUT") == 0) { + req->type = EVHTTP_REQ_PUT; + } else if (strcmp(method, "DELETE") == 0) { + req->type = EVHTTP_REQ_DELETE; + } else if (strcmp(method, "OPTIONS") == 0) { + req->type = EVHTTP_REQ_OPTIONS; + } else if (strcmp(method, "TRACE") == 0) { + req->type = EVHTTP_REQ_TRACE; + } else if (strcmp(method, "PATCH") == 0) { + req->type = EVHTTP_REQ_PATCH; + } else { + req->type = _EVHTTP_REQ_UNKNOWN; + event_debug(("%s: bad method %s on request %p from %s", + __func__, method, req, req->remote_host)); + /* No error yet; we'll give a better error later when + * we see that req->type is unsupported. */ + } + + if (evhttp_parse_http_version(version, req) < 0) + return (-1); + + if ((req->uri = mm_strdup(uri)) == NULL) { + event_debug(("%s: mm_strdup", __func__)); + return (-1); + } + + if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri, + EVHTTP_URI_NONCONFORMANT)) == NULL) { + return -1; + } + + /* If we have an absolute-URI, check to see if it is an http request + for a known vhost or server alias. If we don't know about this + host, we consider it a proxy request. */ + scheme = evhttp_uri_get_scheme(req->uri_elems); + hostname = evhttp_uri_get_host(req->uri_elems); + if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") || + !evutil_ascii_strcasecmp(scheme, "https")) && + hostname && + !evhttp_find_vhost(req->evcon->http_server, NULL, hostname)) + req->flags |= EVHTTP_PROXY_REQUEST; + + return (0); +} + +const char * +evhttp_find_header(const struct evkeyvalq *headers, const char *key) +{ + struct evkeyval *header; + + TAILQ_FOREACH(header, headers, next) { + if (evutil_ascii_strcasecmp(header->key, key) == 0) + return (header->value); + } + + return (NULL); +} + +void +evhttp_clear_headers(struct evkeyvalq *headers) +{ + struct evkeyval *header; + + for (header = TAILQ_FIRST(headers); + header != NULL; + header = TAILQ_FIRST(headers)) { + TAILQ_REMOVE(headers, header, next); + mm_free(header->key); + mm_free(header->value); + mm_free(header); + } +} + +/* + * Returns 0, if the header was successfully removed. + * Returns -1, if the header could not be found. + */ + +int +evhttp_remove_header(struct evkeyvalq *headers, const char *key) +{ + struct evkeyval *header; + + TAILQ_FOREACH(header, headers, next) { + if (evutil_ascii_strcasecmp(header->key, key) == 0) + break; + } + + if (header == NULL) + return (-1); + + /* Free and remove the header that we found */ + TAILQ_REMOVE(headers, header, next); + mm_free(header->key); + mm_free(header->value); + mm_free(header); + + return (0); +} + +static int +evhttp_header_is_valid_value(const char *value) +{ + const char *p = value; + + while ((p = strpbrk(p, "\r\n")) != NULL) { + /* we really expect only one new line */ + p += strspn(p, "\r\n"); + /* we expect a space or tab for continuation */ + if (*p != ' ' && *p != '\t') + return (0); + } + return (1); +} + +int +evhttp_add_header(struct evkeyvalq *headers, + const char *key, const char *value) +{ + event_debug(("%s: key: %s val: %s\n", __func__, key, value)); + + if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) { + /* drop illegal headers */ + event_debug(("%s: dropping illegal header key\n", __func__)); + return (-1); + } + + if (!evhttp_header_is_valid_value(value)) { + event_debug(("%s: dropping illegal header value\n", __func__)); + return (-1); + } + + return (evhttp_add_header_internal(headers, key, value)); +} + +static int +evhttp_add_header_internal(struct evkeyvalq *headers, + const char *key, const char *value) +{ + struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval)); + if (header == NULL) { + event_warn("%s: calloc", __func__); + return (-1); + } + if ((header->key = mm_strdup(key)) == NULL) { + mm_free(header); + event_warn("%s: strdup", __func__); + return (-1); + } + if ((header->value = mm_strdup(value)) == NULL) { + mm_free(header->key); + mm_free(header); + event_warn("%s: strdup", __func__); + return (-1); + } + + TAILQ_INSERT_TAIL(headers, header, next); + + return (0); +} + +/* + * Parses header lines from a request or a response into the specified + * request object given an event buffer. + * + * Returns + * DATA_CORRUPTED on error + * MORE_DATA_EXPECTED when we need to read more headers + * ALL_DATA_READ when all headers have been read. + */ + +enum message_read_status +evhttp_parse_firstline(struct evhttp_request *req, struct evbuffer *buffer) +{ + char *line; + enum message_read_status status = ALL_DATA_READ; + + size_t line_length; + /* XXX try */ + line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF); + if (line == NULL) { + if (req->evcon != NULL && + evbuffer_get_length(buffer) > req->evcon->max_headers_size) + return (DATA_TOO_LONG); + else + return (MORE_DATA_EXPECTED); + } + + if (req->evcon != NULL && + line_length > req->evcon->max_headers_size) { + mm_free(line); + return (DATA_TOO_LONG); + } + + req->headers_size = line_length; + + switch (req->kind) { + case EVHTTP_REQUEST: + if (evhttp_parse_request_line(req, line) == -1) + status = DATA_CORRUPTED; + break; + case EVHTTP_RESPONSE: + if (evhttp_parse_response_line(req, line) == -1) + status = DATA_CORRUPTED; + break; + default: + status = DATA_CORRUPTED; + } + + mm_free(line); + return (status); +} + +static int +evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line) +{ + struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq); + char *newval; + size_t old_len, line_len; + + if (header == NULL) + return (-1); + + old_len = strlen(header->value); + line_len = strlen(line); + + newval = mm_realloc(header->value, old_len + line_len + 1); + if (newval == NULL) + return (-1); + + memcpy(newval + old_len, line, line_len + 1); + header->value = newval; + + return (0); +} + +enum message_read_status +evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer) +{ + enum message_read_status errcode = DATA_CORRUPTED; + char *line; + enum message_read_status status = MORE_DATA_EXPECTED; + + struct evkeyvalq* headers = req->input_headers; + size_t line_length; + while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF)) + != NULL) { + char *skey, *svalue; + + req->headers_size += line_length; + + if (req->evcon != NULL && + req->headers_size > req->evcon->max_headers_size) { + errcode = DATA_TOO_LONG; + goto error; + } + + if (*line == '\0') { /* Last header - Done */ + status = ALL_DATA_READ; + mm_free(line); + break; + } + + /* Check if this is a continuation line */ + if (*line == ' ' || *line == '\t') { + if (evhttp_append_to_last_header(headers, line) == -1) + goto error; + mm_free(line); + continue; + } + + /* Processing of header lines */ + svalue = line; + skey = strsep(&svalue, ":"); + if (svalue == NULL) + goto error; + + svalue += strspn(svalue, " "); + + if (evhttp_add_header(headers, skey, svalue) == -1) + goto error; + + mm_free(line); + } + + if (status == MORE_DATA_EXPECTED) { + if (req->evcon != NULL && + req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size) + return (DATA_TOO_LONG); + } + + return (status); + + error: + mm_free(line); + return (errcode); +} + +static int +evhttp_get_body_length(struct evhttp_request *req) +{ + struct evkeyvalq *headers = req->input_headers; + const char *content_length; + const char *connection; + + content_length = evhttp_find_header(headers, "Content-Length"); + connection = evhttp_find_header(headers, "Connection"); + + if (content_length == NULL && connection == NULL) + req->ntoread = -1; + else if (content_length == NULL && + evutil_ascii_strcasecmp(connection, "Close") != 0) { + /* Bad combination, we don't know when it will end */ + event_warnx("%s: we got no content length, but the " + "server wants to keep the connection open: %s.", + __func__, connection); + return (-1); + } else if (content_length == NULL) { + req->ntoread = -1; + } else { + char *endp; + ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10); + if (*content_length == '\0' || *endp != '\0' || ntoread < 0) { + event_debug(("%s: illegal content length: %s", + __func__, content_length)); + return (-1); + } + req->ntoread = ntoread; + } + + event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n", + __func__, EV_I64_ARG(req->ntoread), + EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev))))); + + return (0); +} + +static int +evhttp_method_may_have_body(enum evhttp_cmd_type type) +{ + switch (type) { + case EVHTTP_REQ_POST: + case EVHTTP_REQ_PUT: + case EVHTTP_REQ_PATCH: + return 1; + case EVHTTP_REQ_TRACE: + return 0; + /* XXX May any of the below methods have a body? */ + case EVHTTP_REQ_GET: + case EVHTTP_REQ_HEAD: + case EVHTTP_REQ_DELETE: + case EVHTTP_REQ_OPTIONS: + case EVHTTP_REQ_CONNECT: + return 0; + default: + return 0; + } +} + +static void +evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req) +{ + const char *xfer_enc; + + /* If this is a request without a body, then we are done */ + if (req->kind == EVHTTP_REQUEST && + !evhttp_method_may_have_body(req->type)) { + evhttp_connection_done(evcon); + return; + } + evcon->state = EVCON_READING_BODY; + xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding"); + if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) { + req->chunked = 1; + req->ntoread = -1; + } else { + if (evhttp_get_body_length(req) == -1) { + evhttp_connection_fail(evcon, + EVCON_HTTP_INVALID_HEADER); + return; + } + if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) { + /* An incoming request with no content-length and no + * transfer-encoding has no body. */ + evhttp_connection_done(evcon); + return; + } + } + + /* Should we send a 100 Continue status line? */ + if (req->kind == EVHTTP_REQUEST && REQ_VERSION_ATLEAST(req, 1, 1)) { + const char *expect; + + expect = evhttp_find_header(req->input_headers, "Expect"); + if (expect) { + if (!evutil_ascii_strcasecmp(expect, "100-continue")) { + /* XXX It would be nice to do some sanity + checking here. Does the resource exist? + Should the resource accept post requests? If + no, we should respond with an error. For + now, just optimistically tell the client to + send their message body. */ + if (req->ntoread > 0) { + /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */ + if ((req->evcon->max_body_size <= EV_INT64_MAX) && (ev_uint64_t)req->ntoread > req->evcon->max_body_size) { + evhttp_send_error(req, HTTP_ENTITYTOOLARGE, NULL); + return; + } + } + if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev))) + evhttp_send_continue(evcon, req); + } else { + evhttp_send_error(req, HTTP_EXPECTATIONFAILED, + NULL); + return; + } + } + } + + evhttp_read_body(evcon, req); + /* note the request may have been freed in evhttp_read_body */ +} + +static void +evhttp_read_firstline(struct evhttp_connection *evcon, + struct evhttp_request *req) +{ + enum message_read_status res; + + res = evhttp_parse_firstline(req, bufferevent_get_input(evcon->bufev)); + if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) { + /* Error while reading, terminate */ + event_debug(("%s: bad header lines on %d\n", + __func__, evcon->fd)); + evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); + return; + } else if (res == MORE_DATA_EXPECTED) { + /* Need more header lines */ + return; + } + + evcon->state = EVCON_READING_HEADERS; + evhttp_read_header(evcon, req); +} + +static void +evhttp_read_header(struct evhttp_connection *evcon, + struct evhttp_request *req) +{ + enum message_read_status res; + evutil_socket_t fd = evcon->fd; + + res = evhttp_parse_headers(req, bufferevent_get_input(evcon->bufev)); + if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) { + /* Error while reading, terminate */ + event_debug(("%s: bad header lines on %d\n", __func__, fd)); + evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); + return; + } else if (res == MORE_DATA_EXPECTED) { + /* Need more header lines */ + return; + } + + /* Disable reading for now */ + bufferevent_disable(evcon->bufev, EV_READ); + + /* Done reading headers, do the real work */ + switch (req->kind) { + case EVHTTP_REQUEST: + event_debug(("%s: checking for post data on %d\n", + __func__, fd)); + evhttp_get_body(evcon, req); + /* note the request may have been freed in evhttp_get_body */ + break; + + case EVHTTP_RESPONSE: + /* Start over if we got a 100 Continue response. */ + if (req->response_code == 100) { + evhttp_start_read(evcon); + return; + } + if (!evhttp_response_needs_body(req)) { + event_debug(("%s: skipping body for code %d\n", + __func__, req->response_code)); + evhttp_connection_done(evcon); + } else { + event_debug(("%s: start of read body for %s on %d\n", + __func__, req->remote_host, fd)); + evhttp_get_body(evcon, req); + /* note the request may have been freed in + * evhttp_get_body */ + } + break; + + default: + event_warnx("%s: bad header on %d", __func__, fd); + evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); + break; + } + /* request may have been freed above */ +} + +/* + * Creates a TCP connection to the specified port and executes a callback + * when finished. Failure or success is indicate by the passed connection + * object. + * + * Although this interface accepts a hostname, it is intended to take + * only numeric hostnames so that non-blocking DNS resolution can + * happen elsewhere. + */ + +struct evhttp_connection * +evhttp_connection_new(const char *address, unsigned short port) +{ + return (evhttp_connection_base_new(NULL, NULL, address, port)); +} + +struct evhttp_connection * +evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase, + const char *address, unsigned short port) +{ + struct evhttp_connection *evcon = NULL; + + event_debug(("Attempting connection to %s:%d\n", address, port)); + + if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) { + event_warn("%s: calloc failed", __func__); + goto error; + } + + evcon->fd = -1; + evcon->port = port; + + evcon->max_headers_size = EV_SIZE_MAX; + evcon->max_body_size = EV_SIZE_MAX; + + evcon->timeout = -1; + evcon->retry_cnt = evcon->retry_max = 0; + + if ((evcon->address = mm_strdup(address)) == NULL) { + event_warn("%s: strdup failed", __func__); + goto error; + } + + if ((evcon->bufev = bufferevent_new(-1, + evhttp_read_cb, + evhttp_write_cb, + evhttp_error_cb, evcon)) == NULL) { + event_warn("%s: bufferevent_new failed", __func__); + goto error; + } + + evcon->state = EVCON_DISCONNECTED; + TAILQ_INIT(&evcon->requests); + + if (base != NULL) { + evcon->base = base; + bufferevent_base_set(base, evcon->bufev); + } + + + event_deferred_cb_init(&evcon->read_more_deferred_cb, + evhttp_deferred_read_cb, evcon); + + evcon->dns_base = dnsbase; + + return (evcon); + + error: + if (evcon != NULL) + evhttp_connection_free(evcon); + return (NULL); +} + +struct bufferevent * +evhttp_connection_get_bufferevent(struct evhttp_connection *evcon) +{ + return evcon->bufev; +} + +void +evhttp_connection_set_base(struct evhttp_connection *evcon, + struct event_base *base) +{ + EVUTIL_ASSERT(evcon->base == NULL); + EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED); + evcon->base = base; + bufferevent_base_set(base, evcon->bufev); +} + +void +evhttp_connection_set_timeout(struct evhttp_connection *evcon, + int timeout_in_secs) +{ + evcon->timeout = timeout_in_secs; + + if (evcon->timeout == -1) + bufferevent_settimeout(evcon->bufev, + HTTP_READ_TIMEOUT, HTTP_WRITE_TIMEOUT); + else + bufferevent_settimeout(evcon->bufev, + evcon->timeout, evcon->timeout); +} + +void +evhttp_connection_set_retries(struct evhttp_connection *evcon, + int retry_max) +{ + evcon->retry_max = retry_max; +} + +void +evhttp_connection_set_closecb(struct evhttp_connection *evcon, + void (*cb)(struct evhttp_connection *, void *), void *cbarg) +{ + evcon->closecb = cb; + evcon->closecb_arg = cbarg; +} + +void +evhttp_connection_get_peer(struct evhttp_connection *evcon, + char **address, ev_uint16_t *port) +{ + *address = evcon->address; + *port = evcon->port; +} + +int +evhttp_connection_connect(struct evhttp_connection *evcon) +{ + if (evcon->state == EVCON_CONNECTING) + return (0); + + evhttp_connection_reset(evcon); + + EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING)); + evcon->flags |= EVHTTP_CON_OUTGOING; + + evcon->fd = bind_socket( + evcon->bind_address, evcon->bind_port, 0 /*reuse*/); + if (evcon->fd == -1) { + event_debug(("%s: failed to bind to \"%s\"", + __func__, evcon->bind_address)); + return (-1); + } + + /* Set up a callback for successful connection setup */ + bufferevent_setfd(evcon->bufev, evcon->fd); + bufferevent_setcb(evcon->bufev, + NULL /* evhttp_read_cb */, + NULL /* evhttp_write_cb */, + evhttp_connection_cb, + evcon); + bufferevent_settimeout(evcon->bufev, 0, + evcon->timeout != -1 ? evcon->timeout : HTTP_CONNECT_TIMEOUT); + /* make sure that we get a write callback */ + bufferevent_enable(evcon->bufev, EV_WRITE); + + if (bufferevent_socket_connect_hostname(evcon->bufev, evcon->dns_base, + AF_UNSPEC, evcon->address, evcon->port) < 0) { + event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed", + __func__, evcon->address); + /* some operating systems return ECONNREFUSED immediately + * when connecting to a local address. the cleanup is going + * to reschedule this function call. + */ + evhttp_connection_cb_cleanup(evcon); + return (0); + } + + evcon->state = EVCON_CONNECTING; + + return (0); +} + +/* + * Starts an HTTP request on the provided evhttp_connection object. + * If the connection object is not connected to the web server already, + * this will start the connection. + */ + +int +evhttp_make_request(struct evhttp_connection *evcon, + struct evhttp_request *req, + enum evhttp_cmd_type type, const char *uri) +{ + /* We are making a request */ + req->kind = EVHTTP_REQUEST; + req->type = type; + if (req->uri != NULL) + mm_free(req->uri); + if ((req->uri = mm_strdup(uri)) == NULL) { + event_warn("%s: strdup", __func__); + evhttp_request_free(req); + return (-1); + } + + /* Set the protocol version if it is not supplied */ + if (!req->major && !req->minor) { + req->major = 1; + req->minor = 1; + } + + EVUTIL_ASSERT(req->evcon == NULL); + req->evcon = evcon; + EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION)); + + TAILQ_INSERT_TAIL(&evcon->requests, req, next); + + /* If the connection object is not connected; make it so */ + if (!evhttp_connected(evcon)) { + int res = evhttp_connection_connect(evcon); + /* evhttp_connection_fail(), which is called through + * evhttp_connection_connect(), assumes that req lies in + * evcon->requests. Thus, enqueue the request in advance and r + * it in the error case. */ + if (res != 0) + TAILQ_REMOVE(&evcon->requests, req, next); + + return res; + } + + /* + * If it's connected already and we are the first in the queue, + * then we can dispatch this request immediately. Otherwise, it + * will be dispatched once the pending requests are completed. + */ + if (TAILQ_FIRST(&evcon->requests) == req) + evhttp_request_dispatch(evcon); + + return (0); +} + +void +evhttp_cancel_request(struct evhttp_request *req) +{ + struct evhttp_connection *evcon = req->evcon; + if (evcon != NULL) { + /* We need to remove it from the connection */ + if (TAILQ_FIRST(&evcon->requests) == req) { + /* it's currently being worked on, so reset + * the connection. + */ + evhttp_connection_fail(evcon, + EVCON_HTTP_REQUEST_CANCEL); + + /* connection fail freed the request */ + return; + } else { + /* otherwise, we can just remove it from the + * queue + */ + TAILQ_REMOVE(&evcon->requests, req, next); + } + } + + evhttp_request_free(req); +} + +/* + * Reads data from file descriptor into request structure + * Request structure needs to be set up correctly. + */ + +void +evhttp_start_read(struct evhttp_connection *evcon) +{ + /* Set up an event to read the headers */ + bufferevent_disable(evcon->bufev, EV_WRITE); + bufferevent_enable(evcon->bufev, EV_READ); + evcon->state = EVCON_READING_FIRSTLINE; + /* Reset the bufferevent callbacks */ + bufferevent_setcb(evcon->bufev, + evhttp_read_cb, + evhttp_write_cb, + evhttp_error_cb, + evcon); + + /* If there's still data pending, process it next time through the + * loop. Don't do it now; that could get recusive. */ + if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) { + event_deferred_cb_schedule(get_deferred_queue(evcon), + &evcon->read_more_deferred_cb); + } +} + +static void +evhttp_send_done(struct evhttp_connection *evcon, void *arg) +{ + int need_close; + struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); + TAILQ_REMOVE(&evcon->requests, req, next); + + need_close = + (REQ_VERSION_BEFORE(req, 1, 1) && + !evhttp_is_connection_keepalive(req->input_headers))|| + evhttp_is_connection_close(req->flags, req->input_headers) || + evhttp_is_connection_close(req->flags, req->output_headers); + + EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION); + evhttp_request_free(req); + + if (need_close) { + evhttp_connection_free(evcon); + return; + } + + /* we have a persistent connection; try to accept another request. */ + if (evhttp_associate_new_request_with_connection(evcon) == -1) { + evhttp_connection_free(evcon); + } +} + +/* + * Returns an error page. + */ + +void +evhttp_send_error(struct evhttp_request *req, int error, const char *reason) +{ + +#define ERR_FORMAT "\n" \ + "%d %s\n" \ + "\n" \ + "

%s

\n" \ + "\n" + + struct evbuffer *buf = evbuffer_new(); + if (buf == NULL) { + /* if we cannot allocate memory; we just drop the connection */ + evhttp_connection_free(req->evcon); + return; + } + if (reason == NULL) { + reason = evhttp_response_phrase_internal(error); + } + + evhttp_response_code(req, error, reason); + + evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason); + + evhttp_send_page(req, buf); + + evbuffer_free(buf); +#undef ERR_FORMAT +} + +/* Requires that headers and response code are already set up */ + +static inline void +evhttp_send(struct evhttp_request *req, struct evbuffer *databuf) +{ + struct evhttp_connection *evcon = req->evcon; + + if (evcon == NULL) { + evhttp_request_free(req); + return; + } + + EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req); + + /* we expect no more calls form the user on this request */ + req->userdone = 1; + + /* xxx: not sure if we really should expose the data buffer this way */ + if (databuf != NULL) + evbuffer_add_buffer(req->output_buffer, databuf); + + /* Adds headers to the response */ + evhttp_make_header(evcon, req); + + evhttp_write_buffer(evcon, evhttp_send_done, NULL); +} + +void +evhttp_send_reply(struct evhttp_request *req, int code, const char *reason, + struct evbuffer *databuf) +{ + evhttp_response_code(req, code, reason); + + evhttp_send(req, databuf); +} + +void +evhttp_send_reply_start(struct evhttp_request *req, int code, + const char *reason) +{ + evhttp_response_code(req, code, reason); + if (evhttp_find_header(req->output_headers, "Content-Length") == NULL && + REQ_VERSION_ATLEAST(req, 1, 1) && + evhttp_response_needs_body(req)) { + /* + * prefer HTTP/1.1 chunked encoding to closing the connection; + * note RFC 2616 section 4.4 forbids it with Content-Length: + * and it's not necessary then anyway. + */ + evhttp_add_header(req->output_headers, "Transfer-Encoding", + "chunked"); + req->chunked = 1; + } else { + req->chunked = 0; + } + evhttp_make_header(req->evcon, req); + evhttp_write_buffer(req->evcon, NULL, NULL); +} + +void +evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf) +{ + struct evhttp_connection *evcon = req->evcon; + struct evbuffer *output; + + if (evcon == NULL) + return; + + output = bufferevent_get_output(evcon->bufev); + + if (evbuffer_get_length(databuf) == 0) + return; + if (!evhttp_response_needs_body(req)) + return; + if (req->chunked) { + evbuffer_add_printf(output, "%x\r\n", + (unsigned)evbuffer_get_length(databuf)); + } + evbuffer_add_buffer(output, databuf); + if (req->chunked) { + evbuffer_add(output, "\r\n", 2); + } + evhttp_write_buffer(evcon, NULL, NULL); +} + +void +evhttp_send_reply_end(struct evhttp_request *req) +{ + struct evhttp_connection *evcon = req->evcon; + struct evbuffer *output; + + if (evcon == NULL) { + evhttp_request_free(req); + return; + } + + output = bufferevent_get_output(evcon->bufev); + + /* we expect no more calls form the user on this request */ + req->userdone = 1; + + if (req->chunked) { + evbuffer_add(output, "0\r\n\r\n", 5); + evhttp_write_buffer(req->evcon, evhttp_send_done, NULL); + req->chunked = 0; + } else if (evbuffer_get_length(output) == 0) { + /* let the connection know that we are done with the request */ + evhttp_send_done(evcon, NULL); + } else { + /* make the callback execute after all data has been written */ + evcon->cb = evhttp_send_done; + evcon->cb_arg = NULL; + } +} + +static const char *informational_phrases[] = { + /* 100 */ "Continue", + /* 101 */ "Switching Protocols" +}; + +static const char *success_phrases[] = { + /* 200 */ "OK", + /* 201 */ "Created", + /* 202 */ "Accepted", + /* 203 */ "Non-Authoritative Information", + /* 204 */ "No Content", + /* 205 */ "Reset Content", + /* 206 */ "Partial Content" +}; + +static const char *redirection_phrases[] = { + /* 300 */ "Multiple Choices", + /* 301 */ "Moved Permanently", + /* 302 */ "Found", + /* 303 */ "See Other", + /* 304 */ "Not Modified", + /* 305 */ "Use Proxy", + /* 307 */ "Temporary Redirect" +}; + +static const char *client_error_phrases[] = { + /* 400 */ "Bad Request", + /* 401 */ "Unauthorized", + /* 402 */ "Payment Required", + /* 403 */ "Forbidden", + /* 404 */ "Not Found", + /* 405 */ "Method Not Allowed", + /* 406 */ "Not Acceptable", + /* 407 */ "Proxy Authentication Required", + /* 408 */ "Request Time-out", + /* 409 */ "Conflict", + /* 410 */ "Gone", + /* 411 */ "Length Required", + /* 412 */ "Precondition Failed", + /* 413 */ "Request Entity Too Large", + /* 414 */ "Request-URI Too Large", + /* 415 */ "Unsupported Media Type", + /* 416 */ "Requested range not satisfiable", + /* 417 */ "Expectation Failed" +}; + +static const char *server_error_phrases[] = { + /* 500 */ "Internal Server Error", + /* 501 */ "Not Implemented", + /* 502 */ "Bad Gateway", + /* 503 */ "Service Unavailable", + /* 504 */ "Gateway Time-out", + /* 505 */ "HTTP Version not supported" +}; + +struct response_class { + const char *name; + size_t num_responses; + const char **responses; +}; + +#ifndef MEMBERSOF +#define MEMBERSOF(x) (sizeof(x)/sizeof(x[0])) +#endif + +static const struct response_class response_classes[] = { + /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases }, + /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases }, + /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases }, + /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases }, + /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases } +}; + +static const char * +evhttp_response_phrase_internal(int code) +{ + int klass = code / 100 - 1; + int subcode = code % 100; + + /* Unknown class - can't do any better here */ + if (klass < 0 || klass >= (int) MEMBERSOF(response_classes)) + return "Unknown Status Class"; + + /* Unknown sub-code, return class name at least */ + if (subcode >= (int) response_classes[klass].num_responses) + return response_classes[klass].name; + + return response_classes[klass].responses[subcode]; +} + +void +evhttp_response_code(struct evhttp_request *req, int code, const char *reason) +{ + req->kind = EVHTTP_RESPONSE; + req->response_code = code; + if (req->response_code_line != NULL) + mm_free(req->response_code_line); + if (reason == NULL) + reason = evhttp_response_phrase_internal(code); + req->response_code_line = mm_strdup(reason); + if (req->response_code_line == NULL) { + event_warn("%s: strdup", __func__); + /* XXX what else can we do? */ + } +} + +void +evhttp_send_page(struct evhttp_request *req, struct evbuffer *databuf) +{ + if (!req->major || !req->minor) { + req->major = 1; + req->minor = 1; + } + + if (req->kind != EVHTTP_RESPONSE) + evhttp_response_code(req, 200, "OK"); + + evhttp_clear_headers(req->output_headers); + evhttp_add_header(req->output_headers, "Content-Type", "text/html"); + evhttp_add_header(req->output_headers, "Connection", "close"); + + evhttp_send(req, databuf); +} + +static const char uri_chars[256] = { + /* 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, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + /* 64 */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, + /* 128 */ + 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, 0, + /* 192 */ + 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, 0, +}; + +#define CHAR_IS_UNRESERVED(c) \ + (uri_chars[(unsigned char)(c)]) + +/* + * Helper functions to encode/decode a string for inclusion in a URI. + * The returned string must be freed by the caller. + */ +char * +evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus) +{ + struct evbuffer *buf = evbuffer_new(); + const char *p, *end; + char *result; + + if (buf == NULL) + return (NULL); + + if (len >= 0) + end = uri+len; + else + end = uri+strlen(uri); + + for (p = uri; p < end; p++) { + if (CHAR_IS_UNRESERVED(*p)) { + evbuffer_add(buf, p, 1); + } else if (*p == ' ' && space_as_plus) { + evbuffer_add(buf, "+", 1); + } else { + evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p)); + } + } + evbuffer_add(buf, "", 1); /* NUL-terminator. */ + result = mm_malloc(evbuffer_get_length(buf)); + if (!result) + return NULL; + evbuffer_remove(buf, result, evbuffer_get_length(buf)); + evbuffer_free(buf); + + return (result); +} + +char * +evhttp_encode_uri(const char *str) +{ + return evhttp_uriencode(str, -1, 0); +} + +/* + * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't. + * If -1, when true we transform plus to space only after we've seen + * a ?. -1 is deprecated. + * @return the number of bytes written to 'ret'. + */ +static int +evhttp_decode_uri_internal( + const char *uri, size_t length, char *ret, int decode_plus_ctl) +{ + char c; + int j; + int decode_plus = (decode_plus_ctl == 1) ? 1: 0; + unsigned i; + + for (i = j = 0; i < length; i++) { + c = uri[i]; + if (c == '?') { + if (decode_plus_ctl < 0) + decode_plus = 1; + } else if (c == '+' && decode_plus) { + c = ' '; + } else if (c == '%' && EVUTIL_ISXDIGIT(uri[i+1]) && + EVUTIL_ISXDIGIT(uri[i+2])) { + char tmp[3]; + tmp[0] = uri[i+1]; + tmp[1] = uri[i+2]; + tmp[2] = '\0'; + c = (char)strtol(tmp, NULL, 16); + i += 2; + } + ret[j++] = c; + } + ret[j] = '\0'; + + return (j); +} + +/* deprecated */ +char * +evhttp_decode_uri(const char *uri) +{ + char *ret; + + if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) { + event_warn("%s: malloc(%lu)", __func__, + (unsigned long)(strlen(uri) + 1)); + return (NULL); + } + + evhttp_decode_uri_internal(uri, strlen(uri), + ret, -1 /*always_decode_plus*/); + + return (ret); +} + +char * +evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out) +{ + char *ret; + int n; + + if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) { + event_warn("%s: malloc(%lu)", __func__, + (unsigned long)(strlen(uri) + 1)); + return (NULL); + } + + n = evhttp_decode_uri_internal(uri, strlen(uri), + ret, !!decode_plus/*always_decode_plus*/); + + if (size_out) { + EVUTIL_ASSERT(n >= 0); + *size_out = (size_t)n; + } + + return (ret); +} + +/* + * Helper function to parse out arguments in a query. + * The arguments are separated by key and value. + */ + +static int +evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers, + int is_whole_uri) +{ + char *line=NULL; + char *argument; + char *p; + const char *query_part; + int result = -1; + struct evhttp_uri *uri=NULL; + + TAILQ_INIT(headers); + + if (is_whole_uri) { + uri = evhttp_uri_parse(str); + if (!uri) + goto error; + query_part = evhttp_uri_get_query(uri); + } else { + query_part = str; + } + + /* No arguments - we are done */ + if (!query_part || !strlen(query_part)) { + result = 0; + goto done; + } + + if ((line = mm_strdup(query_part)) == NULL) { + event_warn("%s: strdup", __func__); + goto error; + } + + p = argument = line; + while (p != NULL && *p != '\0') { + char *key, *value, *decoded_value; + argument = strsep(&p, "&"); + + value = argument; + key = strsep(&value, "="); + if (value == NULL || *key == '\0') { + goto error; + } + + if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) { + event_warn("%s: mm_malloc", __func__); + goto error; + } + evhttp_decode_uri_internal(value, strlen(value), + decoded_value, 1 /*always_decode_plus*/); + event_debug(("Query Param: %s -> %s\n", key, decoded_value)); + evhttp_add_header_internal(headers, key, decoded_value); + mm_free(decoded_value); + } + + result = 0; + goto done; +error: + evhttp_clear_headers(headers); +done: + if (line) + mm_free(line); + if (uri) + evhttp_uri_free(uri); + return result; +} + +int +evhttp_parse_query(const char *uri, struct evkeyvalq *headers) +{ + return evhttp_parse_query_impl(uri, headers, 1); +} +int +evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers) +{ + return evhttp_parse_query_impl(uri, headers, 0); +} + +static struct evhttp_cb * +evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req) +{ + struct evhttp_cb *cb; + size_t offset = 0; + char *translated; + const char *path; + + /* Test for different URLs */ + path = evhttp_uri_get_path(req->uri_elems); + offset = strlen(path); + if ((translated = mm_malloc(offset + 1)) == NULL) + return (NULL); + evhttp_decode_uri_internal(path, offset, translated, + 0 /* decode_plus */); + + TAILQ_FOREACH(cb, callbacks, next) { + if (!strcmp(cb->what, translated)) { + mm_free(translated); + return (cb); + } + } + + mm_free(translated); + return (NULL); +} + + +static int +prefix_suffix_match(const char *pattern, const char *name, int ignorecase) +{ + char c; + + while (1) { + switch (c = *pattern++) { + case '\0': + return *name == '\0'; + + case '*': + while (*name != '\0') { + if (prefix_suffix_match(pattern, name, + ignorecase)) + return (1); + ++name; + } + return (0); + default: + if (c != *name) { + if (!ignorecase || + EVUTIL_TOLOWER(c) != EVUTIL_TOLOWER(*name)) + return (0); + } + ++name; + } + } + /* NOTREACHED */ +} + +/* + Search the vhost hierarchy beginning with http for a server alias + matching hostname. If a match is found, and outhttp is non-null, + outhttp is set to the matching http object and 1 is returned. +*/ + +static int +evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp, + const char *hostname) +{ + struct evhttp_server_alias *alias; + struct evhttp *vhost; + + TAILQ_FOREACH(alias, &http->aliases, next) { + /* XXX Do we need to handle IP addresses? */ + if (!evutil_ascii_strcasecmp(alias->alias, hostname)) { + if (outhttp) + *outhttp = http; + return 1; + } + } + + /* XXX It might be good to avoid recursion here, but I don't + see a way to do that w/o a list. */ + TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) { + if (evhttp_find_alias(vhost, outhttp, hostname)) + return 1; + } + + return 0; +} + +/* + Attempts to find the best http object to handle a request for a hostname. + All aliases for the root http object and vhosts are searched for an exact + match. Then, the vhost hierarchy is traversed again for a matching + pattern. + + If an alias or vhost is matched, 1 is returned, and outhttp, if non-null, + is set with the best matching http object. If there are no matches, the + root http object is stored in outhttp and 0 is returned. +*/ + +static int +evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp, + const char *hostname) +{ + struct evhttp *vhost; + struct evhttp *oldhttp; + int match_found = 0; + + if (evhttp_find_alias(http, outhttp, hostname)) + return 1; + + do { + oldhttp = http; + TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) { + if (prefix_suffix_match(vhost->vhost_pattern, + hostname, 1 /* ignorecase */)) { + http = vhost; + match_found = 1; + break; + } + } + } while (oldhttp != http); + + if (outhttp) + *outhttp = http; + + return match_found; +} + +static void +evhttp_handle_request(struct evhttp_request *req, void *arg) +{ + struct evhttp *http = arg; + struct evhttp_cb *cb = NULL; + const char *hostname; + + /* we have a new request on which the user needs to take action */ + req->userdone = 0; + + if (req->type == 0 || req->uri == NULL) { + evhttp_send_error(req, HTTP_BADREQUEST, NULL); + return; + } + + if ((http->allowed_methods & req->type) == 0) { + event_debug(("Rejecting disallowed method %x (allowed: %x)\n", + (unsigned)req->type, (unsigned)http->allowed_methods)); + evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL); + return; + } + + /* handle potential virtual hosts */ + hostname = evhttp_request_get_host(req); + if (hostname != NULL) { + evhttp_find_vhost(http, &http, hostname); + } + + if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) { + (*cb->cb)(req, cb->cbarg); + return; + } + + /* Generic call back */ + if (http->gencb) { + (*http->gencb)(req, http->gencbarg); + return; + } else { + /* We need to send a 404 here */ +#define ERR_FORMAT "" \ + "404 Not Found" \ + "" \ + "

Not Found

" \ + "

The requested URL %s was not found on this server.

"\ + "\n" + + char *escaped_html; + struct evbuffer *buf; + + if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) { + evhttp_connection_free(req->evcon); + return; + } + + if ((buf = evbuffer_new()) == NULL) { + mm_free(escaped_html); + evhttp_connection_free(req->evcon); + return; + } + + evhttp_response_code(req, HTTP_NOTFOUND, "Not Found"); + + evbuffer_add_printf(buf, ERR_FORMAT, escaped_html); + + mm_free(escaped_html); + + evhttp_send_page(req, buf); + + evbuffer_free(buf); +#undef ERR_FORMAT + } +} + +/* Listener callback when a connection arrives at a server. */ +static void +accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg) +{ + struct evhttp *http = arg; + + evhttp_get_request(http, nfd, peer_sa, peer_socklen); +} + +int +evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port) +{ + struct evhttp_bound_socket *bound = + evhttp_bind_socket_with_handle(http, address, port); + if (bound == NULL) + return (-1); + return (0); +} + +struct evhttp_bound_socket * +evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port) +{ + evutil_socket_t fd; + struct evhttp_bound_socket *bound; + + if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1) + return (NULL); + + if (listen(fd, 128) == -1) { + event_sock_warn(fd, "%s: listen", __func__); + evutil_closesocket(fd); + return (NULL); + } + + bound = evhttp_accept_socket_with_handle(http, fd); + + if (bound != NULL) { + event_debug(("Bound to port %d - Awaiting connections ... ", + port)); + return (bound); + } + + return (NULL); +} + +int +evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd) +{ + struct evhttp_bound_socket *bound = + evhttp_accept_socket_with_handle(http, fd); + if (bound == NULL) + return (-1); + return (0); +} + + +struct evhttp_bound_socket * +evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd) +{ + struct evhttp_bound_socket *bound; + struct evconnlistener *listener; + const int flags = + LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE; + + listener = evconnlistener_new(http->base, NULL, NULL, + flags, + 0, /* Backlog is '0' because we already said 'listen' */ + fd); + if (!listener) + return (NULL); + + bound = evhttp_bind_listener(http, listener); + if (!bound) { + evconnlistener_free(listener); + return (NULL); + } + return (bound); +} + +struct evhttp_bound_socket * +evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener) +{ + struct evhttp_bound_socket *bound; + + bound = mm_malloc(sizeof(struct evhttp_bound_socket)); + if (bound == NULL) + return (NULL); + + bound->listener = listener; + TAILQ_INSERT_TAIL(&http->sockets, bound, next); + + evconnlistener_set_cb(listener, accept_socket_cb, http); + return bound; +} + +evutil_socket_t +evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound) +{ + return evconnlistener_get_fd(bound->listener); +} + +struct evconnlistener * +evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound) +{ + return bound->listener; +} + +void +evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound) +{ + TAILQ_REMOVE(&http->sockets, bound, next); + evconnlistener_free(bound->listener); + mm_free(bound); +} + +static struct evhttp* +evhttp_new_object(void) +{ + struct evhttp *http = NULL; + + if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) { + event_warn("%s: calloc", __func__); + return (NULL); + } + + http->timeout = -1; + evhttp_set_max_headers_size(http, EV_SIZE_MAX); + evhttp_set_max_body_size(http, EV_SIZE_MAX); + evhttp_set_allowed_methods(http, + EVHTTP_REQ_GET | + EVHTTP_REQ_POST | + EVHTTP_REQ_HEAD | + EVHTTP_REQ_PUT | + EVHTTP_REQ_DELETE); + + TAILQ_INIT(&http->sockets); + TAILQ_INIT(&http->callbacks); + TAILQ_INIT(&http->connections); + TAILQ_INIT(&http->virtualhosts); + TAILQ_INIT(&http->aliases); + + return (http); +} + +struct evhttp * +evhttp_new(struct event_base *base) +{ + struct evhttp *http = NULL; + + http = evhttp_new_object(); + if (http == NULL) + return (NULL); + http->base = base; + + return (http); +} + +/* + * Start a web server on the specified address and port. + */ + +struct evhttp * +evhttp_start(const char *address, unsigned short port) +{ + struct evhttp *http = NULL; + + http = evhttp_new_object(); + if (http == NULL) + return (NULL); + if (evhttp_bind_socket(http, address, port) == -1) { + mm_free(http); + return (NULL); + } + + return (http); +} + +void +evhttp_free(struct evhttp* http) +{ + struct evhttp_cb *http_cb; + struct evhttp_connection *evcon; + struct evhttp_bound_socket *bound; + struct evhttp* vhost; + struct evhttp_server_alias *alias; + + /* Remove the accepting part */ + while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) { + TAILQ_REMOVE(&http->sockets, bound, next); + + evconnlistener_free(bound->listener); + + mm_free(bound); + } + + while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) { + /* evhttp_connection_free removes the connection */ + evhttp_connection_free(evcon); + } + + while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) { + TAILQ_REMOVE(&http->callbacks, http_cb, next); + mm_free(http_cb->what); + mm_free(http_cb); + } + + while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) { + TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost); + + evhttp_free(vhost); + } + + if (http->vhost_pattern != NULL) + mm_free(http->vhost_pattern); + + while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) { + TAILQ_REMOVE(&http->aliases, alias, next); + mm_free(alias->alias); + mm_free(alias); + } + + mm_free(http); +} + +int +evhttp_add_virtual_host(struct evhttp* http, const char *pattern, + struct evhttp* vhost) +{ + /* a vhost can only be a vhost once and should not have bound sockets */ + if (vhost->vhost_pattern != NULL || + TAILQ_FIRST(&vhost->sockets) != NULL) + return (-1); + + vhost->vhost_pattern = mm_strdup(pattern); + if (vhost->vhost_pattern == NULL) + return (-1); + + TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost); + + return (0); +} + +int +evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost) +{ + if (vhost->vhost_pattern == NULL) + return (-1); + + TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost); + + mm_free(vhost->vhost_pattern); + vhost->vhost_pattern = NULL; + + return (0); +} + +int +evhttp_add_server_alias(struct evhttp *http, const char *alias) +{ + struct evhttp_server_alias *evalias; + + evalias = mm_calloc(1, sizeof(*evalias)); + if (!evalias) + return -1; + + evalias->alias = mm_strdup(alias); + if (!evalias->alias) { + mm_free(evalias); + return -1; + } + + TAILQ_INSERT_TAIL(&http->aliases, evalias, next); + + return 0; +} + +int +evhttp_remove_server_alias(struct evhttp *http, const char *alias) +{ + struct evhttp_server_alias *evalias; + + TAILQ_FOREACH(evalias, &http->aliases, next) { + if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) { + TAILQ_REMOVE(&http->aliases, evalias, next); + mm_free(evalias->alias); + mm_free(evalias); + return 0; + } + } + + return -1; +} + +void +evhttp_set_timeout(struct evhttp* http, int timeout_in_secs) +{ + http->timeout = timeout_in_secs; +} + +void +evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size) +{ + if (max_headers_size < 0) + http->default_max_headers_size = EV_SIZE_MAX; + else + http->default_max_headers_size = max_headers_size; +} + +void +evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size) +{ + if (max_body_size < 0) + http->default_max_body_size = EV_UINT64_MAX; + else + http->default_max_body_size = max_body_size; +} + +void +evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods) +{ + http->allowed_methods = methods; +} + +int +evhttp_set_cb(struct evhttp *http, const char *uri, + void (*cb)(struct evhttp_request *, void *), void *cbarg) +{ + struct evhttp_cb *http_cb; + + TAILQ_FOREACH(http_cb, &http->callbacks, next) { + if (strcmp(http_cb->what, uri) == 0) + return (-1); + } + + if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) { + event_warn("%s: calloc", __func__); + return (-2); + } + + http_cb->what = mm_strdup(uri); + if (http_cb->what == NULL) { + event_warn("%s: strdup", __func__); + mm_free(http_cb); + return (-3); + } + http_cb->cb = cb; + http_cb->cbarg = cbarg; + + TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next); + + return (0); +} + +int +evhttp_del_cb(struct evhttp *http, const char *uri) +{ + struct evhttp_cb *http_cb; + + TAILQ_FOREACH(http_cb, &http->callbacks, next) { + if (strcmp(http_cb->what, uri) == 0) + break; + } + if (http_cb == NULL) + return (-1); + + TAILQ_REMOVE(&http->callbacks, http_cb, next); + mm_free(http_cb->what); + mm_free(http_cb); + + return (0); +} + +void +evhttp_set_gencb(struct evhttp *http, + void (*cb)(struct evhttp_request *, void *), void *cbarg) +{ + http->gencb = cb; + http->gencbarg = cbarg; +} + +/* + * Request related functions + */ + +struct evhttp_request * +evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg) +{ + struct evhttp_request *req = NULL; + + /* Allocate request structure */ + if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) { + event_warn("%s: calloc", __func__); + goto error; + } + + req->headers_size = 0; + req->body_size = 0; + + req->kind = EVHTTP_RESPONSE; + req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq)); + if (req->input_headers == NULL) { + event_warn("%s: calloc", __func__); + goto error; + } + TAILQ_INIT(req->input_headers); + + req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq)); + if (req->output_headers == NULL) { + event_warn("%s: calloc", __func__); + goto error; + } + TAILQ_INIT(req->output_headers); + + if ((req->input_buffer = evbuffer_new()) == NULL) { + event_warn("%s: evbuffer_new", __func__); + goto error; + } + + if ((req->output_buffer = evbuffer_new()) == NULL) { + event_warn("%s: evbuffer_new", __func__); + goto error; + } + + req->cb = cb; + req->cb_arg = arg; + + return (req); + + error: + if (req != NULL) + evhttp_request_free(req); + return (NULL); +} + +void +evhttp_request_free(struct evhttp_request *req) +{ + if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) { + req->flags |= EVHTTP_REQ_NEEDS_FREE; + return; + } + + if (req->remote_host != NULL) + mm_free(req->remote_host); + if (req->uri != NULL) + mm_free(req->uri); + if (req->uri_elems != NULL) + evhttp_uri_free(req->uri_elems); + if (req->response_code_line != NULL) + mm_free(req->response_code_line); + if (req->host_cache != NULL) + mm_free(req->host_cache); + + evhttp_clear_headers(req->input_headers); + mm_free(req->input_headers); + + evhttp_clear_headers(req->output_headers); + mm_free(req->output_headers); + + if (req->input_buffer != NULL) + evbuffer_free(req->input_buffer); + + if (req->output_buffer != NULL) + evbuffer_free(req->output_buffer); + + mm_free(req); +} + +void +evhttp_request_own(struct evhttp_request *req) +{ + req->flags |= EVHTTP_USER_OWNED; +} + +int +evhttp_request_is_owned(struct evhttp_request *req) +{ + return (req->flags & EVHTTP_USER_OWNED) != 0; +} + +struct evhttp_connection * +evhttp_request_get_connection(struct evhttp_request *req) +{ + return req->evcon; +} + +struct event_base * +evhttp_connection_get_base(struct evhttp_connection *conn) +{ + return conn->base; +} + +void +evhttp_request_set_chunked_cb(struct evhttp_request *req, + void (*cb)(struct evhttp_request *, void *)) +{ + req->chunk_cb = cb; +} + +/* + * Allows for inspection of the request URI + */ + +const char * +evhttp_request_get_uri(const struct evhttp_request *req) { + if (req->uri == NULL) + event_debug(("%s: request %p has no uri\n", __func__, req)); + return (req->uri); +} + +const struct evhttp_uri * +evhttp_request_get_evhttp_uri(const struct evhttp_request *req) { + if (req->uri_elems == NULL) + event_debug(("%s: request %p has no uri elems\n", + __func__, req)); + return (req->uri_elems); +} + +const char * +evhttp_request_get_host(struct evhttp_request *req) +{ + const char *host = NULL; + + if (req->host_cache) + return req->host_cache; + + if (req->uri_elems) + host = evhttp_uri_get_host(req->uri_elems); + if (!host && req->input_headers) { + const char *p; + size_t len; + + host = evhttp_find_header(req->input_headers, "Host"); + /* The Host: header may include a port. Remove it here + to be consistent with uri_elems case above. */ + if (host) { + p = host + strlen(host) - 1; + while (p > host && EVUTIL_ISDIGIT(*p)) + --p; + if (p > host && *p == ':') { + len = p - host; + req->host_cache = mm_malloc(len + 1); + if (!req->host_cache) { + event_warn("%s: malloc", __func__); + return NULL; + } + memcpy(req->host_cache, host, len); + req->host_cache[len] = '\0'; + host = req->host_cache; + } + } + } + + return host; +} + +enum evhttp_cmd_type +evhttp_request_get_command(const struct evhttp_request *req) { + return (req->type); +} + +int +evhttp_request_get_response_code(const struct evhttp_request *req) +{ + return req->response_code; +} + +/** Returns the input headers */ +struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req) +{ + return (req->input_headers); +} + +/** Returns the output headers */ +struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req) +{ + return (req->output_headers); +} + +/** Returns the input buffer */ +struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req) +{ + return (req->input_buffer); +} + +/** Returns the output buffer */ +struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req) +{ + return (req->output_buffer); +} + + +/* + * Takes a file descriptor to read a request from. + * The callback is executed once the whole request has been read. + */ + +static struct evhttp_connection* +evhttp_get_request_connection( + struct evhttp* http, + evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen) +{ + struct evhttp_connection *evcon; + char *hostname = NULL, *portname = NULL; + + name_from_addr(sa, salen, &hostname, &portname); + if (hostname == NULL || portname == NULL) { + if (hostname) mm_free(hostname); + if (portname) mm_free(portname); + return (NULL); + } + + event_debug(("%s: new request from %s:%s on %d\n", + __func__, hostname, portname, fd)); + + /* we need a connection object to put the http request on */ + evcon = evhttp_connection_base_new( + http->base, NULL, hostname, atoi(portname)); + mm_free(hostname); + mm_free(portname); + if (evcon == NULL) + return (NULL); + + evcon->max_headers_size = http->default_max_headers_size; + evcon->max_body_size = http->default_max_body_size; + + evcon->flags |= EVHTTP_CON_INCOMING; + evcon->state = EVCON_READING_FIRSTLINE; + + evcon->fd = fd; + + bufferevent_setfd(evcon->bufev, fd); + + return (evcon); +} + +static int +evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon) +{ + struct evhttp *http = evcon->http_server; + struct evhttp_request *req; + if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL) + return (-1); + + if ((req->remote_host = mm_strdup(evcon->address)) == NULL) { + event_warn("%s: strdup", __func__); + evhttp_request_free(req); + return (-1); + } + req->remote_port = evcon->port; + + req->evcon = evcon; /* the request ends up owning the connection */ + req->flags |= EVHTTP_REQ_OWN_CONNECTION; + + /* We did not present the request to the user user yet, so treat it as + * if the user was done with the request. This allows us to free the + * request on a persistent connection if the client drops it without + * sending a request. + */ + req->userdone = 1; + + TAILQ_INSERT_TAIL(&evcon->requests, req, next); + + req->kind = EVHTTP_REQUEST; + + + evhttp_start_read(evcon); + + return (0); +} + +static void +evhttp_get_request(struct evhttp *http, evutil_socket_t fd, + struct sockaddr *sa, ev_socklen_t salen) +{ + struct evhttp_connection *evcon; + + evcon = evhttp_get_request_connection(http, fd, sa, salen); + if (evcon == NULL) { + event_sock_warn(fd, "%s: cannot get connection on %d", __func__, fd); + evutil_closesocket(fd); + return; + } + + /* the timeout can be used by the server to close idle connections */ + if (http->timeout != -1) + evhttp_connection_set_timeout(evcon, http->timeout); + + /* + * if we want to accept more than one request on a connection, + * we need to know which http server it belongs to. + */ + evcon->http_server = http; + TAILQ_INSERT_TAIL(&http->connections, evcon, next); + + if (evhttp_associate_new_request_with_connection(evcon) == -1) + evhttp_connection_free(evcon); +} + + +/* + * Network helper functions that we do not want to export to the rest of + * the world. + */ + +static void +name_from_addr(struct sockaddr *sa, ev_socklen_t salen, + char **phost, char **pport) +{ + char ntop[NI_MAXHOST]; + char strport[NI_MAXSERV]; + int ni_result; + +#ifdef _EVENT_HAVE_GETNAMEINFO + ni_result = getnameinfo(sa, salen, + ntop, sizeof(ntop), strport, sizeof(strport), + NI_NUMERICHOST|NI_NUMERICSERV); + + if (ni_result != 0) { +#ifdef EAI_SYSTEM + /* Windows doesn't have an EAI_SYSTEM. */ + if (ni_result == EAI_SYSTEM) + event_err(1, "getnameinfo failed"); + else +#endif + event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result)); + return; + } +#else + ni_result = fake_getnameinfo(sa, salen, + ntop, sizeof(ntop), strport, sizeof(strport), + NI_NUMERICHOST|NI_NUMERICSERV); + if (ni_result != 0) + return; +#endif + + *phost = mm_strdup(ntop); + *pport = mm_strdup(strport); +} + +/* Create a non-blocking socket and bind it */ +/* todo: rename this function */ +static evutil_socket_t +bind_socket_ai(struct evutil_addrinfo *ai, int reuse) +{ + evutil_socket_t fd; + + int on = 1, r; + int serrno; + + /* Create listen socket */ + fd = socket(ai ? ai->ai_family : AF_INET, SOCK_STREAM, 0); + if (fd == -1) { + event_sock_warn(-1, "socket"); + return (-1); + } + + if (evutil_make_socket_nonblocking(fd) < 0) + goto out; + if (evutil_make_socket_closeonexec(fd) < 0) + goto out; + + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); + if (reuse) + evutil_make_listen_socket_reuseable(fd); + + if (ai != NULL) { + r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen); + if (r == -1) + goto out; + } + + return (fd); + + out: + serrno = EVUTIL_SOCKET_ERROR(); + evutil_closesocket(fd); + EVUTIL_SET_SOCKET_ERROR(serrno); + return (-1); +} + +static struct evutil_addrinfo * +make_addrinfo(const char *address, ev_uint16_t port) +{ + struct evutil_addrinfo *ai = NULL; + + struct evutil_addrinfo hints; + char strport[NI_MAXSERV]; + int ai_result; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + /* turn NULL hostname into INADDR_ANY, and skip looking up any address + * types we don't have an interface to connect to. */ + hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG; + evutil_snprintf(strport, sizeof(strport), "%d", port); + if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai)) + != 0) { + if (ai_result == EVUTIL_EAI_SYSTEM) + event_warn("getaddrinfo"); + else + event_warnx("getaddrinfo: %s", + evutil_gai_strerror(ai_result)); + return (NULL); + } + + return (ai); +} + +static evutil_socket_t +bind_socket(const char *address, ev_uint16_t port, int reuse) +{ + evutil_socket_t fd; + struct evutil_addrinfo *aitop = NULL; + + /* just create an unbound socket */ + if (address == NULL && port == 0) + return bind_socket_ai(NULL, 0); + + aitop = make_addrinfo(address, port); + + if (aitop == NULL) + return (-1); + + fd = bind_socket_ai(aitop, reuse); + + evutil_freeaddrinfo(aitop); + + return (fd); +} + +struct evhttp_uri { + unsigned flags; + char *scheme; /* scheme; e.g http, ftp etc */ + char *userinfo; /* userinfo (typically username:pass), or NULL */ + char *host; /* hostname, IP address, or NULL */ + int port; /* port, or zero */ + char *path; /* path, or "". */ + char *query; /* query, or NULL */ + char *fragment; /* fragment or NULL */ +}; + +struct evhttp_uri * +evhttp_uri_new(void) +{ + struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1); + if (uri) + uri->port = -1; + return uri; +} + +void +evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags) +{ + uri->flags = flags; +} + +/* Return true if the string starting at s and ending immediately before eos + * is a valid URI scheme according to RFC3986 + */ +static int +scheme_ok(const char *s, const char *eos) +{ + /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */ + EVUTIL_ASSERT(eos >= s); + if (s == eos) + return 0; + if (!EVUTIL_ISALPHA(*s)) + return 0; + while (++s < eos) { + if (! EVUTIL_ISALNUM(*s) && + *s != '+' && *s != '-' && *s != '.') + return 0; + } + return 1; +} + +#define SUBDELIMS "!$&'()*+,;=" + +/* Return true iff [s..eos) is a valid userinfo */ +static int +userinfo_ok(const char *s, const char *eos) +{ + while (s < eos) { + if (CHAR_IS_UNRESERVED(*s) || + strchr(SUBDELIMS, *s) || + *s == ':') + ++s; + else if (*s == '%' && s+2 < eos && + EVUTIL_ISXDIGIT(s[1]) && + EVUTIL_ISXDIGIT(s[2])) + s += 3; + else + return 0; + } + return 1; +} + +static int +regname_ok(const char *s, const char *eos) +{ + while (s && s eos || *s != '[' || *(eos-1) != ']') + return 0; + if (s[1] == 'v') { + /* IPvFuture, or junk. + "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) + */ + s += 2; /* skip [v */ + --eos; + if (!EVUTIL_ISXDIGIT(*s)) /*require at least one*/ + return 0; + while (s < eos && *s != '.') { + if (EVUTIL_ISXDIGIT(*s)) + ++s; + else + return 0; + } + if (*s != '.') + return 0; + ++s; + while (s < eos) { + if (CHAR_IS_UNRESERVED(*s) || + strchr(SUBDELIMS, *s) || + *s == ':') + ++s; + else + return 0; + } + return 2; + } else { + /* IPv6, or junk */ + char buf[64]; + ev_ssize_t n_chars = eos-s-2; + struct in6_addr in6; + if (n_chars >= 64) /* way too long */ + return 0; + memcpy(buf, s+1, n_chars); + buf[n_chars]='\0'; + return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0; + } +} + +static int +parse_authority(struct evhttp_uri *uri, char *s, char *eos) +{ + char *cp, *port; + EVUTIL_ASSERT(eos); + if (eos == s) { + uri->host = mm_strdup(""); + if (uri->host == NULL) { + event_warn("%s: strdup", __func__); + return -1; + } + return 0; + } + + /* Optionally, we start with "userinfo@" */ + + cp = strchr(s, '@'); + if (cp && cp < eos) { + if (! userinfo_ok(s,cp)) + return -1; + *cp++ = '\0'; + uri->userinfo = mm_strdup(s); + if (uri->userinfo == NULL) { + event_warn("%s: strdup", __func__); + return -1; + } + } else { + cp = s; + } + /* Optionally, we end with ":port" */ + for (port=eos-1; port >= cp && EVUTIL_ISDIGIT(*port); --port) + ; + if (port >= cp && *port == ':') { + if (port+1 == eos) /* Leave port unspecified; the RFC allows a + * nil port */ + uri->port = -1; + else if ((uri->port = parse_port(port+1, eos))<0) + return -1; + eos = port; + } + /* Now, cp..eos holds the "host" port, which can be an IPv4Address, + * an IP-Literal, or a reg-name */ + EVUTIL_ASSERT(eos >= cp); + if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') { + /* IPv6address, IP-Literal, or junk. */ + if (! bracket_addr_ok(cp, eos)) + return -1; + } else { + /* Make sure the host part is ok. */ + if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */ + return -1; + } + uri->host = mm_malloc(eos-cp+1); + if (uri->host == NULL) { + event_warn("%s: malloc", __func__); + return -1; + } + memcpy(uri->host, cp, eos-cp); + uri->host[eos-cp] = '\0'; + return 0; + +} + +static char * +end_of_authority(char *cp) +{ + while (*cp) { + if (*cp == '?' || *cp == '#' || *cp == '/') + return cp; + ++cp; + } + return cp; +} + +enum uri_part { + PART_PATH, + PART_QUERY, + PART_FRAGMENT +}; + +/* Return the character after the longest prefix of 'cp' that matches... + * *pchar / "/" if allow_qchars is false, or + * *(pchar / "/" / "?") if allow_qchars is true. + */ +static char * +end_of_path(char *cp, enum uri_part part, unsigned flags) +{ + if (flags & EVHTTP_URI_NONCONFORMANT) { + /* If NONCONFORMANT: + * Path is everything up to a # or ? or nul. + * Query is everything up a # or nul + * Fragment is everything up to a nul. + */ + switch (part) { + case PART_PATH: + while (*cp && *cp != '#' && *cp != '?') + ++cp; + break; + case PART_QUERY: + while (*cp && *cp != '#') + ++cp; + break; + case PART_FRAGMENT: + cp += strlen(cp); + break; + }; + return cp; + } + + while (*cp) { + if (CHAR_IS_UNRESERVED(*cp) || + strchr(SUBDELIMS, *cp) || + *cp == ':' || *cp == '@' || *cp == '/') + ++cp; + else if (*cp == '%' && EVUTIL_ISXDIGIT(cp[1]) && + EVUTIL_ISXDIGIT(cp[2])) + cp += 3; + else if (*cp == '?' && part != PART_PATH) + ++cp; + else + return cp; + } + return cp; +} + +static int +path_matches_noscheme(const char *cp) +{ + while (*cp) { + if (*cp == ':') + return 0; + else if (*cp == '/') + return 1; + ++cp; + } + return 1; +} + +struct evhttp_uri * +evhttp_uri_parse(const char *source_uri) +{ + return evhttp_uri_parse_with_flags(source_uri, 0); +} + +struct evhttp_uri * +evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags) +{ + char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL; + char *path = NULL, *fragment = NULL; + int got_authority = 0; + + struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri)); + if (uri == NULL) { + event_warn("%s: calloc", __func__); + goto err; + } + uri->port = -1; + uri->flags = flags; + + readbuf = mm_strdup(source_uri); + if (readbuf == NULL) { + event_warn("%s: strdup", __func__); + goto err; + } + + readp = readbuf; + token = NULL; + + /* We try to follow RFC3986 here as much as we can, and match + the productions + + URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] + + relative-ref = relative-part [ "?" query ] [ "#" fragment ] + */ + + /* 1. scheme: */ + token = strchr(readp, ':'); + if (token && scheme_ok(readp,token)) { + *token = '\0'; + uri->scheme = mm_strdup(readp); + if (uri->scheme == NULL) { + event_warn("%s: strdup", __func__); + goto err; + } + readp = token+1; /* eat : */ + } + + /* 2. Optionally, "//" then an 'authority' part. */ + if (readp[0]=='/' && readp[1] == '/') { + char *authority; + readp += 2; + authority = readp; + path = end_of_authority(readp); + if (parse_authority(uri, authority, path) < 0) + goto err; + readp = path; + got_authority = 1; + } + + /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty + */ + path = readp; + readp = end_of_path(path, PART_PATH, flags); + + /* Query */ + if (*readp == '?') { + *readp = '\0'; + ++readp; + query = readp; + readp = end_of_path(readp, PART_QUERY, flags); + } + /* fragment */ + if (*readp == '#') { + *readp = '\0'; + ++readp; + fragment = readp; + readp = end_of_path(readp, PART_FRAGMENT, flags); + } + if (*readp != '\0') { + goto err; + } + + /* These next two cases may be unreachable; I'm leaving them + * in to be defensive. */ + /* If you didn't get an authority, the path can't begin with "//" */ + if (!got_authority && path[0]=='/' && path[1]=='/') + goto err; + /* If you did get an authority, the path must begin with "/" or be + * empty. */ + if (got_authority && path[0] != '/' && path[0] != '\0') + goto err; + /* (End of maybe-unreachable cases) */ + + /* If there was no scheme, the first part of the path (if any) must + * have no colon in it. */ + if (! uri->scheme && !path_matches_noscheme(path)) + goto err; + + EVUTIL_ASSERT(path); + uri->path = mm_strdup(path); + if (uri->path == NULL) { + event_warn("%s: strdup", __func__); + goto err; + } + + if (query) { + uri->query = mm_strdup(query); + if (uri->query == NULL) { + event_warn("%s: strdup", __func__); + goto err; + } + } + if (fragment) { + uri->fragment = mm_strdup(fragment); + if (uri->fragment == NULL) { + event_warn("%s: strdup", __func__); + goto err; + } + } + + mm_free(readbuf); + + return uri; +err: + if (uri) + evhttp_uri_free(uri); + if (readbuf) + mm_free(readbuf); + return NULL; +} + +void +evhttp_uri_free(struct evhttp_uri *uri) +{ +#define _URI_FREE_STR(f) \ + if (uri->f) { \ + mm_free(uri->f); \ + } + + _URI_FREE_STR(scheme); + _URI_FREE_STR(userinfo); + _URI_FREE_STR(host); + _URI_FREE_STR(path); + _URI_FREE_STR(query); + _URI_FREE_STR(fragment); + + mm_free(uri); +#undef _URI_FREE_STR +} + +char * +evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit) +{ + struct evbuffer *tmp = 0; + size_t joined_size = 0; + char *output = NULL; + +#define _URI_ADD(f) evbuffer_add(tmp, uri->f, strlen(uri->f)) + + if (!uri || !buf || !limit) + return NULL; + + tmp = evbuffer_new(); + if (!tmp) + return NULL; + + if (uri->scheme) { + _URI_ADD(scheme); + evbuffer_add(tmp, ":", 1); + } + if (uri->host) { + evbuffer_add(tmp, "//", 2); + if (uri->userinfo) + evbuffer_add_printf(tmp,"%s@", uri->userinfo); + _URI_ADD(host); + if (uri->port >= 0) + evbuffer_add_printf(tmp,":%d", uri->port); + + if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0') + goto err; + } + + if (uri->path) + _URI_ADD(path); + + if (uri->query) { + evbuffer_add(tmp, "?", 1); + _URI_ADD(query); + } + + if (uri->fragment) { + evbuffer_add(tmp, "#", 1); + _URI_ADD(fragment); + } + + evbuffer_add(tmp, "\0", 1); /* NUL */ + + joined_size = evbuffer_get_length(tmp); + + if (joined_size > limit) { + /* It doesn't fit. */ + evbuffer_free(tmp); + return NULL; + } + evbuffer_remove(tmp, buf, joined_size); + + output = buf; +err: + evbuffer_free(tmp); + + return output; +#undef _URI_ADD +} + +const char * +evhttp_uri_get_scheme(const struct evhttp_uri *uri) +{ + return uri->scheme; +} +const char * +evhttp_uri_get_userinfo(const struct evhttp_uri *uri) +{ + return uri->userinfo; +} +const char * +evhttp_uri_get_host(const struct evhttp_uri *uri) +{ + return uri->host; +} +int +evhttp_uri_get_port(const struct evhttp_uri *uri) +{ + return uri->port; +} +const char * +evhttp_uri_get_path(const struct evhttp_uri *uri) +{ + return uri->path; +} +const char * +evhttp_uri_get_query(const struct evhttp_uri *uri) +{ + return uri->query; +} +const char * +evhttp_uri_get_fragment(const struct evhttp_uri *uri) +{ + return uri->fragment; +} + +#define _URI_SET_STR(f) do { \ + if (uri->f) \ + mm_free(uri->f); \ + if (f) { \ + if ((uri->f = mm_strdup(f)) == NULL) { \ + event_warn("%s: strdup()", __func__); \ + return -1; \ + } \ + } else { \ + uri->f = NULL; \ + } \ + } while(0) + +int +evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme) +{ + if (scheme && !scheme_ok(scheme, scheme+strlen(scheme))) + return -1; + + _URI_SET_STR(scheme); + return 0; +} +int +evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo) +{ + if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo))) + return -1; + _URI_SET_STR(userinfo); + return 0; +} +int +evhttp_uri_set_host(struct evhttp_uri *uri, const char *host) +{ + if (host) { + if (host[0] == '[') { + if (! bracket_addr_ok(host, host+strlen(host))) + return -1; + } else { + if (! regname_ok(host, host+strlen(host))) + return -1; + } + } + + _URI_SET_STR(host); + return 0; +} +int +evhttp_uri_set_port(struct evhttp_uri *uri, int port) +{ + if (port < -1) + return -1; + uri->port = port; + return 0; +} +#define end_of_cpath(cp,p,f) \ + ((const char*)(end_of_path(((char*)(cp)), (p), (f)))) + +int +evhttp_uri_set_path(struct evhttp_uri *uri, const char *path) +{ + if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path)) + return -1; + + _URI_SET_STR(path); + return 0; +} +int +evhttp_uri_set_query(struct evhttp_uri *uri, const char *query) +{ + if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query)) + return -1; + _URI_SET_STR(query); + return 0; +} +int +evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment) +{ + if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment)) + return -1; + _URI_SET_STR(fragment); + return 0; +} diff --git a/libevent/include/Makefile.am b/libevent/include/Makefile.am new file mode 100644 index 0000000..5153db2 --- /dev/null +++ b/libevent/include/Makefile.am @@ -0,0 +1,47 @@ +# include/Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + +AUTOMAKE_OPTIONS = foreign + +EVENT2_EXPORT = \ + event2/buffer.h \ + event2/buffer_compat.h \ + event2/bufferevent.h \ + event2/bufferevent_compat.h \ + event2/bufferevent_ssl.h \ + event2/bufferevent_struct.h \ + event2/dns.h \ + event2/dns_compat.h \ + event2/dns_struct.h \ + event2/event.h \ + event2/event_compat.h \ + event2/event_struct.h \ + event2/http.h \ + event2/http_compat.h \ + event2/http_struct.h \ + event2/keyvalq_struct.h \ + event2/listener.h \ + event2/rpc.h \ + event2/rpc_compat.h \ + event2/rpc_struct.h \ + event2/tag.h \ + event2/tag_compat.h \ + event2/thread.h \ + event2/util.h + +EXTRA_SRC = $(EVENT2_EXPORT) + +## Without the nobase_ prefixing, Automake would strip "event2/" from +## the source header filename to derive the installed header filename. +## With nobase_ the installed path is $(includedir)/event2/ev*.h. + +if INSTALL_LIBEVENT +nobase_include_HEADERS = $(EVENT2_EXPORT) +nobase_nodist_include_HEADERS = ./event2/event-config.h +else +noinst_HEADERS = $(EVENT2_EXPORT) +nodist_noinst_HEADERS = ./event2/event-config.h +endif diff --git a/libevent/include/Makefile.in b/libevent/include/Makefile.in new file mode 100644 index 0000000..bb9f6c6 --- /dev/null +++ b/libevent/include/Makefile.in @@ -0,0 +1,610 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# include/Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include +DIST_COMMON = $(am__nobase_include_HEADERS_DIST) \ + $(am__noinst_HEADERS_DIST) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__nobase_include_HEADERS_DIST = event2/buffer.h \ + event2/buffer_compat.h event2/bufferevent.h \ + event2/bufferevent_compat.h event2/bufferevent_ssl.h \ + event2/bufferevent_struct.h event2/dns.h event2/dns_compat.h \ + event2/dns_struct.h event2/event.h event2/event_compat.h \ + event2/event_struct.h event2/http.h event2/http_compat.h \ + event2/http_struct.h event2/keyvalq_struct.h event2/listener.h \ + event2/rpc.h event2/rpc_compat.h event2/rpc_struct.h \ + event2/tag.h event2/tag_compat.h event2/thread.h event2/util.h +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" +am__noinst_HEADERS_DIST = event2/buffer.h event2/buffer_compat.h \ + event2/bufferevent.h event2/bufferevent_compat.h \ + event2/bufferevent_ssl.h event2/bufferevent_struct.h \ + event2/dns.h event2/dns_compat.h event2/dns_struct.h \ + event2/event.h event2/event_compat.h event2/event_struct.h \ + event2/http.h event2/http_compat.h event2/http_struct.h \ + event2/keyvalq_struct.h event2/listener.h event2/rpc.h \ + event2/rpc_compat.h event2/rpc_struct.h event2/tag.h \ + event2/tag_compat.h event2/thread.h event2/util.h +HEADERS = $(nobase_include_HEADERS) $(nobase_nodist_include_HEADERS) \ + $(nodist_noinst_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EV_LIB_GDI = @EV_LIB_GDI@ +EV_LIB_WS32 = @EV_LIB_WS32@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBEVENT_GC_SECTIONS = @LIBEVENT_GC_SECTIONS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIBADD = @OPENSSL_LIBADD@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acx_pthread_config = @acx_pthread_config@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +EVENT2_EXPORT = \ + event2/buffer.h \ + event2/buffer_compat.h \ + event2/bufferevent.h \ + event2/bufferevent_compat.h \ + event2/bufferevent_ssl.h \ + event2/bufferevent_struct.h \ + event2/dns.h \ + event2/dns_compat.h \ + event2/dns_struct.h \ + event2/event.h \ + event2/event_compat.h \ + event2/event_struct.h \ + event2/http.h \ + event2/http_compat.h \ + event2/http_struct.h \ + event2/keyvalq_struct.h \ + event2/listener.h \ + event2/rpc.h \ + event2/rpc_compat.h \ + event2/rpc_struct.h \ + event2/tag.h \ + event2/tag_compat.h \ + event2/thread.h \ + event2/util.h + +EXTRA_SRC = $(EVENT2_EXPORT) +@INSTALL_LIBEVENT_TRUE@nobase_include_HEADERS = $(EVENT2_EXPORT) +@INSTALL_LIBEVENT_TRUE@nobase_nodist_include_HEADERS = ./event2/event-config.h +@INSTALL_LIBEVENT_FALSE@noinst_HEADERS = $(EVENT2_EXPORT) +@INSTALL_LIBEVENT_FALSE@nodist_noinst_HEADERS = ./event2/event-config.h +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-nobase_includeHEADERS: $(nobase_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) +install-nobase_nodist_includeHEADERS: $(nobase_nodist_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_nodist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-nobase_includeHEADERS \ + install-nobase_nodist_includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-nobase_includeHEADERS \ + uninstall-nobase_nodist_includeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool cscopelist ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-nobase_includeHEADERS \ + install-nobase_nodist_includeHEADERS install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-nobase_includeHEADERS \ + uninstall-nobase_nodist_includeHEADERS + + +# 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/libevent/include/event2/buffer.h b/libevent/include/event2/buffer.h new file mode 100644 index 0000000..16236c4 --- /dev/null +++ b/libevent/include/event2/buffer.h @@ -0,0 +1,838 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_BUFFER_H_ +#define _EVENT2_BUFFER_H_ + +/** @file event2/buffer.h + + Functions for buffering data for network sending or receiving. + + An evbuffer can be used for preparing data before sending it to + the network or conversely for reading data from the network. + Evbuffers try to avoid memory copies as much as possible. As a + result, evbuffers can be used to pass data around without actually + incurring the overhead of copying the data. + + A new evbuffer can be allocated with evbuffer_new(), and can be + freed with evbuffer_free(). Most users will be using evbuffers via + the bufferevent interface. To access a bufferevent's evbuffers, use + bufferevent_get_input() and bufferevent_get_output(). + + There are several guidelines for using evbuffers. + + - if you already know how much data you are going to add as a result + of calling evbuffer_add() multiple times, it makes sense to use + evbuffer_expand() first to make sure that enough memory is allocated + before hand. + + - evbuffer_add_buffer() adds the contents of one buffer to the other + without incurring any unnecessary memory copies. + + - evbuffer_add() and evbuffer_add_buffer() do not mix very well: + if you use them, you will wind up with fragmented memory in your + buffer. + + - For high-performance code, you may want to avoid copying data into and out + of buffers. You can skip the copy step by using + evbuffer_reserve_space()/evbuffer_commit_space() when writing into a + buffer, and evbuffer_peek() when reading. + + In Libevent 2.0 and later, evbuffers are represented using a linked + list of memory chunks, with pointers to the first and last chunk in + the chain. + + As the contents of an evbuffer can be stored in multiple different + memory blocks, it cannot be accessed directly. Instead, evbuffer_pullup() + can be used to force a specified number of bytes to be contiguous. This + will cause memory reallocation and memory copies if the data is split + across multiple blocks. It is more efficient, however, to use + evbuffer_peek() if you don't require that the memory to be contiguous. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_UIO_H +#include +#endif +#include + +/** + An evbuffer is an opaque data type for efficiently buffering data to be + sent or received on the network. + + @see event2/event.h for more information +*/ +struct evbuffer +#ifdef _EVENT_IN_DOXYGEN +{} +#endif +; + +/** + Pointer to a position within an evbuffer. + + Used when repeatedly searching through a buffer. Calling any function + that modifies or re-packs the buffer contents may invalidate all + evbuffer_ptrs for that buffer. Do not modify these values except with + evbuffer_ptr_set. + */ +struct evbuffer_ptr { + ev_ssize_t pos; + + /* Do not alter the values of fields. */ + struct { + void *chain; + size_t pos_in_chain; + } _internal; +}; + +/** Describes a single extent of memory inside an evbuffer. Used for + direct-access functions. + + @see evbuffer_reserve_space, evbuffer_commit_space, evbuffer_peek + */ +#ifdef _EVENT_HAVE_SYS_UIO_H +#define evbuffer_iovec iovec +/* Internal use -- defined only if we are using the native struct iovec */ +#define _EVBUFFER_IOVEC_IS_NATIVE +#else +struct evbuffer_iovec { + /** The start of the extent of memory. */ + void *iov_base; + /** The length of the extent of memory. */ + size_t iov_len; +}; +#endif + +/** + Allocate storage for a new evbuffer. + + @return a pointer to a newly allocated evbuffer struct, or NULL if an error + occurred + */ +struct evbuffer *evbuffer_new(void); +/** + Deallocate storage for an evbuffer. + + @param buf pointer to the evbuffer to be freed + */ +void evbuffer_free(struct evbuffer *buf); + +/** + Enable locking on an evbuffer so that it can safely be used by multiple + threads at the same time. + + NOTE: when locking is enabled, the lock will be held when callbacks are + invoked. This could result in deadlock if you aren't careful. Plan + accordingly! + + @param buf An evbuffer to make lockable. + @param lock A lock object, or NULL if we should allocate our own. + @return 0 on success, -1 on failure. + */ +int evbuffer_enable_locking(struct evbuffer *buf, void *lock); + +/** + Acquire the lock on an evbuffer. Has no effect if locking was not enabled + with evbuffer_enable_locking. +*/ +void evbuffer_lock(struct evbuffer *buf); + +/** + Release the lock on an evbuffer. Has no effect if locking was not enabled + with evbuffer_enable_locking. +*/ +void evbuffer_unlock(struct evbuffer *buf); + + +/** If this flag is set, then we will not use evbuffer_peek(), + * evbuffer_remove(), evbuffer_remove_buffer(), and so on to read bytes + * from this buffer: we'll only take bytes out of this buffer by + * writing them to the network (as with evbuffer_write_atmost), by + * removing them without observing them (as with evbuffer_drain), + * or by copying them all out at once (as with evbuffer_add_buffer). + * + * Using this option allows the implementation to use sendfile-based + * operations for evbuffer_add_file(); see that function for more + * information. + * + * This flag is on by default for bufferevents that can take advantage + * of it; you should never actually need to set it on a bufferevent's + * output buffer. + */ +#define EVBUFFER_FLAG_DRAINS_TO_FD 1 + +/** Change the flags that are set for an evbuffer by adding more. + * + * @param buffer the evbuffer that the callback is watching. + * @param cb the callback whose status we want to change. + * @param flags One or more EVBUFFER_FLAG_* options + * @return 0 on success, -1 on failure. + */ +int evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags); +/** Change the flags that are set for an evbuffer by removing some. + * + * @param buffer the evbuffer that the callback is watching. + * @param cb the callback whose status we want to change. + * @param flags One or more EVBUFFER_FLAG_* options + * @return 0 on success, -1 on failure. + */ +int evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags); + +/** + Returns the total number of bytes stored in the evbuffer + + @param buf pointer to the evbuffer + @return the number of bytes stored in the evbuffer +*/ +size_t evbuffer_get_length(const struct evbuffer *buf); + +/** + Returns the number of contiguous available bytes in the first buffer chain. + + This is useful when processing data that might be split into multiple + chains, or that might all be in the first chain. Calls to + evbuffer_pullup() that cause reallocation and copying of data can thus be + avoided. + + @param buf pointer to the evbuffer + @return 0 if no data is available, otherwise the number of available bytes + in the first buffer chain. +*/ +size_t evbuffer_get_contiguous_space(const struct evbuffer *buf); + +/** + Expands the available space in an evbuffer. + + Expands the available space in the evbuffer to at least datlen, so that + appending datlen additional bytes will not require any new allocations. + + @param buf the evbuffer to be expanded + @param datlen the new minimum length requirement + @return 0 if successful, or -1 if an error occurred +*/ +int evbuffer_expand(struct evbuffer *buf, size_t datlen); + +/** + Reserves space in the last chain or chains of an evbuffer. + + Makes space available in the last chain or chains of an evbuffer that can + be arbitrarily written to by a user. The space does not become + available for reading until it has been committed with + evbuffer_commit_space(). + + The space is made available as one or more extents, represented by + an initial pointer and a length. You can force the memory to be + available as only one extent. Allowing more extents, however, makes the + function more efficient. + + Multiple subsequent calls to this function will make the same space + available until evbuffer_commit_space() has been called. + + It is an error to do anything that moves around the buffer's internal + memory structures before committing the space. + + NOTE: The code currently does not ever use more than two extents. + This may change in future versions. + + @param buf the evbuffer in which to reserve space. + @param size how much space to make available, at minimum. The + total length of the extents may be greater than the requested + length. + @param vec an array of one or more evbuffer_iovec structures to + hold pointers to the reserved extents of memory. + @param n_vec The length of the vec array. Must be at least 1; + 2 is more efficient. + @return the number of provided extents, or -1 on error. + @see evbuffer_commit_space() +*/ +int +evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size, + struct evbuffer_iovec *vec, int n_vec); + +/** + Commits previously reserved space. + + Commits some of the space previously reserved with + evbuffer_reserve_space(). It then becomes available for reading. + + This function may return an error if the pointer in the extents do + not match those returned from evbuffer_reserve_space, or if data + has been added to the buffer since the space was reserved. + + If you want to commit less data than you got reserved space for, + modify the iov_len pointer of the appropriate extent to a smaller + value. Note that you may have received more space than you + requested if it was available! + + @param buf the evbuffer in which to reserve space. + @param vec one or two extents returned by evbuffer_reserve_space. + @param n_vecs the number of extents. + @return 0 on success, -1 on error + @see evbuffer_reserve_space() +*/ +int evbuffer_commit_space(struct evbuffer *buf, + struct evbuffer_iovec *vec, int n_vecs); + +/** + Append data to the end of an evbuffer. + + @param buf the evbuffer to be appended to + @param data pointer to the beginning of the data buffer + @param datlen the number of bytes to be copied from the data buffer + @return 0 on success, -1 on failure. + */ +int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen); + + +/** + Read data from an evbuffer and drain the bytes read. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param data the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen); + +/** + Read data from an evbuffer, and leave the buffer unchanged. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param data_out the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen); + +/** + Read data from an evbuffer into another evbuffer, draining + the bytes from the source buffer. This function avoids copy + operations to the extent possible. + + If more bytes are requested than are available in src, the src + buffer is drained completely. + + @param src the evbuffer to be read from + @param dst the destination evbuffer to store the result into + @param datlen the maximum numbers of bytes to transfer + @return the number of bytes read + */ +int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst, + size_t datlen); + +/** Used to tell evbuffer_readln what kind of line-ending to look for. + */ +enum evbuffer_eol_style { + /** Any sequence of CR and LF characters is acceptable as an + * EOL. + * + * Note that this style can produce ambiguous results: the + * sequence "CRLF" will be treated as a single EOL if it is + * all in the buffer at once, but if you first read a CR from + * the network and later read an LF from the network, it will + * be treated as two EOLs. + */ + EVBUFFER_EOL_ANY, + /** An EOL is an LF, optionally preceded by a CR. This style is + * most useful for implementing text-based internet protocols. */ + EVBUFFER_EOL_CRLF, + /** An EOL is a CR followed by an LF. */ + EVBUFFER_EOL_CRLF_STRICT, + /** An EOL is a LF. */ + EVBUFFER_EOL_LF +}; + +/** + * Read a single line from an evbuffer. + * + * Reads a line terminated by an EOL as determined by the evbuffer_eol_style + * argument. Returns a newly allocated nul-terminated string; the caller must + * free the returned value. The EOL is not included in the returned string. + * + * @param buffer the evbuffer to read from + * @param n_read_out if non-NULL, points to a size_t that is set to the + * number of characters in the returned string. This is useful for + * strings that can contain NUL characters. + * @param eol_style the style of line-ending to use. + * @return pointer to a single line, or NULL if an error occurred + */ +char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, + enum evbuffer_eol_style eol_style); + +/** + Move all data from one evbuffer into another evbuffer. + + This is a destructive add. The data from one buffer moves into + the other buffer. However, no unnecessary memory copies occur. + + @param outbuf the output buffer + @param inbuf the input buffer + @return 0 if successful, or -1 if an error occurred + + @see evbuffer_remove_buffer() + */ +int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf); + +/** + A cleanup function for a piece of memory added to an evbuffer by + reference. + + @see evbuffer_add_reference() + */ +typedef void (*evbuffer_ref_cleanup_cb)(const void *data, + size_t datalen, void *extra); + +/** + Reference memory into an evbuffer without copying. + + The memory needs to remain valid until all the added data has been + read. This function keeps just a reference to the memory without + actually incurring the overhead of a copy. + + @param outbuf the output buffer + @param data the memory to reference + @param datlen how memory to reference + @param cleanupfn callback to be invoked when the memory is no longer + referenced by this evbuffer. + @param cleanupfn_arg optional argument to the cleanup callback + @return 0 if successful, or -1 if an error occurred + */ +int evbuffer_add_reference(struct evbuffer *outbuf, + const void *data, size_t datlen, + evbuffer_ref_cleanup_cb cleanupfn, void *cleanupfn_arg); + +/** + Copy data from a file into the evbuffer for writing to a socket. + + This function avoids unnecessary data copies between userland and + kernel. If sendfile is available and the EVBUFFER_FLAG_DRAINS_TO_FD + flag is set, it uses those functions. Otherwise, it tries to use + mmap (or CreateFileMapping on Windows). + + The function owns the resulting file descriptor and will close it + when finished transferring data. + + The results of using evbuffer_remove() or evbuffer_pullup() on + evbuffers whose data was added using this function are undefined. + + @param outbuf the output buffer + @param fd the file descriptor + @param offset the offset from which to read data + @param length how much data to read + @return 0 if successful, or -1 if an error occurred +*/ + +int evbuffer_add_file(struct evbuffer *outbuf, int fd, ev_off_t offset, + ev_off_t length); + +/** + Append a formatted string to the end of an evbuffer. + + The string is formated as printf. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ... arguments that will be passed to printf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + + @see evutil_printf(), evbuffer_add_vprintf() + */ +int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__((format(printf, 2, 3))) +#endif +; + +/** + Append a va_list formatted string to the end of an evbuffer. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ap a varargs va_list argument array that will be passed to vprintf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + */ +int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap); + + +/** + Remove a specified number of bytes data from the beginning of an evbuffer. + + @param buf the evbuffer to be drained + @param len the number of bytes to drain from the beginning of the buffer + @return 0 on success, -1 on failure. + */ +int evbuffer_drain(struct evbuffer *buf, size_t len); + + +/** + Write the contents of an evbuffer to a file descriptor. + + The evbuffer will be drained after the bytes have been successfully written. + + @param buffer the evbuffer to be written and drained + @param fd the file descriptor to be written to + @return the number of bytes written, or -1 if an error occurred + @see evbuffer_read() + */ +int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd); + +/** + Write some of the contents of an evbuffer to a file descriptor. + + The evbuffer will be drained after the bytes have been successfully written. + + @param buffer the evbuffer to be written and drained + @param fd the file descriptor to be written to + @param howmuch the largest allowable number of bytes to write, or -1 + to write as many bytes as we can. + @return the number of bytes written, or -1 if an error occurred + @see evbuffer_read() + */ +int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd, + ev_ssize_t howmuch); + +/** + Read from a file descriptor and store the result in an evbuffer. + + @param buffer the evbuffer to store the result + @param fd the file descriptor to read from + @param howmuch the number of bytes to be read + @return the number of bytes read, or -1 if an error occurred + @see evbuffer_write() + */ +int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch); + +/** + Search for a string within an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @param start NULL or a pointer to a valid struct evbuffer_ptr. + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence of the string in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start); + +/** + Search for a string within part of an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @param start NULL or a pointer to a valid struct evbuffer_ptr that + indicates where we should start searching. + @param end NULL or a pointer to a valid struct evbuffer_ptr that + indicates where we should stop searching. + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence of the string in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end); + +/** + Defines how to adjust an evbuffer_ptr by evbuffer_ptr_set() + + @see evbuffer_ptr_set() */ +enum evbuffer_ptr_how { + /** Sets the pointer to the position; can be called on with an + uninitialized evbuffer_ptr. */ + EVBUFFER_PTR_SET, + /** Advances the pointer by adding to the current position. */ + EVBUFFER_PTR_ADD +}; + +/** + Sets the search pointer in the buffer to position. + + If evbuffer_ptr is not initialized. This function can only be called + with EVBUFFER_PTR_SET. + + @param buffer the evbuffer to be search + @param ptr a pointer to a struct evbuffer_ptr + @param position the position at which to start the next search + @param how determines how the pointer should be manipulated. + @returns 0 on success or -1 otherwise +*/ +int +evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *ptr, + size_t position, enum evbuffer_ptr_how how); + +/** + Search for an end-of-line string within an evbuffer. + + @param buffer the evbuffer to be searched + @param start NULL or a pointer to a valid struct evbuffer_ptr to start + searching at. + @param eol_len_out If non-NULL, the pointed-to value will be set to + the length of the end-of-line string. + @param eol_style The kind of EOL to look for; see evbuffer_readln() for + more information + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence EOL in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer, + struct evbuffer_ptr *start, size_t *eol_len_out, + enum evbuffer_eol_style eol_style); + +/** Function to peek at data inside an evbuffer without removing it or + copying it out. + + Pointers to the data are returned by filling the 'vec_out' array + with pointers to one or more extents of data inside the buffer. + + The total data in the extents that you get back may be more than + you requested (if there is more data last extent than you asked + for), or less (if you do not provide enough evbuffer_iovecs, or if + the buffer does not have as much data as you asked to see). + + @param buffer the evbuffer to peek into, + @param len the number of bytes to try to peek. If len is negative, we + will try to fill as much of vec_out as we can. If len is negative + and vec_out is not provided, we return the number of evbuffer_iovecs + that would be needed to get all the data in the buffer. + @param start_at an evbuffer_ptr indicating the point at which we + should start looking for data. NULL means, "At the start of the + buffer." + @param vec_out an array of evbuffer_iovec + @param n_vec the length of vec_out. If 0, we only count how many + extents would be necessary to point to the requested amount of + data. + @return The number of extents needed. This may be less than n_vec + if we didn't need all the evbuffer_iovecs we were given, or more + than n_vec if we would need more to return all the data that was + requested. + */ +int evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len, + struct evbuffer_ptr *start_at, + struct evbuffer_iovec *vec_out, int n_vec); + + +/** Structure passed to an evbuffer_cb_func evbuffer callback + + @see evbuffer_cb_func, evbuffer_add_cb() + */ +struct evbuffer_cb_info { + /** The number of bytes in this evbuffer when callbacks were last + * invoked. */ + size_t orig_size; + /** The number of bytes added since callbacks were last invoked. */ + size_t n_added; + /** The number of bytes removed since callbacks were last invoked. */ + size_t n_deleted; +}; + +/** Type definition for a callback that is invoked whenever data is added or + removed from an evbuffer. + + An evbuffer may have one or more callbacks set at a time. The order + in which they are executed is undefined. + + A callback function may add more callbacks, or remove itself from the + list of callbacks, or add or remove data from the buffer. It may not + remove another callback from the list. + + If a callback adds or removes data from the buffer or from another + buffer, this can cause a recursive invocation of your callback or + other callbacks. If you ask for an infinite loop, you might just get + one: watch out! + + @param buffer the buffer whose size has changed + @param info a structure describing how the buffer changed. + @param arg a pointer to user data +*/ +typedef void (*evbuffer_cb_func)(struct evbuffer *buffer, const struct evbuffer_cb_info *info, void *arg); + +struct evbuffer_cb_entry; +/** Add a new callback to an evbuffer. + + Subsequent calls to evbuffer_add_cb() add new callbacks. To remove this + callback, call evbuffer_remove_cb or evbuffer_remove_cb_entry. + + @param buffer the evbuffer to be monitored + @param cb the callback function to invoke when the evbuffer is modified, + or NULL to remove all callbacks. + @param cbarg an argument to be provided to the callback function + @return a handle to the callback on success, or NULL on failure. + */ +struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg); + +/** Remove a callback from an evbuffer, given a handle returned from + evbuffer_add_cb. + + Calling this function invalidates the handle. + + @return 0 if a callback was removed, or -1 if no matching callback was + found. + */ +int evbuffer_remove_cb_entry(struct evbuffer *buffer, + struct evbuffer_cb_entry *ent); + +/** Remove a callback from an evbuffer, given the function and argument + used to add it. + + @return 0 if a callback was removed, or -1 if no matching callback was + found. + */ +int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg); + +/** If this flag is not set, then a callback is temporarily disabled, and + * should not be invoked. + * + * @see evbuffer_cb_set_flags(), evbuffer_cb_clear_flags() + */ +#define EVBUFFER_CB_ENABLED 1 + +/** Change the flags that are set for a callback on a buffer by adding more. + + @param buffer the evbuffer that the callback is watching. + @param cb the callback whose status we want to change. + @param flags EVBUFFER_CB_ENABLED to re-enable the callback. + @return 0 on success, -1 on failure. + */ +int evbuffer_cb_set_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags); + +/** Change the flags that are set for a callback on a buffer by removing some + + @param buffer the evbuffer that the callback is watching. + @param cb the callback whose status we want to change. + @param flags EVBUFFER_CB_ENABLED to disable the callback. + @return 0 on success, -1 on failure. + */ +int evbuffer_cb_clear_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags); + +#if 0 +/** Postpone calling a given callback until unsuspend is called later. + + This is different from disabling the callback, since the callback will get + invoked later if the buffer size changes between now and when we unsuspend + it. + + @param the buffer that the callback is watching. + @param cb the callback we want to suspend. + */ +void evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb); +/** Stop postponing a callback that we postponed with evbuffer_cb_suspend. + + If data was added to or removed from the buffer while the callback was + suspended, the callback will get called once now. + + @param the buffer that the callback is watching. + @param cb the callback we want to stop suspending. + */ +void evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb); +#endif + +/** + Makes the data at the begging of an evbuffer contiguous. + + @param buf the evbuffer to make contiguous + @param size the number of bytes to make contiguous, or -1 to make the + entire buffer contiguous. + @return a pointer to the contiguous memory array +*/ + +unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size); + +/** + Prepends data to the beginning of the evbuffer + + @param buf the evbuffer to which to prepend data + @param data a pointer to the memory to prepend + @param size the number of bytes to prepend + @return 0 if successful, or -1 otherwise +*/ + +int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size); + +/** + Prepends all data from the src evbuffer to the beginning of the dst + evbuffer. + + @param dst the evbuffer to which to prepend data + @param src the evbuffer to prepend; it will be emptied as a result + @return 0 if successful, or -1 otherwise +*/ +int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src); + +/** + Prevent calls that modify an evbuffer from succeeding. A buffer may + frozen at the front, at the back, or at both the front and the back. + + If the front of a buffer is frozen, operations that drain data from + the front of the buffer, or that prepend data to the buffer, will + fail until it is unfrozen. If the back a buffer is frozen, operations + that append data from the buffer will fail until it is unfrozen. + + @param buf The buffer to freeze + @param at_front If true, we freeze the front of the buffer. If false, + we freeze the back. + @return 0 on success, -1 on failure. +*/ +int evbuffer_freeze(struct evbuffer *buf, int at_front); +/** + Re-enable calls that modify an evbuffer. + + @param buf The buffer to un-freeze + @param at_front If true, we unfreeze the front of the buffer. If false, + we unfreeze the back. + @return 0 on success, -1 on failure. + */ +int evbuffer_unfreeze(struct evbuffer *buf, int at_front); + +struct event_base; +/** + Force all the callbacks on an evbuffer to be run, not immediately after + the evbuffer is altered, but instead from inside the event loop. + + This can be used to serialize all the callbacks to a single thread + of execution. + */ +int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_BUFFER_H_ */ diff --git a/libevent/include/event2/buffer_compat.h b/libevent/include/event2/buffer_compat.h new file mode 100644 index 0000000..a713ee3 --- /dev/null +++ b/libevent/include/event2/buffer_compat.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#ifndef _EVENT2_BUFFER_COMPAT_H_ +#define _EVENT2_BUFFER_COMPAT_H_ + +/** @file event2/buffer_compat.h + + Obsolete and deprecated versions of the functions in buffer.h: provided + only for backward compatibility. + */ + + +/** + Obsolete alias for evbuffer_readln(buffer, NULL, EOL_STYLE_ANY). + + @deprecated This function is deprecated because its behavior is not correct + for almost any protocol, and also because it's wholly subsumed by + evbuffer_readln(). + + @param buffer the evbuffer to read from + @return pointer to a single line, or NULL if an error occurred + +*/ +char *evbuffer_readline(struct evbuffer *buffer); + +/** Type definition for a callback that is invoked whenever data is added or + removed from an evbuffer. + + An evbuffer may have one or more callbacks set at a time. The order + in which they are executed is undefined. + + A callback function may add more callbacks, or remove itself from the + list of callbacks, or add or remove data from the buffer. It may not + remove another callback from the list. + + If a callback adds or removes data from the buffer or from another + buffer, this can cause a recursive invocation of your callback or + other callbacks. If you ask for an infinite loop, you might just get + one: watch out! + + @param buffer the buffer whose size has changed + @param old_len the previous length of the buffer + @param new_len the current length of the buffer + @param arg a pointer to user data +*/ +typedef void (*evbuffer_cb)(struct evbuffer *buffer, size_t old_len, size_t new_len, void *arg); + +/** + Replace all callbacks on an evbuffer with a single new callback, or + remove them. + + Subsequent calls to evbuffer_setcb() replace callbacks set by previous + calls. Setting the callback to NULL removes any previously set callback. + + @deprecated This function is deprecated because it clears all previous + callbacks set on the evbuffer, which can cause confusing behavior if + multiple parts of the code all want to add their own callbacks on a + buffer. Instead, use evbuffer_add(), evbuffer_del(), and + evbuffer_setflags() to manage your own evbuffer callbacks without + interfering with callbacks set by others. + + @param buffer the evbuffer to be monitored + @param cb the callback function to invoke when the evbuffer is modified, + or NULL to remove all callbacks. + @param cbarg an argument to be provided to the callback function + */ +void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg); + + +/** + Find a string within an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @return a pointer to the beginning of the search string, or NULL if the search failed. + */ +unsigned char *evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len); + +/** deprecated in favor of calling the functions directly */ +#define EVBUFFER_LENGTH(x) evbuffer_get_length(x) +/** deprecated in favor of calling the functions directly */ +#define EVBUFFER_DATA(x) evbuffer_pullup((x), -1) + +#endif + diff --git a/libevent/include/event2/bufferevent.h b/libevent/include/event2/bufferevent.h new file mode 100644 index 0000000..f3d8b1a --- /dev/null +++ b/libevent/include/event2/bufferevent.h @@ -0,0 +1,821 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_BUFFEREVENT_H_ +#define _EVENT2_BUFFEREVENT_H_ + +/** + @file event2/bufferevent.h + + Functions for buffering data for network sending or receiving. Bufferevents + are higher level than evbuffers: each has an underlying evbuffer for reading + and one for writing, and callbacks that are invoked under certain + circumstances. + + A bufferevent provides input and output buffers that get filled and + drained automatically. The user of a bufferevent no longer deals + directly with the I/O, but instead is reading from input and writing + to output buffers. + + Once initialized, the bufferevent structure can be used repeatedly + with bufferevent_enable() and bufferevent_disable(). + + When reading is enabled, the bufferevent will try to read from the + file descriptor onto its input buffer, and and call the read callback. + When writing is enabled, the bufferevent will try to write data onto its + file descriptor when writing is enabled, and call the write callback + when the output buffer is sufficiently drained. + + Bufferevents come in several flavors, including: + +
+
Socket-based bufferevents
+
A bufferevent that reads and writes data onto a network + socket. Created with bufferevent_socket_new().
+ +
Paired bufferevents
+
A pair of bufferevents that send and receive data to one + another without touching the network. Created with + bufferevent_pair_new().
+ +
Filtering bufferevents
+
A bufferevent that transforms data, and sends or receives it + over another underlying bufferevent. Created with + bufferevent_filter_new().
+ +
SSL-backed bufferevents
+
A bufferevent that uses the openssl library to send and + receive data over an encrypted connection. Created with + bufferevent_openssl_socket_new() or + bufferevent_openssl_filter_new().
+
+ */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** @name Bufferevent event codes + + These flags are passed as arguments to a bufferevent's event callback. + + @{ +*/ +#define BEV_EVENT_READING 0x01 /**< error encountered while reading */ +#define BEV_EVENT_WRITING 0x02 /**< error encountered while writing */ +#define BEV_EVENT_EOF 0x10 /**< eof file reached */ +#define BEV_EVENT_ERROR 0x20 /**< unrecoverable error encountered */ +#define BEV_EVENT_TIMEOUT 0x40 /**< user-specified timeout reached */ +#define BEV_EVENT_CONNECTED 0x80 /**< connect operation finished. */ +/**@}*/ + +/** + An opaque type for handling buffered IO + + @see event2/bufferevent.h + */ +struct bufferevent +#ifdef _EVENT_IN_DOXYGEN +{} +#endif +; +struct event_base; +struct evbuffer; +struct sockaddr; + +/** + A read or write callback for a bufferevent. + + The read callback is triggered when new data arrives in the input + buffer and the amount of readable data exceed the low watermark + which is 0 by default. + + The write callback is triggered if the write buffer has been + exhausted or fell below its low watermark. + + @param bev the bufferevent that triggered the callback + @param ctx the user-specified context for this bufferevent + */ +typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx); + +/** + An event/error callback for a bufferevent. + + The event callback is triggered if either an EOF condition or another + unrecoverable error was encountered. + + @param bev the bufferevent for which the error condition was reached + @param what a conjunction of flags: BEV_EVENT_READING or BEV_EVENT_WRITING + to indicate if the error was encountered on the read or write path, + and one of the following flags: BEV_EVENT_EOF, BEV_EVENT_ERROR, + BEV_EVENT_TIMEOUT, BEV_EVENT_CONNECTED. + + @param ctx the user-specified context for this bufferevent +*/ +typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short what, void *ctx); + +/** Options that can be specified when creating a bufferevent */ +enum bufferevent_options { + /** If set, we close the underlying file + * descriptor/bufferevent/whatever when this bufferevent is freed. */ + BEV_OPT_CLOSE_ON_FREE = (1<<0), + + /** If set, and threading is enabled, operations on this bufferevent + * are protected by a lock */ + BEV_OPT_THREADSAFE = (1<<1), + + /** If set, callbacks are run deferred in the event loop. */ + BEV_OPT_DEFER_CALLBACKS = (1<<2), + + /** If set, callbacks are executed without locks being held on the + * bufferevent. This option currently requires that + * BEV_OPT_DEFER_CALLBACKS also be set; a future version of Libevent + * might remove the requirement.*/ + BEV_OPT_UNLOCK_CALLBACKS = (1<<3) +}; + +/** + Create a new socket bufferevent over an existing socket. + + @param base the event base to associate with the new bufferevent. + @param fd the file descriptor from which data is read and written to. + This file descriptor is not allowed to be a pipe(2). + It is safe to set the fd to -1, so long as you later + set it with bufferevent_setfd or bufferevent_socket_connect(). + @param options Zero or more BEV_OPT_* flags + @return a pointer to a newly allocated bufferevent struct, or NULL if an + error occurred + @see bufferevent_free() + */ +struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options); + +/** + Launch a connect() attempt with a socket-based bufferevent. + + When the connect succeeds, the eventcb will be invoked with + BEV_EVENT_CONNECTED set. + + If the bufferevent does not already have a socket set, we allocate a new + socket here and make it nonblocking before we begin. + + If no address is provided, we assume that the socket is already connecting, + and configure the bufferevent so that a BEV_EVENT_CONNECTED event will be + yielded when it is done connecting. + + @param bufev an existing bufferevent allocated with + bufferevent_socket_new(). + @param addr the address we should connect to + @param socklen The length of the address + @return 0 on success, -1 on failure. + */ +int bufferevent_socket_connect(struct bufferevent *, struct sockaddr *, int); + +struct evdns_base; +/** + Resolve the hostname 'hostname' and connect to it as with + bufferevent_socket_connect(). + + @param bufev An existing bufferevent allocated with bufferevent_socket_new() + @param evdns_base Optionally, an evdns_base to use for resolving hostnames + asynchronously. May be set to NULL for a blocking resolve. + @param family A preferred address family to resolve addresses to, or + AF_UNSPEC for no preference. Only AF_INET, AF_INET6, and AF_UNSPEC are + supported. + @param hostname The hostname to resolve; see below for notes on recognized + formats + @param port The port to connect to on the resolved address. + @return 0 if successful, -1 on failure. + + Recognized hostname formats are: + + www.example.com (hostname) + 1.2.3.4 (ipv4address) + ::1 (ipv6address) + [::1] ([ipv6address]) + + Performance note: If you do not provide an evdns_base, this function + may block while it waits for a DNS response. This is probably not + what you want. + */ +int bufferevent_socket_connect_hostname(struct bufferevent *, + struct evdns_base *, int, const char *, int); + +/** + Return the error code for the last failed DNS lookup attempt made by + bufferevent_socket_connect_hostname(). + + @param bev The bufferevent object. + @return DNS error code. + @see evutil_gai_strerror() +*/ +int bufferevent_socket_get_dns_error(struct bufferevent *bev); + +/** + Assign a bufferevent to a specific event_base. + + NOTE that only socket bufferevents support this function. + + @param base an event_base returned by event_init() + @param bufev a bufferevent struct returned by bufferevent_new() + or bufferevent_socket_new() + @return 0 if successful, or -1 if an error occurred + @see bufferevent_new() + */ +int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev); + +/** + Return the event_base used by a bufferevent +*/ +struct event_base *bufferevent_get_base(struct bufferevent *bev); + +/** + Assign a priority to a bufferevent. + + Only supported for socket bufferevents. + + @param bufev a bufferevent struct + @param pri the priority to be assigned + @return 0 if successful, or -1 if an error occurred + */ +int bufferevent_priority_set(struct bufferevent *bufev, int pri); + + +/** + Deallocate the storage associated with a bufferevent structure. + + @param bufev the bufferevent structure to be freed. + */ +void bufferevent_free(struct bufferevent *bufev); + + +/** + Changes the callbacks for a bufferevent. + + @param bufev the bufferevent object for which to change callbacks + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param eventcb callback to invoke when there is an event on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @see bufferevent_new() + */ +void bufferevent_setcb(struct bufferevent *bufev, + bufferevent_data_cb readcb, bufferevent_data_cb writecb, + bufferevent_event_cb eventcb, void *cbarg); + +/** + Changes the file descriptor on which the bufferevent operates. + Not supported for all bufferevent types. + + @param bufev the bufferevent object for which to change the file descriptor + @param fd the file descriptor to operate on +*/ +int bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd); + +/** + Returns the file descriptor associated with a bufferevent, or -1 if + no file descriptor is associated with the bufferevent. + */ +evutil_socket_t bufferevent_getfd(struct bufferevent *bufev); + +/** + Returns the underlying bufferevent associated with a bufferevent (if + the bufferevent is a wrapper), or NULL if there is no underlying bufferevent. + */ +struct bufferevent *bufferevent_get_underlying(struct bufferevent *bufev); + +/** + Write data to a bufferevent buffer. + + The bufferevent_write() function can be used to write data to the file + descriptor. The data is appended to the output buffer and written to the + descriptor automatically as it becomes available for writing. + + @param bufev the bufferevent to be written to + @param data a pointer to the data to be written + @param size the length of the data, in bytes + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write_buffer() + */ +int bufferevent_write(struct bufferevent *bufev, + const void *data, size_t size); + + +/** + Write data from an evbuffer to a bufferevent buffer. The evbuffer is + being drained as a result. + + @param bufev the bufferevent to be written to + @param buf the evbuffer to be written + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write() + */ +int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf); + + +/** + Read data from a bufferevent buffer. + + The bufferevent_read() function is used to read data from the input buffer. + + @param bufev the bufferevent to be read from + @param data pointer to a buffer that will store the data + @param size the size of the data buffer, in bytes + @return the amount of data read, in bytes. + */ +size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); + +/** + Read data from a bufferevent buffer into an evbuffer. This avoids + memory copies. + + @param bufev the bufferevent to be read from + @param buf the evbuffer to which to add data + @return 0 if successful, or -1 if an error occurred. + */ +int bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf); + +/** + Returns the input buffer. + + The user MUST NOT set the callback on this buffer. + + @param bufev the bufferevent from which to get the evbuffer + @return the evbuffer object for the input buffer + */ + +struct evbuffer *bufferevent_get_input(struct bufferevent *bufev); + +/** + Returns the output buffer. + + The user MUST NOT set the callback on this buffer. + + When filters are being used, the filters need to be manually + triggered if the output buffer was manipulated. + + @param bufev the bufferevent from which to get the evbuffer + @return the evbuffer object for the output buffer + */ + +struct evbuffer *bufferevent_get_output(struct bufferevent *bufev); + +/** + Enable a bufferevent. + + @param bufev the bufferevent to be enabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_disable() + */ +int bufferevent_enable(struct bufferevent *bufev, short event); + +/** + Disable a bufferevent. + + @param bufev the bufferevent to be disabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_enable() + */ +int bufferevent_disable(struct bufferevent *bufev, short event); + +/** + Return the events that are enabled on a given bufferevent. + + @param bufev the bufferevent to inspect + @return A combination of EV_READ | EV_WRITE + */ +short bufferevent_get_enabled(struct bufferevent *bufev); + +/** + Set the read and write timeout for a bufferevent. + + A bufferevent's timeout will fire the first time that the indicated + amount of time has elapsed since a successful read or write operation, + during which the bufferevent was trying to read or write. + + (In other words, if reading or writing is disabled, or if the + bufferevent's read or write operation has been suspended because + there's no data to write, or not enough banwidth, or so on, the + timeout isn't active. The timeout only becomes active when we we're + willing to actually read or write.) + + Calling bufferevent_enable or setting a timeout for a bufferevent + whose timeout is already pending resets its timeout. + + If the timeout elapses, the corresponding operation (EV_READ or + EV_WRITE) becomes disabled until you re-enable it again. The + bufferevent's event callback is called with the + BEV_EVENT_TIMEOUT|BEV_EVENT_READING or + BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING. + + @param bufev the bufferevent to be modified + @param timeout_read the read timeout, or NULL + @param timeout_write the write timeout, or NULL + */ +int bufferevent_set_timeouts(struct bufferevent *bufev, + const struct timeval *timeout_read, const struct timeval *timeout_write); + +/** + Sets the watermarks for read and write events. + + On input, a bufferevent does not invoke the user read callback unless + there is at least low watermark data in the buffer. If the read buffer + is beyond the high watermark, the bufferevent stops reading from the network. + + On output, the user write callback is invoked whenever the buffered data + falls below the low watermark. Filters that write to this bufev will try + not to write more bytes to this buffer than the high watermark would allow, + except when flushing. + + @param bufev the bufferevent to be modified + @param events EV_READ, EV_WRITE or both + @param lowmark the lower watermark to set + @param highmark the high watermark to set +*/ + +void bufferevent_setwatermark(struct bufferevent *bufev, short events, + size_t lowmark, size_t highmark); + +/** + Acquire the lock on a bufferevent. Has no effect if locking was not + enabled with BEV_OPT_THREADSAFE. + */ +void bufferevent_lock(struct bufferevent *bufev); + +/** + Release the lock on a bufferevent. Has no effect if locking was not + enabled with BEV_OPT_THREADSAFE. + */ +void bufferevent_unlock(struct bufferevent *bufev); + +/** + Flags that can be passed into filters to let them know how to + deal with the incoming data. +*/ +enum bufferevent_flush_mode { + /** usually set when processing data */ + BEV_NORMAL = 0, + + /** want to checkpoint all data sent. */ + BEV_FLUSH = 1, + + /** encountered EOF on read or done sending data */ + BEV_FINISHED = 2 +}; + +/** + Triggers the bufferevent to produce more data if possible. + + @param bufev the bufferevent object + @param iotype either EV_READ or EV_WRITE or both. + @param mode either BEV_NORMAL or BEV_FLUSH or BEV_FINISHED + @return -1 on failure, 0 if no data was produces, 1 if data was produced + */ +int bufferevent_flush(struct bufferevent *bufev, + short iotype, + enum bufferevent_flush_mode mode); + +/** + @name Filtering support + + @{ +*/ +/** + Values that filters can return. + */ +enum bufferevent_filter_result { + /** everything is okay */ + BEV_OK = 0, + + /** the filter needs to read more data before output */ + BEV_NEED_MORE = 1, + + /** the filter encountered a critical error, no further data + can be processed. */ + BEV_ERROR = 2 +}; + +/** A callback function to implement a filter for a bufferevent. + + @param src An evbuffer to drain data from. + @param dst An evbuffer to add data to. + @param limit A suggested upper bound of bytes to write to dst. + The filter may ignore this value, but doing so means that + it will overflow the high-water mark associated with dst. + -1 means "no limit". + @param mode Whether we should write data as may be convenient + (BEV_NORMAL), or flush as much data as we can (BEV_FLUSH), + or flush as much as we can, possibly including an end-of-stream + marker (BEV_FINISH). + @param ctx A user-supplied pointer. + + @return BEV_OK if we wrote some data; BEV_NEED_MORE if we can't + produce any more output until we get some input; and BEV_ERROR + on an error. + */ +typedef enum bufferevent_filter_result (*bufferevent_filter_cb)( + struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit, + enum bufferevent_flush_mode mode, void *ctx); + +/** + Allocate a new filtering bufferevent on top of an existing bufferevent. + + @param underlying the underlying bufferevent. + @param input_filter The filter to apply to data we read from the underlying + bufferevent + @param output_filter The filer to apply to data we write to the underlying + bufferevent + @param options A bitfield of bufferevent options. + @param free_context A function to use to free the filter context when + this bufferevent is freed. + @param ctx A context pointer to pass to the filter functions. + */ +struct bufferevent * +bufferevent_filter_new(struct bufferevent *underlying, + bufferevent_filter_cb input_filter, + bufferevent_filter_cb output_filter, + int options, + void (*free_context)(void *), + void *ctx); +/**@}*/ + +/** + Allocate a pair of linked bufferevents. The bufferevents behave as would + two bufferevent_sock instances connected to opposite ends of a + socketpair(), except that no internal socketpair is allocated. + + @param base The event base to associate with the socketpair. + @param options A set of options for this bufferevent + @param pair A pointer to an array to hold the two new bufferevent objects. + @return 0 on success, -1 on failure. + */ +int bufferevent_pair_new(struct event_base *base, int options, + struct bufferevent *pair[2]); + +/** + Given one bufferevent returned by bufferevent_pair_new(), returns the + other one if it still exists. Otherwise returns NULL. + */ +struct bufferevent *bufferevent_pair_get_partner(struct bufferevent *bev); + +/** + Abstract type used to configure rate-limiting on a bufferevent or a group + of bufferevents. + */ +struct ev_token_bucket_cfg; + +/** + A group of bufferevents which are configured to respect the same rate + limit. +*/ +struct bufferevent_rate_limit_group; + +/** Maximum configurable rate- or burst-limit. */ +#define EV_RATE_LIMIT_MAX EV_SSIZE_MAX + +/** + Initialize and return a new object to configure the rate-limiting behavior + of bufferevents. + + @param read_rate The maximum number of bytes to read per tick on + average. + @param read_burst The maximum number of bytes to read in any single tick. + @param write_rate The maximum number of bytes to write per tick on + average. + @param write_burst The maximum number of bytes to write in any single tick. + @param tick_len The length of a single tick. Defaults to one second. + Any fractions of a millisecond are ignored. + + Note that all rate-limits hare are currently best-effort: future versions + of Libevent may implement them more tightly. + */ +struct ev_token_bucket_cfg *ev_token_bucket_cfg_new( + size_t read_rate, size_t read_burst, + size_t write_rate, size_t write_burst, + const struct timeval *tick_len); + +/** Free all storage held in 'cfg'. + + Note: 'cfg' is not currently reference-counted; it is not safe to free it + until no bufferevent is using it. + */ +void ev_token_bucket_cfg_free(struct ev_token_bucket_cfg *cfg); + +/** + Set the rate-limit of a the bufferevent 'bev' to the one specified in + 'cfg'. If 'cfg' is NULL, disable any per-bufferevent rate-limiting on + 'bev'. + + Note that only some bufferevent types currently respect rate-limiting. + They are: socket-based bufferevents (normal and IOCP-based), and SSL-based + bufferevents. + + Return 0 on sucess, -1 on failure. + */ +int bufferevent_set_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg); + +/** + Create a new rate-limit group for bufferevents. A rate-limit group + constrains the maximum number of bytes sent and received, in toto, + by all of its bufferevents. + + @param base An event_base to run any necessary timeouts for the group. + Note that all bufferevents in the group do not necessarily need to share + this event_base. + @param cfg The rate-limit for this group. + + Note that all rate-limits hare are currently best-effort: future versions + of Libevent may implement them more tightly. + + Note also that only some bufferevent types currently respect rate-limiting. + They are: socket-based bufferevents (normal and IOCP-based), and SSL-based + bufferevents. + */ +struct bufferevent_rate_limit_group *bufferevent_rate_limit_group_new( + struct event_base *base, + const struct ev_token_bucket_cfg *cfg); +/** + Change the rate-limiting settings for a given rate-limiting group. + + Return 0 on success, -1 on failure. +*/ +int bufferevent_rate_limit_group_set_cfg( + struct bufferevent_rate_limit_group *, + const struct ev_token_bucket_cfg *); + +/** + Change the smallest quantum we're willing to allocate to any single + bufferevent in a group for reading or writing at a time. + + The rationale is that, because of TCP/IP protocol overheads and kernel + behavior, if a rate-limiting group is so tight on bandwidth that you're + only willing to send 1 byte per tick per bufferevent, you might instead + want to batch up the reads and writes so that you send N bytes per + 1/N of the bufferevents (chosen at random) each tick, so you still wind + up send 1 byte per tick per bufferevent on average, but you don't send + so many tiny packets. + + The default min-share is currently 64 bytes. + + Returns 0 on success, -1 on faulre. + */ +int bufferevent_rate_limit_group_set_min_share( + struct bufferevent_rate_limit_group *, size_t); + +/** + Free a rate-limiting group. The group must have no members when + this function is called. +*/ +void bufferevent_rate_limit_group_free(struct bufferevent_rate_limit_group *); + +/** + Add 'bev' to the list of bufferevents whose aggregate reading and writing + is restricted by 'g'. If 'g' is NULL, remove 'bev' from its current group. + + A bufferevent may belong to no more than one rate-limit group at a time. + If 'bev' is already a member of a group, it will be removed from its old + group before being added to 'g'. + + Return 0 on success and -1 on failure. + */ +int bufferevent_add_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g); + +/** Remove 'bev' from its current rate-limit group (if any). */ +int bufferevent_remove_from_rate_limit_group(struct bufferevent *bev); + +/** + @name Rate limit inspection + + Return the current read or write bucket size for a bufferevent. + If it is not configured with a per-bufferevent ratelimit, return + EV_SSIZE_MAX. This function does not inspect the group limit, if any. + Note that it can return a negative value if the bufferevent has been + made to read or write more than its limit. + + @{ + */ +ev_ssize_t bufferevent_get_read_limit(struct bufferevent *bev); +ev_ssize_t bufferevent_get_write_limit(struct bufferevent *bev); +/*@}*/ + +ev_ssize_t bufferevent_get_max_to_read(struct bufferevent *bev); +ev_ssize_t bufferevent_get_max_to_write(struct bufferevent *bev); + +/** + @name GrouprRate limit inspection + + Return the read or write bucket size for a bufferevent rate limit + group. Note that it can return a negative value if bufferevents in + the group have been made to read or write more than their limits. + + @{ + */ +ev_ssize_t bufferevent_rate_limit_group_get_read_limit( + struct bufferevent_rate_limit_group *); +ev_ssize_t bufferevent_rate_limit_group_get_write_limit( + struct bufferevent_rate_limit_group *); +/*@}*/ + +/** + @name Rate limit manipulation + + Subtract a number of bytes from a bufferevent's read or write bucket. + The decrement value can be negative, if you want to manually refill + the bucket. If the change puts the bucket above or below zero, the + bufferevent will resume or suspend reading writing as appropriate. + These functions make no change in the buckets for the bufferevent's + group, if any. + + Returns 0 on success, -1 on internal error. + + @{ + */ +int bufferevent_decrement_read_limit(struct bufferevent *bev, ev_ssize_t decr); +int bufferevent_decrement_write_limit(struct bufferevent *bev, ev_ssize_t decr); +/*@}*/ + +/** + @name Group rate limit manipulation + + Subtract a number of bytes from a bufferevent rate-limiting group's + read or write bucket. The decrement value can be negative, if you + want to manually refill the bucket. If the change puts the bucket + above or below zero, the bufferevents in the group will resume or + suspend reading writing as appropriate. + + Returns 0 on success, -1 on internal error. + + @{ + */ +int bufferevent_rate_limit_group_decrement_read( + struct bufferevent_rate_limit_group *, ev_ssize_t); +int bufferevent_rate_limit_group_decrement_write( + struct bufferevent_rate_limit_group *, ev_ssize_t); +/*@}*/ + + +/** + * Inspect the total bytes read/written on a group. + * + * Set the variable pointed to by total_read_out to the total number of bytes + * ever read on grp, and the variable pointed to by total_written_out to the + * total number of bytes ever written on grp. */ +void bufferevent_rate_limit_group_get_totals( + struct bufferevent_rate_limit_group *grp, + ev_uint64_t *total_read_out, ev_uint64_t *total_written_out); + +/** + * Reset the total bytes read/written on a group. + * + * Reset the number of bytes read or written on grp as given by + * bufferevent_rate_limit_group_reset_totals(). */ +void +bufferevent_rate_limit_group_reset_totals( + struct bufferevent_rate_limit_group *grp); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_BUFFEREVENT_H_ */ diff --git a/libevent/include/event2/bufferevent_compat.h b/libevent/include/event2/bufferevent_compat.h new file mode 100644 index 0000000..3256fd1 --- /dev/null +++ b/libevent/include/event2/bufferevent_compat.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2007-2012 Niels Provos, Nick Mathewson + * Copyright (c) 2000-2007 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + */ +#ifndef _EVENT2_BUFFEREVENT_COMPAT_H_ +#define _EVENT2_BUFFEREVENT_COMPAT_H_ + +#define evbuffercb bufferevent_data_cb +#define everrorcb bufferevent_event_cb + +/** + Create a new bufferevent for an fd. + + This function is deprecated. Use bufferevent_socket_new and + bufferevent_set_callbacks instead. + + Libevent provides an abstraction on top of the regular event callbacks. + This abstraction is called a buffered event. A buffered event provides + input and output buffers that get filled and drained automatically. The + user of a buffered event no longer deals directly with the I/O, but + instead is reading from input and writing to output buffers. + + Once initialized, the bufferevent structure can be used repeatedly with + bufferevent_enable() and bufferevent_disable(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + If multiple bases are in use, bufferevent_base_set() must be called before + enabling the bufferevent for the first time. + + @deprecated This function is deprecated because it uses the current + event base, and as such can be error prone for multithreaded programs. + Use bufferevent_socket_new() instead. + + @param fd the file descriptor from which data is read and written to. + This file descriptor is not allowed to be a pipe(2). + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param errorcb callback to invoke when there is an error on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @return a pointer to a newly allocated bufferevent struct, or NULL if an + error occurred + @see bufferevent_base_set(), bufferevent_free() + */ +struct bufferevent *bufferevent_new(evutil_socket_t fd, + evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); + + +/** + Set the read and write timeout for a buffered event. + + @param bufev the bufferevent to be modified + @param timeout_read the read timeout + @param timeout_write the write timeout + */ +void bufferevent_settimeout(struct bufferevent *bufev, + int timeout_read, int timeout_write); + +#define EVBUFFER_READ BEV_EVENT_READING +#define EVBUFFER_WRITE BEV_EVENT_WRITING +#define EVBUFFER_EOF BEV_EVENT_EOF +#define EVBUFFER_ERROR BEV_EVENT_ERROR +#define EVBUFFER_TIMEOUT BEV_EVENT_TIMEOUT + +/** macro for getting access to the input buffer of a bufferevent */ +#define EVBUFFER_INPUT(x) bufferevent_get_input(x) +/** macro for getting access to the output buffer of a bufferevent */ +#define EVBUFFER_OUTPUT(x) bufferevent_get_output(x) + +#endif diff --git a/libevent/include/event2/bufferevent_ssl.h b/libevent/include/event2/bufferevent_ssl.h new file mode 100644 index 0000000..c612e99 --- /dev/null +++ b/libevent/include/event2/bufferevent_ssl.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_BUFFEREVENT_SSL_H_ +#define _EVENT2_BUFFEREVENT_SSL_H_ + +/** @file event2/bufferevent_ssl.h + + OpenSSL support for bufferevents. + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is what openssl's SSL objects are underneath. */ +struct ssl_st; + +/** + The state of an SSL object to be used when creating a new + SSL bufferevent. + */ +enum bufferevent_ssl_state { + BUFFEREVENT_SSL_OPEN = 0, + BUFFEREVENT_SSL_CONNECTING = 1, + BUFFEREVENT_SSL_ACCEPTING = 2 +}; + +#if defined(_EVENT_HAVE_OPENSSL) || defined(_EVENT_IN_DOXYGEN) +/** + Create a new SSL bufferevent to send its data over another bufferevent. + + @param base An event_base to use to detect reading and writing. It + must also be the base for the underlying bufferevent. + @param underlying A socket to use for this SSL + @param ssl A SSL* object from openssl. + @param state The current state of the SSL connection + @param options One or more bufferevent_options + @return A new bufferevent on success, or NULL on failure +*/ +struct bufferevent * +bufferevent_openssl_filter_new(struct event_base *base, + struct bufferevent *underlying, + struct ssl_st *ssl, + enum bufferevent_ssl_state state, + int options); + +/** + Create a new SSL bufferevent to send its data over an SSL * on a socket. + + @param base An event_base to use to detect reading and writing + @param fd A socket to use for this SSL + @param ssl A SSL* object from openssl. + @param state The current state of the SSL connection + @param options One or more bufferevent_options + @return A new bufferevent on success, or NULL on failure. +*/ +struct bufferevent * +bufferevent_openssl_socket_new(struct event_base *base, + evutil_socket_t fd, + struct ssl_st *ssl, + enum bufferevent_ssl_state state, + int options); + +/** Return the underlying openssl SSL * object for an SSL bufferevent. */ +struct ssl_st * +bufferevent_openssl_get_ssl(struct bufferevent *bufev); + +/** Tells a bufferevent to begin SSL renegotiation. */ +int bufferevent_ssl_renegotiate(struct bufferevent *bev); + +/** Return the most recent OpenSSL error reported on an SSL bufferevent. */ +unsigned long bufferevent_get_openssl_error(struct bufferevent *bev); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_BUFFEREVENT_SSL_H_ */ diff --git a/libevent/include/event2/bufferevent_struct.h b/libevent/include/event2/bufferevent_struct.h new file mode 100644 index 0000000..02835c1 --- /dev/null +++ b/libevent/include/event2/bufferevent_struct.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_BUFFEREVENT_STRUCT_H_ +#define _EVENT2_BUFFEREVENT_STRUCT_H_ + +/** @file event2/bufferevent_struct.h + + Data structures for bufferevents. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + @deprecated Use of bufferevent_struct.h is completely deprecated; these + structures are only exposed for backward compatibility with programs + written before Libevent 2.0 that used them. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include +/* For struct event */ +#include + +struct event_watermark { + size_t low; + size_t high; +}; + +/** + Shared implementation of a bufferevent. + + This type is exposed only because it was exposed in previous versions, + and some people's code may rely on manipulating it. Otherwise, you + should really not rely on the layout, size, or contents of this structure: + it is fairly volatile, and WILL change in future versions of the code. +**/ +struct bufferevent { + /** Event base for which this bufferevent was created. */ + struct event_base *ev_base; + /** Pointer to a table of function pointers to set up how this + bufferevent behaves. */ + const struct bufferevent_ops *be_ops; + + /** A read event that triggers when a timeout has happened or a socket + is ready to read data. Only used by some subtypes of + bufferevent. */ + struct event ev_read; + /** A write event that triggers when a timeout has happened or a socket + is ready to write data. Only used by some subtypes of + bufferevent. */ + struct event ev_write; + + /** An input buffer. Only the bufferevent is allowed to add data to + this buffer, though the user is allowed to drain it. */ + struct evbuffer *input; + + /** An input buffer. Only the bufferevent is allowed to drain data + from this buffer, though the user is allowed to add it. */ + struct evbuffer *output; + + struct event_watermark wm_read; + struct event_watermark wm_write; + + bufferevent_data_cb readcb; + bufferevent_data_cb writecb; + /* This should be called 'eventcb', but renaming it would break + * backward compatibility */ + bufferevent_event_cb errorcb; + void *cbarg; + + struct timeval timeout_read; + struct timeval timeout_write; + + /** Events that are currently enabled: currently EV_READ and EV_WRITE + are supported. */ + short enabled; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_BUFFEREVENT_STRUCT_H_ */ diff --git a/libevent/include/event2/dns.h b/libevent/include/event2/dns.h new file mode 100644 index 0000000..ca0da3c --- /dev/null +++ b/libevent/include/event2/dns.h @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +/* + * The original DNS code is due to Adam Langley with heavy + * modifications by Nick Mathewson. Adam put his DNS software in the + * public domain. You can find his original copyright below. Please, + * aware that the code as part of Libevent is governed by the 3-clause + * BSD license above. + * + * This software is Public Domain. To view a copy of the public domain dedication, + * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to + * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. + * + * I ask and expect, but do not require, that all derivative works contain an + * attribution similar to: + * Parts developed by Adam Langley + * + * You may wish to replace the word "Parts" with something else depending on + * the amount of original code. + * + * (Derivative works does not include programs which link against, run or include + * the source verbatim in their source distributions) + */ + +/** @file event2/dns.h + * + * Welcome, gentle reader + * + * Async DNS lookups are really a whole lot harder than they should be, + * mostly stemming from the fact that the libc resolver has never been + * very good at them. Before you use this library you should see if libc + * can do the job for you with the modern async call getaddrinfo_a + * (see http://www.imperialviolet.org/page25.html#e498). Otherwise, + * please continue. + * + * The library keeps track of the state of nameservers and will avoid + * them when they go down. Otherwise it will round robin between them. + * + * Quick start guide: + * #include "evdns.h" + * void callback(int result, char type, int count, int ttl, + * void *addresses, void *arg); + * evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); + * evdns_resolve("www.hostname.com", 0, callback, NULL); + * + * When the lookup is complete the callback function is called. The + * first argument will be one of the DNS_ERR_* defines in evdns.h. + * Hopefully it will be DNS_ERR_NONE, in which case type will be + * DNS_IPv4_A, count will be the number of IP addresses, ttl is the time + * which the data can be cached for (in seconds), addresses will point + * to an array of uint32_t's and arg will be whatever you passed to + * evdns_resolve. + * + * Searching: + * + * In order for this library to be a good replacement for glibc's resolver it + * supports searching. This involves setting a list of default domains, in + * which names will be queried for. The number of dots in the query name + * determines the order in which this list is used. + * + * Searching appears to be a single lookup from the point of view of the API, + * although many DNS queries may be generated from a single call to + * evdns_resolve. Searching can also drastically slow down the resolution + * of names. + * + * To disable searching: + * 1. Never set it up. If you never call evdns_resolv_conf_parse or + * evdns_search_add then no searching will occur. + * + * 2. If you do call evdns_resolv_conf_parse then don't pass + * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it). + * + * 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag. + * + * The order of searches depends on the number of dots in the name. If the + * number is greater than the ndots setting then the names is first tried + * globally. Otherwise each search domain is appended in turn. + * + * The ndots setting can either be set from a resolv.conf, or by calling + * evdns_search_ndots_set. + * + * For example, with ndots set to 1 (the default) and a search domain list of + * ["myhome.net"]: + * Query: www + * Order: www.myhome.net, www. + * + * Query: www.abc + * Order: www.abc., www.abc.myhome.net + * + * Internals: + * + * Requests are kept in two queues. The first is the inflight queue. In + * this queue requests have an allocated transaction id and nameserver. + * They will soon be transmitted if they haven't already been. + * + * The second is the waiting queue. The size of the inflight ring is + * limited and all other requests wait in waiting queue for space. This + * bounds the number of concurrent requests so that we don't flood the + * nameserver. Several algorithms require a full walk of the inflight + * queue and so bounding its size keeps thing going nicely under huge + * (many thousands of requests) loads. + * + * If a nameserver loses too many requests it is considered down and we + * try not to use it. After a while we send a probe to that nameserver + * (a lookup for google.com) and, if it replies, we consider it working + * again. If the nameserver fails a probe we wait longer to try again + * with the next probe. + */ + +#ifndef _EVENT2_DNS_H_ +#define _EVENT2_DNS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* For integer types. */ +#include + +/** Error codes 0-5 are as described in RFC 1035. */ +#define DNS_ERR_NONE 0 +/** The name server was unable to interpret the query */ +#define DNS_ERR_FORMAT 1 +/** The name server was unable to process this query due to a problem with the + * name server */ +#define DNS_ERR_SERVERFAILED 2 +/** The domain name does not exist */ +#define DNS_ERR_NOTEXIST 3 +/** The name server does not support the requested kind of query */ +#define DNS_ERR_NOTIMPL 4 +/** The name server refuses to reform the specified operation for policy + * reasons */ +#define DNS_ERR_REFUSED 5 +/** The reply was truncated or ill-formatted */ +#define DNS_ERR_TRUNCATED 65 +/** An unknown error occurred */ +#define DNS_ERR_UNKNOWN 66 +/** Communication with the server timed out */ +#define DNS_ERR_TIMEOUT 67 +/** The request was canceled because the DNS subsystem was shut down. */ +#define DNS_ERR_SHUTDOWN 68 +/** The request was canceled via a call to evdns_cancel_request */ +#define DNS_ERR_CANCEL 69 +/** There were no answers and no error condition in the DNS packet. + * This can happen when you ask for an address that exists, but a record + * type that doesn't. */ +#define DNS_ERR_NODATA 70 + +#define DNS_IPv4_A 1 +#define DNS_PTR 2 +#define DNS_IPv6_AAAA 3 + +#define DNS_QUERY_NO_SEARCH 1 + +#define DNS_OPTION_SEARCH 1 +#define DNS_OPTION_NAMESERVERS 2 +#define DNS_OPTION_MISC 4 +#define DNS_OPTION_HOSTSFILE 8 +#define DNS_OPTIONS_ALL 15 + +/* Obsolete name for DNS_QUERY_NO_SEARCH */ +#define DNS_NO_SEARCH DNS_QUERY_NO_SEARCH + +/** + * The callback that contains the results from a lookup. + * - result is one of the DNS_ERR_* values (DNS_ERR_NONE for success) + * - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA + * - count contains the number of addresses of form type + * - ttl is the number of seconds the resolution may be cached for. + * - addresses needs to be cast according to type. It will be an array of + * 4-byte sequences for ipv4, or an array of 16-byte sequences for ipv6, + * or a nul-terminated string for PTR. + */ +typedef void (*evdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg); + +struct evdns_base; +struct event_base; + +/** + Initialize the asynchronous DNS library. + + This function initializes support for non-blocking name resolution by + calling evdns_resolv_conf_parse() on UNIX and + evdns_config_windows_nameservers() on Windows. + + @param event_base the event base to associate the dns client with + @param initialize_nameservers 1 if resolve.conf processing should occur + @return evdns_base object if successful, or NULL if an error occurred. + @see evdns_base_free() + */ +struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize_nameservers); + + +/** + Shut down the asynchronous DNS resolver and terminate all active requests. + + If the 'fail_requests' option is enabled, all active requests will return + an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, + the requests will be silently discarded. + + @param evdns_base the evdns base to free + @param fail_requests if zero, active requests will be aborted; if non-zero, + active requests will return DNS_ERR_SHUTDOWN. + @see evdns_base_new() + */ +void evdns_base_free(struct evdns_base *base, int fail_requests); + +/** + Convert a DNS error code to a string. + + @param err the DNS error code + @return a string containing an explanation of the error code +*/ +const char *evdns_err_to_string(int err); + + +/** + Add a nameserver. + + The address should be an IPv4 address in network byte order. + The type of address is chosen so that it matches in_addr.s_addr. + + @param base the evdns_base to which to add the name server + @param address an IP address in network byte order + @return 0 if successful, or -1 if an error occurred + @see evdns_base_nameserver_ip_add() + */ +int evdns_base_nameserver_add(struct evdns_base *base, + unsigned long int address); + +/** + Get the number of configured nameservers. + + This returns the number of configured nameservers (not necessarily the + number of running nameservers). This is useful for double-checking + whether our calls to the various nameserver configuration functions + have been successful. + + @param base the evdns_base to which to apply this operation + @return the number of configured nameservers + @see evdns_base_nameserver_add() + */ +int evdns_base_count_nameservers(struct evdns_base *base); + +/** + Remove all configured nameservers, and suspend all pending resolves. + + Resolves will not necessarily be re-attempted until evdns_base_resume() is called. + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_resume() + */ +int evdns_base_clear_nameservers_and_suspend(struct evdns_base *base); + + +/** + Resume normal operation and continue any suspended resolve requests. + + Re-attempt resolves left in limbo after an earlier call to + evdns_base_clear_nameservers_and_suspend(). + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_clear_nameservers_and_suspend() + */ +int evdns_base_resume(struct evdns_base *base); + +/** + Add a nameserver by string address. + + This function parses a n IPv4 or IPv6 address from a string and adds it as a + nameserver. It supports the following formats: + - [IPv6Address]:port + - [IPv6Address] + - IPv6Address + - IPv4Address:port + - IPv4Address + + If no port is specified, it defaults to 53. + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_nameserver_add() + */ +int evdns_base_nameserver_ip_add(struct evdns_base *base, + const char *ip_as_string); + +/** + Add a nameserver by sockaddr. + **/ +int +evdns_base_nameserver_sockaddr_add(struct evdns_base *base, + const struct sockaddr *sa, ev_socklen_t len, unsigned flags); + +struct evdns_request; + +/** + Lookup an A record for a given name. + + @param base the evdns_base to which to apply this operation + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +struct evdns_request *evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup an AAAA record for a given name. + + @param base the evdns_base to which to apply this operation + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +struct evdns_request *evdns_base_resolve_ipv6(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr); + +struct in_addr; +struct in6_addr; + +/** + Lookup a PTR record for a given IP address. + + @param base the evdns_base to which to apply this operation + @param in an IPv4 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +struct evdns_request *evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr); + + +/** + Lookup a PTR record for a given IPv6 address. + + @param base the evdns_base to which to apply this operation + @param in an IPv6 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +struct evdns_request *evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Cancels a pending DNS resolution request. + + @param base the evdns_base that was used to make the request + @param req the evdns_request that was returned by calling a resolve function + @see evdns_base_resolve_ipv4(), evdns_base_resolve_ipv6, evdns_base_resolve_reverse +*/ +void evdns_cancel_request(struct evdns_base *base, struct evdns_request *req); + +/** + Set the value of a configuration option. + + The currently available configuration options are: + + ndots, timeout, max-timeouts, max-inflight, attempts, randomize-case, + bind-to, initial-probe-timeout, getaddrinfo-allow-skew. + + In versions before Libevent 2.0.3-alpha, the option name needed to end with + a colon. + + @param base the evdns_base to which to apply this operation + @param option the name of the configuration option to be modified + @param val the value to be set + @return 0 if successful, or -1 if an error occurred + */ +int evdns_base_set_option(struct evdns_base *base, const char *option, const char *val); + + +/** + Parse a resolv.conf file. + + The 'flags' parameter determines what information is parsed from the + resolv.conf file. See the man page for resolv.conf for the format of this + file. + + The following directives are not parsed from the file: sortlist, rotate, + no-check-names, inet6, debug. + + If this function encounters an error, the possible return values are: 1 = + failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of + memory, 5 = short read from file, 6 = no nameservers listed in the file + + @param base the evdns_base to which to apply this operation + @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC| + DNS_OPTIONS_HOSTSFILE|DNS_OPTIONS_ALL + @param filename the path to the resolv.conf file + @return 0 if successful, or various positive error codes if an error + occurred (see above) + @see resolv.conf(3), evdns_config_windows_nameservers() + */ +int evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename); + +/** + Load an /etc/hosts-style file from 'hosts_fname' into 'base'. + + If hosts_fname is NULL, add minimal entries for localhost, and nothing + else. + + Note that only evdns_getaddrinfo uses the /etc/hosts entries. + + Return 0 on success, negative on failure. +*/ +int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname); + +/** + Obtain nameserver information using the Windows API. + + Attempt to configure a set of nameservers based on platform settings on + a win32 host. Preferentially tries to use GetNetworkParams; if that fails, + looks in the registry. + + @return 0 if successful, or -1 if an error occurred + @see evdns_resolv_conf_parse() + */ +#ifdef WIN32 +int evdns_base_config_windows_nameservers(struct evdns_base *); +#define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED +#endif + + +/** + Clear the list of search domains. + */ +void evdns_base_search_clear(struct evdns_base *base); + + +/** + Add a domain to the list of search domains + + @param domain the domain to be added to the search list + */ +void evdns_base_search_add(struct evdns_base *base, const char *domain); + + +/** + Set the 'ndots' parameter for searches. + + Sets the number of dots which, when found in a name, causes + the first query to be without any search domain. + + @param ndots the new ndots parameter + */ +void evdns_base_search_ndots_set(struct evdns_base *base, const int ndots); + +/** + A callback that is invoked when a log message is generated + + @param is_warning indicates if the log message is a 'warning' + @param msg the content of the log message + */ +typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg); + + +/** + Set the callback function to handle DNS log messages. If this + callback is not set, evdns log messages are handled with the regular + Libevent logging system. + + @param fn the callback to be invoked when a log message is generated + */ +void evdns_set_log_fn(evdns_debug_log_fn_type fn); + +/** + Set a callback that will be invoked to generate transaction IDs. By + default, we pick transaction IDs based on the current clock time, which + is bad for security. + + @param fn the new callback, or NULL to use the default. + + NOTE: This function has no effect in Libevent 2.0.4-alpha and later, + since Libevent now provides its own secure RNG. + */ +void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void)); + +/** + Set a callback used to generate random bytes. By default, we use + the same function as passed to evdns_set_transaction_id_fn to generate + bytes two at a time. If a function is provided here, it's also used + to generate transaction IDs. + + NOTE: This function has no effect in Libevent 2.0.4-alpha and later, + since Libevent now provides its own secure RNG. +*/ +void evdns_set_random_bytes_fn(void (*fn)(char *, size_t)); + +/* + * Functions used to implement a DNS server. + */ + +struct evdns_server_request; +struct evdns_server_question; + +/** + A callback to implement a DNS server. The callback function receives a DNS + request. It should then optionally add a number of answers to the reply + using the evdns_server_request_add_*_reply functions, before calling either + evdns_server_request_respond to send the reply back, or + evdns_server_request_drop to decline to answer the request. + + @param req A newly received request + @param user_data A pointer that was passed to + evdns_add_server_port_with_base(). + */ +typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, void *); +#define EVDNS_ANSWER_SECTION 0 +#define EVDNS_AUTHORITY_SECTION 1 +#define EVDNS_ADDITIONAL_SECTION 2 + +#define EVDNS_TYPE_A 1 +#define EVDNS_TYPE_NS 2 +#define EVDNS_TYPE_CNAME 5 +#define EVDNS_TYPE_SOA 6 +#define EVDNS_TYPE_PTR 12 +#define EVDNS_TYPE_MX 15 +#define EVDNS_TYPE_TXT 16 +#define EVDNS_TYPE_AAAA 28 + +#define EVDNS_QTYPE_AXFR 252 +#define EVDNS_QTYPE_ALL 255 + +#define EVDNS_CLASS_INET 1 + +/* flags that can be set in answers; as part of the err parameter */ +#define EVDNS_FLAGS_AA 0x400 +#define EVDNS_FLAGS_RD 0x080 + +/** Create a new DNS server port. + + @param base The event base to handle events for the server port. + @param socket A UDP socket to accept DNS requests. + @param flags Always 0 for now. + @param callback A function to invoke whenever we get a DNS request + on the socket. + @param user_data Data to pass to the callback. + @return an evdns_server_port structure for this server port. + */ +struct evdns_server_port *evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data); +/** Close down a DNS server port, and free associated structures. */ +void evdns_close_server_port(struct evdns_server_port *port); + +/** Sets some flags in a reply we're building. + Allows setting of the AA or RD flags + */ +void evdns_server_request_set_flags(struct evdns_server_request *req, int flags); + +/* Functions to add an answer to an in-progress DNS reply. + */ +int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data); +int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl); +int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl); +int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl); +int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl); + +/** + Send back a response to a DNS request, and free the request structure. +*/ +int evdns_server_request_respond(struct evdns_server_request *req, int err); +/** + Free a DNS request without sending back a reply. +*/ +int evdns_server_request_drop(struct evdns_server_request *req); +struct sockaddr; +/** + Get the address that made a DNS request. + */ +int evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len); + +/** Callback for evdns_getaddrinfo. */ +typedef void (*evdns_getaddrinfo_cb)(int result, struct evutil_addrinfo *res, void *arg); + +struct evdns_base; +struct evdns_getaddrinfo_request; +/** Make a non-blocking getaddrinfo request using the dns_base in 'dns_base'. + * + * If we can answer the request immediately (with an error or not!), then we + * invoke cb immediately and return NULL. Otherwise we return + * an evdns_getaddrinfo_request and invoke cb later. + * + * When the callback is invoked, we pass as its first argument the error code + * that getaddrinfo would return (or 0 for no error). As its second argument, + * we pass the evutil_addrinfo structures we found (or NULL on error). We + * pass 'arg' as the third argument. + * + * Limitations: + * + * - The AI_V4MAPPED and AI_ALL flags are not currently implemented. + * - For ai_socktype, we only handle SOCKTYPE_STREAM, SOCKTYPE_UDP, and 0. + * - For ai_protocol, we only handle IPPROTO_TCP, IPPROTO_UDP, and 0. + */ +struct evdns_getaddrinfo_request *evdns_getaddrinfo( + struct evdns_base *dns_base, + const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, + evdns_getaddrinfo_cb cb, void *arg); + +/* Cancel an in-progress evdns_getaddrinfo. This MUST NOT be called after the + * getaddrinfo's callback has been invoked. The resolves will be canceled, + * and the callback will be invoked with the error EVUTIL_EAI_CANCEL. */ +void evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *req); + +#ifdef __cplusplus +} +#endif + +#endif /* !_EVENT2_DNS_H_ */ diff --git a/libevent/include/event2/dns_compat.h b/libevent/include/event2/dns_compat.h new file mode 100644 index 0000000..7c1c776 --- /dev/null +++ b/libevent/include/event2/dns_compat.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_DNS_COMPAT_H_ +#define _EVENT2_DNS_COMPAT_H_ + +/** @file event2/dns_compat.h + + Potentially non-threadsafe versions of the functions in dns.h: provided + only for backwards compatibility. + + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + Initialize the asynchronous DNS library. + + This function initializes support for non-blocking name resolution by + calling evdns_resolv_conf_parse() on UNIX and + evdns_config_windows_nameservers() on Windows. + + @deprecated This function is deprecated because it always uses the current + event base, and is easily confused by multiple calls to event_init(), and + so is not safe for multithreaded use. Additionally, it allocates a global + structure that only one thread can use. The replacement is + evdns_base_new(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_shutdown() + */ +int evdns_init(void); + +struct evdns_base; +/** + Return the global evdns_base created by event_init() and used by the other + deprecated functions. + + @deprecated This function is deprecated because use of the global + evdns_base is error-prone. + */ +struct evdns_base *evdns_get_global_base(void); + +/** + Shut down the asynchronous DNS resolver and terminate all active requests. + + If the 'fail_requests' option is enabled, all active requests will return + an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, + the requests will be silently discarded. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_shutdown(). + + @param fail_requests if zero, active requests will be aborted; if non-zero, + active requests will return DNS_ERR_SHUTDOWN. + @see evdns_init() + */ +void evdns_shutdown(int fail_requests); + +/** + Add a nameserver. + + The address should be an IPv4 address in network byte order. + The type of address is chosen so that it matches in_addr.s_addr. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_nameserver_add(). + + @param address an IP address in network byte order + @return 0 if successful, or -1 if an error occurred + @see evdns_nameserver_ip_add() + */ +int evdns_nameserver_add(unsigned long int address); + +/** + Get the number of configured nameservers. + + This returns the number of configured nameservers (not necessarily the + number of running nameservers). This is useful for double-checking + whether our calls to the various nameserver configuration functions + have been successful. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_count_nameservers(). + + @return the number of configured nameservers + @see evdns_nameserver_add() + */ +int evdns_count_nameservers(void); + +/** + Remove all configured nameservers, and suspend all pending resolves. + + Resolves will not necessarily be re-attempted until evdns_resume() is called. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_clear_nameservers_and_suspend(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_resume() + */ +int evdns_clear_nameservers_and_suspend(void); + +/** + Resume normal operation and continue any suspended resolve requests. + + Re-attempt resolves left in limbo after an earlier call to + evdns_clear_nameservers_and_suspend(). + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resume(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_clear_nameservers_and_suspend() + */ +int evdns_resume(void); + +/** + Add a nameserver. + + This wraps the evdns_nameserver_add() function by parsing a string as an IP + address and adds it as a nameserver. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_nameserver_ip_add(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_nameserver_add() + */ +int evdns_nameserver_ip_add(const char *ip_as_string); + +/** + Lookup an A record for a given name. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_ipv4(). + + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup an AAAA record for a given name. + + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr); + +struct in_addr; +struct in6_addr; + +/** + Lookup a PTR record for a given IP address. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_reverse(). + + @param in an IPv4 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup a PTR record for a given IPv6 address. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_reverse_ipv6(). + + @param in an IPv6 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Set the value of a configuration option. + + The currently available configuration options are: + + ndots, timeout, max-timeouts, max-inflight, and attempts + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_set_option(). + + @param option the name of the configuration option to be modified + @param val the value to be set + @param flags Ignored. + @return 0 if successful, or -1 if an error occurred + */ +int evdns_set_option(const char *option, const char *val, int flags); + +/** + Parse a resolv.conf file. + + The 'flags' parameter determines what information is parsed from the + resolv.conf file. See the man page for resolv.conf for the format of this + file. + + The following directives are not parsed from the file: sortlist, rotate, + no-check-names, inet6, debug. + + If this function encounters an error, the possible return values are: 1 = + failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of + memory, 5 = short read from file, 6 = no nameservers listed in the file + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolv_conf_parse(). + + @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC| + DNS_OPTIONS_ALL + @param filename the path to the resolv.conf file + @return 0 if successful, or various positive error codes if an error + occurred (see above) + @see resolv.conf(3), evdns_config_windows_nameservers() + */ +int evdns_resolv_conf_parse(int flags, const char *const filename); + +/** + Clear the list of search domains. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_clear(). + */ +void evdns_search_clear(void); + +/** + Add a domain to the list of search domains + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_add(). + + @param domain the domain to be added to the search list + */ +void evdns_search_add(const char *domain); + +/** + Set the 'ndots' parameter for searches. + + Sets the number of dots which, when found in a name, causes + the first query to be without any search domain. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_ndots_set(). + + @param ndots the new ndots parameter + */ +void evdns_search_ndots_set(const int ndots); + +/** + As evdns_server_new_with_base. + + @deprecated This function is deprecated because it does not allow the + caller to specify which even_base it uses. The recommended + function is evdns_add_server_port_with_base(). + +*/ +struct evdns_server_port *evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data); + +#ifdef WIN32 +int evdns_config_windows_nameservers(void); +#define EVDNS_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_EVENT_COMPAT_H_ */ diff --git a/libevent/include/event2/dns_struct.h b/libevent/include/event2/dns_struct.h new file mode 100644 index 0000000..5a02a0b --- /dev/null +++ b/libevent/include/event2/dns_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_DNS_STRUCT_H_ +#define _EVENT2_DNS_STRUCT_H_ + +/** @file event2/dns_struct.h + + Data structures for dns. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/* + * Structures used to implement a DNS server. + */ + +struct evdns_server_request { + int flags; + int nquestions; + struct evdns_server_question **questions; +}; +struct evdns_server_question { + int type; +#ifdef __cplusplus + int dns_question_class; +#else + /* You should refer to this field as "dns_question_class". The + * name "class" works in C for backward compatibility, and will be + * removed in a future version. (1.5 or later). */ + int class; +#define dns_question_class class +#endif + char name[1]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_DNS_STRUCT_H_ */ + diff --git a/libevent/include/event2/event.h b/libevent/include/event2/event.h new file mode 100644 index 0000000..3993707 --- /dev/null +++ b/libevent/include/event2/event.h @@ -0,0 +1,1197 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_EVENT_H_ +#define _EVENT2_EVENT_H_ + +/** + @mainpage + + @section intro Introduction + + Libevent is an event notification library for developing scalable network + servers. The Libevent API provides a mechanism to execute a callback + function when a specific event occurs on a file descriptor or after a + timeout has been reached. Furthermore, Libevent also support callbacks due + to signals or regular timeouts. + + Libevent is meant to replace the event loop found in event driven network + servers. An application just needs to call event_dispatch() and then add or + remove events dynamically without having to change the event loop. + + + Currently, Libevent supports /dev/poll, kqueue(2), select(2), poll(2), + epoll(4), and evports. The internal event mechanism is completely + independent of the exposed event API, and a simple update of Libevent can + provide new functionality without having to redesign the applications. As a + result, Libevent allows for portable application development and provides + the most scalable event notification mechanism available on an operating + system. Libevent can also be used for multithreaded programs. Libevent + should compile on Linux, *BSD, Mac OS X, Solaris and, Windows. + + @section usage Standard usage + + Every program that uses Libevent must inclurde the + header, and pass the -levent flag to the linker. (You can instead link + -levent_core if you only want the main event and buffered IO-based code, + and don't want to link any protocol code.) + + @section setup Library setup + + Before you call any other Libevent functions, you need to set up the + library. If you're going to use Libevent from multiple threads in a + multithreaded application, you need to initialize thread support -- + typically by using evthread_use_pthreads() or + evthread_use_windows_threads(). See for more + information. + + This is also the point where you can replace Libevent's memory + management functions with event_set_mem_functions, and enable debug mode + with event_enable_debug_mode(). + + @section base Creating an event base + + Next, you need to create an event_base structure, using event_base_new() + or event_base_new_with_config(). The event_base is responsible for + keeping track of which events are "pending" (that is to say, being + watched to see if they become active) and which events are "active". + Every event is associated with a single event_base. + + @section event Event notification + + For each file descriptor that you wish to monitor, you must create an + event structure with event_new(). (You may also declare an event + structure and call event_assign() to initialize the members of the + structure.) To enable notification, you add the structure to the list + of monitored events by calling event_add(). The event structure must + remain allocated as long as it is active, so it should generally be + allocated on the heap. + + @section loop Dispaching evets. + + Finally, you call event_base_dispatch() to loop and dispatch events. + You can also use event_base_loop() for more fine-grained control. + + Currently, only one thread can be dispatching a given event_base at a + time. If you want to run events in multiple threads at once, you can + either have a single event_base whose events add work to a work queue, + or you can create multiple event_base objects. + + @section bufferevent I/O Buffers + + Libevent provides a buffered I/O abstraction on top of the regular event + callbacks. This abstraction is called a bufferevent. A bufferevent + provides input and output buffers that get filled and drained + automatically. The user of a buffered event no longer deals directly + with the I/O, but instead is reading from input and writing to output + buffers. + + Once initialized via bufferevent_socket_new(), the bufferevent structure + can be used repeatedly with bufferevent_enable() and + bufferevent_disable(). Instead of reading and writing directly to a + socket, you would call bufferevent_read() and bufferevent_write(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + See for more information. + + @section timers Timers + + Libevent can also be used to create timers that invoke a callback after a + certain amount of time has expired. The evtimer_new() function returns + an event struct to use as a timer. To activate the timer, call + evtimer_add(). Timers can be deactivated by calling evtimer_del(). + + @section evdns Asynchronous DNS resolution + + Libevent provides an asynchronous DNS resolver that should be used instead + of the standard DNS resolver functions. See the + functions for more detail. + + @section evhttp Event-driven HTTP servers + + Libevent provides a very simple event-driven HTTP server that can be + embedded in your program and used to service HTTP requests. + + To use this capability, you need to include the header in your + program. See that header for more information. + + @section evrpc A framework for RPC servers and clients + + Libevent provides a framework for creating RPC servers and clients. It + takes care of marshaling and unmarshaling all data structures. + + @section api API Reference + + To browse the complete documentation of the libevent API, click on any of + the following links. + + event2/event.h + The primary libevent header + + event2/thread.h + Functions for use by multithreaded programs + + event2/buffer.h and event2/bufferevent.h + Buffer management for network reading and writing + + event2/util.h + Utility functions for portable nonblocking network code + + event2/dns.h + Asynchronous DNS resolution + + event2/http.h + An embedded libevent-based HTTP server + + event2/rpc.h + A framework for creating RPC servers and clients + + */ + +/** @file event2/event.h + + Core functions for waiting for and receiving events, and using event bases. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +#include + +/* For int types. */ +#include + +/** + * Structure to hold information and state for a Libevent dispatch loop. + * + * The event_base lies at the center of Libevent; every application will + * have one. It keeps track of all pending and active events, and + * notifies your application of the active ones. + * + * This is an opaque structure; you can allocate one using + * event_base_new() or event_base_new_with_config(). + * + * @see event_base_new(), event_base_free(), event_base_loop(), + * event_base_new_with_config() + */ +struct event_base +#ifdef _EVENT_IN_DOXYGEN +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * @struct event + * + * Structure to represent a single event. + * + * An event can have some underlying condition it represents: a socket + * becoming readable or writeable (or both), or a signal becoming raised. + * (An event that represents no underlying condition is still useful: you + * can use one to implement a timer, or to communicate between threads.) + * + * Generally, you can create events with event_new(), then make them + * pending with event_add(). As your event_base runs, it will run the + * callbacks of an events whose conditions are triggered. When you + * longer want the event, free it with event_free(). + * + * In more depth: + * + * An event may be "pending" (one whose condition we are watching), + * "active" (one whose condition has triggered and whose callback is about + * to run), neither, or both. Events come into existence via + * event_assign() or event_new(), and are then neither active nor pending. + * + * To make an event pending, pass it to event_add(). When doing so, you + * can also set a timeout for the event. + * + * Events become active during an event_base_loop() call when either their + * condition has triggered, or when their timeout has elapsed. You can + * also activate an event manually using event_active(). The even_base + * loop will run the callbacks of active events; after it has done so, it + * marks them as no longer active. + * + * You can make an event non-pending by passing it to event_del(). This + * also makes the event non-active. + * + * Events can be "persistent" or "non-persistent". A non-persistent event + * becomes non-pending as soon as it is triggered: thus, it only runs at + * most once per call to event_add(). A persistent event remains pending + * even when it becomes active: you'll need to event_del() it manually in + * order to make it non-pending. When a persistent event with a timeout + * becomes active, its timeout is reset: this means you can use persistent + * events to implement periodic timeouts. + * + * This should be treated as an opaque structure; you should never read or + * write any of its fields directly. For backward compatibility with old + * code, it is defined in the event2/event_struct.h header; including this + * header may make your code incompatible with other versions of Libevent. + * + * @see event_new(), event_free(), event_assign(), event_get_assignment(), + * event_add(), event_del(), event_active(), event_pending(), + * event_get_fd(), event_get_base(), event_get_events(), + * event_get_callback(), event_get_callback_arg(), + * event_priority_set() + */ +struct event +#ifdef _EVENT_IN_DOXYGEN +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * Configuration for an event_base. + * + * There are many options that can be used to alter the behavior and + * implementation of an event_base. To avoid having to pass them all in a + * complex many-argument constructor, we provide an abstract data type + * wrhere you set up configation information before passing it to + * event_base_new_with_config(). + * + * @see event_config_new(), event_config_free(), event_base_new_with_config(), + * event_config_avoid_method(), event_config_require_features(), + * event_config_set_flag(), event_config_set_num_cpus_hint() + */ +struct event_config +#ifdef _EVENT_IN_DOXYGEN +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * Enable some relatively expensive debugging checks in Libevent that + * would normally be turned off. Generally, these checks cause code that + * would otherwise crash mysteriously to fail earlier with an assertion + * failure. Note that this method MUST be called before any events or + * event_bases have been created. + * + * Debug mode can currently catch the following errors: + * An event is re-assigned while it is added + * Any function is called on a non-assigned event + * + * Note that debugging mode uses memory to track every event that has been + * initialized (via event_assign, event_set, or event_new) but not yet + * released (via event_free or event_debug_unassign). If you want to use + * debug mode, and you find yourself running out of memory, you will need + * to use event_debug_unassign to explicitly stop tracking events that + * are no longer considered set-up. + * + * @see event_debug_unassign() + */ +void event_enable_debug_mode(void); + +/** + * When debugging mode is enabled, informs Libevent that an event should no + * longer be considered as assigned. When debugging mode is not enabled, does + * nothing. + * + * This function must only be called on a non-added event. + * + * @see event_enable_debug_mode() + */ +void event_debug_unassign(struct event *); + +/** + * Create and return a new event_base to use with the rest of Libevent. + * + * @return a new event_base on success, or NULL on failure. + * + * @see event_base_free(), event_base_new_with_config() + */ +struct event_base *event_base_new(void); + +/** + Reinitialize the event base after a fork + + Some event mechanisms do not survive across fork. The event base needs + to be reinitialized with the event_reinit() function. + + @param base the event base that needs to be re-initialized + @return 0 if successful, or -1 if some events could not be re-added. + @see event_base_new() +*/ +int event_reinit(struct event_base *base); + +/** + Event dispatching loop + + This loop will run the event base until either there are no more added + events, or until something calls event_base_loopbreak() or + event_base_loopexit(). + + @param base the event_base structure returned by event_base_new() or + event_base_new_with_config() + @return 0 if successful, -1 if an error occurred, or 1 if no events were + registered. + @see event_base_loop() + */ +int event_base_dispatch(struct event_base *); + +/** + Get the kernel event notification mechanism used by Libevent. + + @param eb the event_base structure returned by event_base_new() + @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) + */ +const char *event_base_get_method(const struct event_base *); + +/** + Gets all event notification mechanisms supported by Libevent. + + This functions returns the event mechanism in order preferred by + Libevent. Note that this list will include all backends that + Libevent has compiled-in support for, and will not necessarily check + your OS to see whether it has the required resources. + + @return an array with pointers to the names of support methods. + The end of the array is indicated by a NULL pointer. If an + error is encountered NULL is returned. +*/ +const char **event_get_supported_methods(void); + +/** + Allocates a new event configuration object. + + The event configuration object can be used to change the behavior of + an event base. + + @return an event_config object that can be used to store configuration, or + NULL if an error is encountered. + @see event_base_new_with_config(), event_config_free(), event_config +*/ +struct event_config *event_config_new(void); + +/** + Deallocates all memory associated with an event configuration object + + @param cfg the event configuration object to be freed. +*/ +void event_config_free(struct event_config *cfg); + +/** + Enters an event method that should be avoided into the configuration. + + This can be used to avoid event mechanisms that do not support certain + file descriptor types, or for debugging to avoid certain event + mechanisms. An application can make use of multiple event bases to + accommodate incompatible file descriptor types. + + @param cfg the event configuration object + @param method the name of the event method to avoid + @return 0 on success, -1 on failure. +*/ +int event_config_avoid_method(struct event_config *cfg, const char *method); + +/** + A flag used to describe which features an event_base (must) provide. + + Because of OS limitations, not every Libevent backend supports every + possible feature. You can use this type with + event_config_require_features() to tell Libevent to only proceed if your + event_base implements a given feature, and you can receive this type from + event_base_get_features() to see which features are available. +*/ +enum event_method_feature { + /** Require an event method that allows edge-triggered events with EV_ET. */ + EV_FEATURE_ET = 0x01, + /** Require an event method where having one event triggered among + * many is [approximately] an O(1) operation. This excludes (for + * example) select and poll, which are approximately O(N) for N + * equal to the total number of possible events. */ + EV_FEATURE_O1 = 0x02, + /** Require an event method that allows file descriptors as well as + * sockets. */ + EV_FEATURE_FDS = 0x04 +}; + +/** + A flag passed to event_config_set_flag(). + + These flags change the behavior of an allocated event_base. + + @see event_config_set_flag(), event_base_new_with_config(), + event_method_feature + */ +enum event_base_config_flag { + /** Do not allocate a lock for the event base, even if we have + locking set up. */ + EVENT_BASE_FLAG_NOLOCK = 0x01, + /** Do not check the EVENT_* environment variables when configuring + an event_base */ + EVENT_BASE_FLAG_IGNORE_ENV = 0x02, + /** Windows only: enable the IOCP dispatcher at startup + + If this flag is set then bufferevent_socket_new() and + evconn_listener_new() will use IOCP-backed implementations + instead of the usual select-based one on Windows. + */ + EVENT_BASE_FLAG_STARTUP_IOCP = 0x04, + /** Instead of checking the current time every time the event loop is + ready to run timeout callbacks, check after each timeout callback. + */ + EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08, + + /** If we are using the epoll backend, this flag says that it is + safe to use Libevent's internal change-list code to batch up + adds and deletes in order to try to do as few syscalls as + possible. Setting this flag can make your code run faster, but + it may trigger a Linux bug: it is not safe to use this flag + if you have any fds cloned by dup() or its variants. Doing so + will produce strange and hard-to-diagnose bugs. + + This flag can also be activated by settnig the + EVENT_EPOLL_USE_CHANGELIST environment variable. + + This flag has no effect if you wind up using a backend other than + epoll. + */ + EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10 +}; + +/** + Return a bitmask of the features implemented by an event base. This + will be a bitwise OR of one or more of the values of + event_method_feature + + @see event_method_feature + */ +int event_base_get_features(const struct event_base *base); + +/** + Enters a required event method feature that the application demands. + + Note that not every feature or combination of features is supported + on every platform. Code that requests features should be prepared + to handle the case where event_base_new_with_config() returns NULL, as in: +
+     event_config_require_features(cfg, EV_FEATURE_ET);
+     base = event_base_new_with_config(cfg);
+     if (base == NULL) {
+       // We can't get edge-triggered behavior here.
+       event_config_require_features(cfg, 0);
+       base = event_base_new_with_config(cfg);
+     }
+   
+ + @param cfg the event configuration object + @param feature a bitfield of one or more event_method_feature values. + Replaces values from previous calls to this function. + @return 0 on success, -1 on failure. + @see event_method_feature, event_base_new_with_config() +*/ +int event_config_require_features(struct event_config *cfg, int feature); + +/** + * Sets one or more flags to configure what parts of the eventual event_base + * will be initialized, and how they'll work. + * + * @see event_base_config_flags, event_base_new_with_config() + **/ +int event_config_set_flag(struct event_config *cfg, int flag); + +/** + * Records a hint for the number of CPUs in the system. This is used for + * tuning thread pools, etc, for optimal performance. In Libevent 2.0, + * it is only on Windows, and only when IOCP is in use. + * + * @param cfg the event configuration object + * @param cpus the number of cpus + * @return 0 on success, -1 on failure. + */ +int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus); + +/** + Initialize the event API. + + Use event_base_new_with_config() to initialize a new event base, taking + the specified configuration under consideration. The configuration object + can currently be used to avoid certain event notification mechanisms. + + @param cfg the event configuration object + @return an initialized event_base that can be used to registering events, + or NULL if no event base can be created with the requested event_config. + @see event_base_new(), event_base_free(), event_init(), event_assign() +*/ +struct event_base *event_base_new_with_config(const struct event_config *); + +/** + Deallocate all memory associated with an event_base, and free the base. + + Note that this function will not close any fds or free any memory passed + to event_new as the argument to callback. + + @param eb an event_base to be freed + */ +void event_base_free(struct event_base *); + +/** @name Log severities + */ +/**@{*/ +#define _EVENT_LOG_DEBUG 0 +#define _EVENT_LOG_MSG 1 +#define _EVENT_LOG_WARN 2 +#define _EVENT_LOG_ERR 3 +/**@}*/ + +/** + A callback function used to intercept Libevent's log messages. + + @see event_set_log_callback + */ +typedef void (*event_log_cb)(int severity, const char *msg); +/** + Redirect Libevent's log messages. + + @param cb a function taking two arguments: an integer severity between + _EVENT_LOG_DEBUG and _EVENT_LOG_ERR, and a string. If cb is NULL, + then the default log is used. + + NOTE: The function you provide *must not* call any other libevent + functionality. Doing so can produce undefined behavior. + */ +void event_set_log_callback(event_log_cb cb); + +/** + A function to be called if Libevent encounters a fatal internal error. + + @see event_set_fatal_callback + */ +typedef void (*event_fatal_cb)(int err); + +/** + Override Libevent's behavior in the event of a fatal internal error. + + By default, Libevent will call exit(1) if a programming error makes it + impossible to continue correct operation. This function allows you to supply + another callback instead. Note that if the function is ever invoked, + something is wrong with your program, or with Libevent: any subsequent calls + to Libevent may result in undefined behavior. + + Libevent will (almost) always log an _EVENT_LOG_ERR message before calling + this function; look at the last log message to see why Libevent has died. + */ +void event_set_fatal_callback(event_fatal_cb cb); + +/** + Associate a different event base with an event. + + The event to be associated must not be currently active or pending. + + @param eb the event base + @param ev the event + @return 0 on success, -1 on failure. + */ +int event_base_set(struct event_base *, struct event *); + +/** @name Loop flags + + These flags control the behavior of event_base_loop(). + */ +/**@{*/ +/** Block until we have an active event, then exit once all active events + * have had their callbacks run. */ +#define EVLOOP_ONCE 0x01 +/** Do not block: see which events are ready now, run the callbacks + * of the highest-priority ones, then exit. */ +#define EVLOOP_NONBLOCK 0x02 +/**@}*/ + +/** + Wait for events to become active, and run their callbacks. + + This is a more flexible version of event_base_dispatch(). + + By default, this loop will run the event base until either there are no more + added events, or until something calls event_base_loopbreak() or + evenet_base_loopexit(). You can override this behavior with the 'flags' + argument. + + @param eb the event_base structure returned by event_base_new() or + event_base_new_with_config() + @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK + @return 0 if successful, -1 if an error occurred, or 1 if no events were + registered. + @see event_base_loopexit(), event_base_dispatch(), EVLOOP_ONCE, + EVLOOP_NONBLOCK + */ +int event_base_loop(struct event_base *, int); + +/** + Exit the event loop after the specified time + + The next event_base_loop() iteration after the given timer expires will + complete normally (handling all queued events) then exit without + blocking for events again. + + Subsequent invocations of event_base_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @param tv the amount of time after which the loop should terminate, + or NULL to exit after running all currently active events. + @return 0 if successful, or -1 if an error occurred + @see event_base_loopbreak() + */ +int event_base_loopexit(struct event_base *, const struct timeval *); + +/** + Abort the active event_base_loop() immediately. + + event_base_loop() will abort the loop after the next event is completed; + event_base_loopbreak() is typically invoked from this event's callback. + This behavior is analogous to the "break;" statement. + + Subsequent invocations of event_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @return 0 if successful, or -1 if an error occurred + @see event_base_loopexit() + */ +int event_base_loopbreak(struct event_base *); + +/** + Checks if the event loop was told to exit by event_loopexit(). + + This function will return true for an event_base at every point after + event_loopexit() is called, until the event loop is next entered. + + @param eb the event_base structure returned by event_init() + @return true if event_base_loopexit() was called on this event base, + or 0 otherwise + @see event_base_loopexit() + @see event_base_got_break() + */ +int event_base_got_exit(struct event_base *); + +/** + Checks if the event loop was told to abort immediately by event_loopbreak(). + + This function will return true for an event_base at every point after + event_loopbreak() is called, until the event loop is next entered. + + @param eb the event_base structure returned by event_init() + @return true if event_base_loopbreak() was called on this event base, + or 0 otherwise + @see event_base_loopbreak() + @see event_base_got_exit() + */ +int event_base_got_break(struct event_base *); + +/** + * @name event flags + * + * Flags to pass to event_new(), event_assign(), event_pending(), and + * anything else with an argument of the form "short events" + */ +/**@{*/ +/** Indicates that a timeout has occurred. It's not necessary to pass + * this flag to event_for new()/event_assign() to get a timeout. */ +#define EV_TIMEOUT 0x01 +/** Wait for a socket or FD to become readable */ +#define EV_READ 0x02 +/** Wait for a socket or FD to become writeable */ +#define EV_WRITE 0x04 +/** Wait for a POSIX signal to be raised*/ +#define EV_SIGNAL 0x08 +/** + * Persistent event: won't get removed automatically when activated. + * + * When a persistent event with a timeout becomes activated, its timeout + * is reset to 0. + */ +#define EV_PERSIST 0x10 +/** Select edge-triggered behavior, if supported by the backend. */ +#define EV_ET 0x20 +/**@}*/ + +/** + @name evtimer_* macros + + Aliases for working with one-shot timer events */ +/**@{*/ +#define evtimer_assign(ev, b, cb, arg) \ + event_assign((ev), (b), -1, 0, (cb), (arg)) +#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) +#define evtimer_add(ev, tv) event_add((ev), (tv)) +#define evtimer_del(ev) event_del(ev) +#define evtimer_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv)) +#define evtimer_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + @name evsignal_* macros + + Aliases for working with signal events + */ +/**@{*/ +#define evsignal_add(ev, tv) event_add((ev), (tv)) +#define evsignal_assign(ev, b, x, cb, arg) \ + event_assign((ev), (b), (x), EV_SIGNAL|EV_PERSIST, cb, (arg)) +#define evsignal_new(b, x, cb, arg) \ + event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) +#define evsignal_del(ev) event_del(ev) +#define evsignal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) +#define evsignal_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + A callback function for an event. + + It receives three arguments: + + @param fd An fd or signal + @param events One or more EV_* flags + @param arg A user-supplied argument. + + @see event_new() + */ +typedef void (*event_callback_fn)(evutil_socket_t, short, void *); + +/** + Allocate and asssign a new event structure, ready to be added. + + The function event_new() returns a new event that can be used in + future calls to event_add() and event_del(). The fd and events + arguments determine which conditions will trigger the event; the + callback and callback_arg arguments tell Libevent what to do when the + event becomes active. + + If events contains one of EV_READ, EV_WRITE, or EV_READ|EV_WRITE, then + fd is a file descriptor or socket that should get monitored for + readiness to read, readiness to write, or readiness for either operation + (respectively). If events contains EV_SIGNAL, then fd is a signal + number to wait for. If events contains none of those flags, then the + event can be triggered only by a timeout or by manual activation with + event_active(): In this case, fd must be -1. + + The EV_PERSIST flag can also be passed in the events argument: it makes + event_add() persistent until event_del() is called. + + The EV_ET flag is compatible with EV_READ and EV_WRITE, and supported + only by certain backends. It tells Libevent to use edge-triggered + events. + + The EV_TIMEOUT flag has no effect here. + + It is okay to have multiple events all listening on the same fds; but + they must either all be edge-triggered, or all not be edge triggerd. + + When the event becomes active, the event loop will run the provided + callbuck function, with three arguments. The first will be the provided + fd value. The second will be a bitfield of the events that triggered: + EV_READ, EV_WRITE, or EV_SIGNAL. Here the EV_TIMEOUT flag indicates + that a timeout occurred, and EV_ET indicates that an edge-triggered + event occurred. The third event will be the callback_arg pointer that + you provide. + + @param base the event base to which the event should be attached. + @param fd the file descriptor or signal to be monitored, or -1. + @param events desired events to monitor: bitfield of EV_READ, EV_WRITE, + EV_SIGNAL, EV_PERSIST, EV_ET. + @param callback callback function to be invoked when the event occurs + @param callback_arg an argument to be passed to the callback function + + @return a newly allocated struct event that must later be freed with + event_free(). + @see event_free(), event_add(), event_del(), event_assign() + */ +struct event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *); + + +/** + Prepare a new, already-allocated event structure to be added. + + The function event_assign() prepares the event structure ev to be used + in future calls to event_add() and event_del(). Unlike event_new(), it + doesn't allocate memory itself: it requires that you have already + allocated a struct event, probably on the heap. Doing this will + typically make your code depend on the size of the event structure, and + thereby create incompatibility with future versions of Libevent. + + The easiest way to avoid this problem is just to use event_new() and + event_free() instead. + + A slightly harder way to future-proof your code is to use + event_get_struct_event_size() to determine the required size of an event + at runtime. + + Note that it is NOT safe to call this function on an event that is + active or pending. Doing so WILL corrupt internal data structures in + Libevent, and lead to strange, hard-to-diagnose bugs. You _can_ use + event_assign to change an existing event, but only if it is not active + or pending! + + The arguments for this function, and the behavior of the events that it + makes, are as for event_new(). + + @param ev an event struct to be modified + @param base the event base to which ev should be attached. + @param fd the file descriptor to be monitored + @param events desired events to monitor; can be EV_READ and/or EV_WRITE + @param callback callback function to be invoked when the event occurs + @param callback_arg an argument to be passed to the callback function + + @return 0 if success, or -1 on invalid arguments. + + @see event_new(), event_add(), event_del(), event_base_once(), + event_get_struct_event_size() + */ +int event_assign(struct event *, struct event_base *, evutil_socket_t, short, event_callback_fn, void *); + +/** + Deallocate a struct event * returned by event_new(). + + If the event is pending or active, first make it non-pending and + non-active. + */ +void event_free(struct event *); + +/** + Schedule a one-time event + + The function event_base_once() is similar to event_set(). However, it + schedules a callback to be called exactly once, and does not require the + caller to prepare an event structure. + + Note that in Libevent 2.0 and earlier, if the event is never triggered, + the internal memory used to hold it will never be freed. This may be + fixed in a later version of Libevent. + + @param base an event_base + @param fd a file descriptor to monitor, or -1 for no fd. + @param events event(s) to monitor; can be any of EV_READ | + EV_WRITE, or EV_TIMEOUT + @param callback callback function to be invoked when the event occurs + @param arg an argument to be passed to the callback function + @param timeout the maximum amount of time to wait for the event. NULL + makes an EV_READ/EV_WRITE event make forever; NULL makes an + EV_TIMEOUT event succees immediately. + @return 0 if successful, or -1 if an error occurred + */ +int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_fn, void *, const struct timeval *); + +/** + Add an event to the set of pending events. + + The function event_add() schedules the execution of the ev event when the + event specified in event_assign()/event_new() occurs, or when the time + specified in timeout has elapesed. If atimeout is NULL, no timeout + occurs and the function will only be + called if a matching event occurs. The event in the + ev argument must be already initialized by event_assign() or event_new() + and may not be used + in calls to event_assign() until it is no longer pending. + + If the event in the ev argument already has a scheduled timeout, calling + event_add() replaces the old timeout with the new one, or clears the old + timeout if the timeout argument is NULL. + + @param ev an event struct initialized via event_set() + @param timeout the maximum amount of time to wait for the event, or NULL + to wait forever + @return 0 if successful, or -1 if an error occurred + @see event_del(), event_assign(), event_new() + */ +int event_add(struct event *ev, const struct timeval *timeout); + +/** + Remove an event from the set of monitored events. + + The function event_del() will cancel the event in the argument ev. If the + event has already executed or has never been added the call will have no + effect. + + @param ev an event struct to be removed from the working set + @return 0 if successful, or -1 if an error occurred + @see event_add() + */ +int event_del(struct event *); + + +/** + Make an event active. + + You can use this function on a pending or a non-pending event to make it + active, so that its callback will be run by event_base_dispatch() or + event_base_loop(). + + One common use in multithreaded programs is to wake the thread running + event_base_loop() from another thread. + + @param ev an event to make active. + @param res a set of flags to pass to the event's callback. + @param ncalls an obsolete argument: this is ignored. + **/ +void event_active(struct event *ev, int res, short ncalls); + +/** + Checks if a specific event is pending or scheduled. + + @param ev an event struct previously passed to event_add() + @param events the requested event type; any of EV_TIMEOUT|EV_READ| + EV_WRITE|EV_SIGNAL + @param tv if this field is not NULL, and the event has a timeout, + this field is set to hold the time at which the timeout will + expire. + + @return true if the event is pending on any of the events in 'what', (that + is to say, it has been added), or 0 if the event is not added. + */ +int event_pending(const struct event *ev, short events, struct timeval *tv); + + +/** + Test if an event structure might be initialized. + + The event_initialized() function can be used to check if an event has been + initialized. + + Warning: This function is only useful for distinguishing a a zeroed-out + piece of memory from an initialized event, it can easily be confused by + uninitialized memory. Thus, it should ONLY be used to distinguish an + initialized event from zero. + + @param ev an event structure to be tested + @return 1 if the structure might be initialized, or 0 if it has not been + initialized + */ +int event_initialized(const struct event *ev); + +/** + Get the signal number assigned to a signal event +*/ +#define event_get_signal(ev) ((int)event_get_fd(ev)) + +/** + Get the socket or signal assigned to an event, or -1 if the event has + no socket. +*/ +evutil_socket_t event_get_fd(const struct event *ev); + +/** + Get the event_base associated with an event. +*/ +struct event_base *event_get_base(const struct event *ev); + +/** + Return the events (EV_READ, EV_WRITE, etc) assigned to an event. +*/ +short event_get_events(const struct event *ev); + +/** + Return the callback assigned to an event. +*/ +event_callback_fn event_get_callback(const struct event *ev); + +/** + Return the callback argument assigned to an event. +*/ +void *event_get_callback_arg(const struct event *ev); + +/** + Extract _all_ of arguments given to construct a given event. The + event_base is copied into *base_out, the fd is copied into *fd_out, and so + on. + + If any of the "_out" arguments is NULL, it will be ignored. + */ +void event_get_assignment(const struct event *event, + struct event_base **base_out, evutil_socket_t *fd_out, short *events_out, + event_callback_fn *callback_out, void **arg_out); + +/** + Return the size of struct event that the Libevent library was compiled + with. + + This will be NO GREATER than sizeof(struct event) if you're running with + the same version of Libevent that your application was built with, but + otherwise might not. + + Note that it might be SMALLER than sizeof(struct event) if some future + version of Libevent adds extra padding to the end of struct event. + We might do this to help ensure ABI-compatibility between different + versions of Libevent. + */ +size_t event_get_struct_event_size(void); + +/** + Get the Libevent version. + + Note that this will give you the version of the library that you're + currently linked against, not the version of the headers that you've + compiled against. + + @return a string containing the version number of Libevent +*/ +const char *event_get_version(void); + +/** + Return a numeric representation of Libevent's version. + + Note that this will give you the version of the library that you're + currently linked against, not the version of the headers you've used to + compile. + + The format uses one byte each for the major, minor, and patchlevel parts of + the version number. The low-order byte is unused. For example, version + 2.0.1-alpha has a numeric representation of 0x02000100 +*/ +ev_uint32_t event_get_version_number(void); + +/** As event_get_version, but gives the version of Libevent's headers. */ +#define LIBEVENT_VERSION _EVENT_VERSION +/** As event_get_version_number, but gives the version number of Libevent's + * headers. */ +#define LIBEVENT_VERSION_NUMBER _EVENT_NUMERIC_VERSION + +/** Largest number of priorities that Libevent can support. */ +#define EVENT_MAX_PRIORITIES 256 +/** + Set the number of different event priorities + + By default Libevent schedules all active events with the same priority. + However, some time it is desirable to process some events with a higher + priority than others. For that reason, Libevent supports strict priority + queues. Active events with a lower priority are always processed before + events with a higher priority. + + The number of different priorities can be set initially with the + event_base_priority_init() function. This function should be called + before the first call to event_base_dispatch(). The + event_priority_set() function can be used to assign a priority to an + event. By default, Libevent assigns the middle priority to all events + unless their priority is explicitly set. + + Note that urgent-priority events can starve less-urgent events: after + running all urgent-priority callbacks, Libevent checks for more urgent + events again, before running less-urgent events. Less-urgent events + will not have their callbacks run until there are no events more urgent + than them that want to be active. + + @param eb the event_base structure returned by event_base_new() + @param npriorities the maximum number of priorities + @return 0 if successful, or -1 if an error occurred + @see event_priority_set() + */ +int event_base_priority_init(struct event_base *, int); + +/** + Assign a priority to an event. + + @param ev an event struct + @param priority the new priority to be assigned + @return 0 if successful, or -1 if an error occurred + @see event_priority_init() + */ +int event_priority_set(struct event *, int); + +/** + Prepare an event_base to use a large number of timeouts with the same + duration. + + Libevent's default scheduling algorithm is optimized for having a large + number of timeouts with their durations more or less randomly + distributed. But if you have a large number of timeouts that all have + the same duration (for example, if you have a large number of + connections that all have a 10-second timeout), then you can improve + Libevent's performance by telling Libevent about it. + + To do this, call this function with the common duration. It will return a + pointer to a different, opaque timeout value. (Don't depend on its actual + contents!) When you use this timeout value in event_add(), Libevent will + schedule the event more efficiently. + + (This optimization probably will not be worthwhile until you have thousands + or tens of thousands of events with the same timeout.) + */ +const struct timeval *event_base_init_common_timeout(struct event_base *base, + const struct timeval *duration); + +#if !defined(_EVENT_DISABLE_MM_REPLACEMENT) || defined(_EVENT_IN_DOXYGEN) +/** + Override the functions that Libevent uses for memory management. + + Usually, Libevent uses the standard libc functions malloc, realloc, and + free to allocate memory. Passing replacements for those functions to + event_set_mem_functions() overrides this behavior. + + Note that all memory returned from Libevent will be allocated by the + replacement functions rather than by malloc() and realloc(). Thus, if you + have replaced those functions, it will not be appropriate to free() memory + that you get from Libevent. Instead, you must use the free_fn replacement + that you provided. + + Note also that if you are going to call this function, you should do so + before any call to any Libevent function that does allocation. + Otherwise, those funtions will allocate their memory using malloc(), but + then later free it using your provided free_fn. + + @param malloc_fn A replacement for malloc. + @param realloc_fn A replacement for realloc + @param free_fn A replacement for free. + **/ +void event_set_mem_functions( + void *(*malloc_fn)(size_t sz), + void *(*realloc_fn)(void *ptr, size_t sz), + void (*free_fn)(void *ptr)); +/** This definition is present if Libevent was built with support for + event_set_mem_functions() */ +#define EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED +#endif + +void event_base_dump_events(struct event_base *, FILE *); + +/** Sets 'tv' to the current time (as returned by gettimeofday()), + looking at the cached value in 'base' if possible, and calling + gettimeofday() or clock_gettime() as appropriate if there is no + cached time. + + Generally, this value will only be cached while actually + processing event callbacks, and may be very inaccuate if your + callbacks take a long time to execute. + + Returns 0 on success, negative on failure. + */ +int event_base_gettimeofday_cached(struct event_base *base, + struct timeval *tv); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_EVENT_H_ */ diff --git a/libevent/include/event2/event_compat.h b/libevent/include/event2/event_compat.h new file mode 100644 index 0000000..14a10e9 --- /dev/null +++ b/libevent/include/event2/event_compat.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_EVENT_COMPAT_H_ +#define _EVENT2_EVENT_COMPAT_H_ + +/** @file event2/event_compat.h + + Potentially non-threadsafe versions of the functions in event.h: provided + only for backwards compatibility. + + In the oldest versions of Libevent, event_base was not a first-class + structure. Instead, there was a single event base that every function + manipulated. Later, when separate event bases were added, the old functions + that didn't take an event_base argument needed to work by manipulating the + "current" event base. This could lead to thread-safety issues, and obscure, + hard-to-diagnose bugs. + + @deprecated All functions in this file are by definition deprecated. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + Initialize the event API. + + The event API needs to be initialized with event_init() before it can be + used. Sets the global current base that gets used for events that have no + base associated with them. + + @deprecated This function is deprecated because it replaces the "current" + event_base, and is totally unsafe for multithreaded use. The replacement + is event_base_new(). + + @see event_base_set(), event_base_new() + */ +struct event_base *event_init(void); + +/** + Loop to process events. + + Like event_base_dispatch(), but uses the "current" base. + + @deprecated This function is deprecated because it is easily confused by + multiple calls to event_init(), and because it is not safe for + multithreaded use. The replacement is event_base_dispatch(). + + @see event_base_dispatch(), event_init() + */ +int event_dispatch(void); + +/** + Handle events. + + This function behaves like event_base_loop(), but uses the "current" base + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loop(). + + @see event_base_loop(), event_init() +*/ +int event_loop(int); + + +/** + Exit the event loop after the specified time. + + This function behaves like event_base_loopexit(), except that it uses the + "current" base. + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loopexit(). + + @see event_init, event_base_loopexit() + */ +int event_loopexit(const struct timeval *); + + +/** + Abort the active event_loop() immediately. + + This function behaves like event_base_loopbreakt(), except that it uses the + "current" base. + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loopbreak(). + + @see event_base_loopbreak(), event_init() + */ +int event_loopbreak(void); + +/** + Schedule a one-time event to occur. + + @deprecated This function is obsolete, and has been replaced by + event_base_once(). Its use is deprecated because it relies on the + "current" base configured by event_init(). + + @see event_base_once() + */ +int event_once(evutil_socket_t , short, + void (*)(evutil_socket_t, short, void *), void *, const struct timeval *); + + +/** + Get the kernel event notification mechanism used by Libevent. + + @deprecated This function is obsolete, and has been replaced by + event_base_get_method(). Its use is deprecated because it relies on the + "current" base configured by event_init(). + + @see event_base_get_method() + */ +const char *event_get_method(void); + + +/** + Set the number of different event priorities. + + @deprecated This function is deprecated because it is easily confused by + multiple calls to event_init(), and because it is not safe for + multithreaded use. The replacement is event_base_priority_init(). + + @see event_base_priority_init() + */ +int event_priority_init(int); + +/** + Prepare an event structure to be added. + + @deprecated event_set() is not recommended for new code, because it requires + a subsequent call to event_base_set() to be safe under most circumstances. + Use event_assign() or event_new() instead. + */ +void event_set(struct event *, evutil_socket_t, short, void (*)(evutil_socket_t, short, void *), void *); + +#define evtimer_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg)) +#define evsignal_set(ev, x, cb, arg) \ + event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) + + +/** + @name timeout_* macros + + @deprecated These macros are deprecated because their naming is inconsistent + with the rest of Libevent. Use the evtimer_* macros instead. + @{ + */ +#define timeout_add(ev, tv) event_add((ev), (tv)) +#define timeout_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg)) +#define timeout_del(ev) event_del(ev) +#define timeout_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv)) +#define timeout_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + @name signal_* macros + + @deprecated These macros are deprecated because their naming is inconsistent + with the rest of Libevent. Use the evsignal_* macros instead. + @{ + */ +#define signal_add(ev, tv) event_add((ev), (tv)) +#define signal_set(ev, x, cb, arg) \ + event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) +#define signal_del(ev) event_del(ev) +#define signal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) +#define signal_initialized(ev) event_initialized(ev) +/**@}*/ + +#ifndef EVENT_FD +/* These macros are obsolete; use event_get_fd and event_get_signal instead. */ +#define EVENT_FD(ev) ((int)event_get_fd(ev)) +#define EVENT_SIGNAL(ev) event_get_signal(ev) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_EVENT_COMPAT_H_ */ diff --git a/libevent/include/event2/event_struct.h b/libevent/include/event2/event_struct.h new file mode 100644 index 0000000..2ed4272 --- /dev/null +++ b/libevent/include/event2/event_struct.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_EVENT_STRUCT_H_ +#define _EVENT2_EVENT_STRUCT_H_ + +/** @file event2/event_struct.h + + Structures used by event.h. Using these structures directly WILL harm + forward compatibility: be careful. + + No field declared in this file should be used directly in user code. Except + for historical reasons, these fields would not be exposed at all. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/* For evkeyvalq */ +#include + +#define EVLIST_TIMEOUT 0x01 +#define EVLIST_INSERTED 0x02 +#define EVLIST_SIGNAL 0x04 +#define EVLIST_ACTIVE 0x08 +#define EVLIST_INTERNAL 0x10 +#define EVLIST_INIT 0x80 + +/* EVLIST_X_ Private space: 0x1000-0xf000 */ +#define EVLIST_ALL (0xf000 | 0x9f) + +/* Fix so that people don't have to run with */ +#ifndef TAILQ_ENTRY +#define _EVENT_DEFINED_TQENTRY +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ + +#ifndef TAILQ_HEAD +#define _EVENT_DEFINED_TQHEAD +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; \ + struct type **tqh_last; \ +} +#endif + +struct event_base; +struct event { + TAILQ_ENTRY(event) ev_active_next; + TAILQ_ENTRY(event) ev_next; + /* for managing timeouts */ + union { + TAILQ_ENTRY(event) ev_next_with_common_timeout; + int min_heap_idx; + } ev_timeout_pos; + evutil_socket_t ev_fd; + + struct event_base *ev_base; + + union { + /* used for io events */ + struct { + TAILQ_ENTRY(event) ev_io_next; + struct timeval ev_timeout; + } ev_io; + + /* used by signal events */ + struct { + TAILQ_ENTRY(event) ev_signal_next; + short ev_ncalls; + /* Allows deletes in callback */ + short *ev_pncalls; + } ev_signal; + } _ev; + + short ev_events; + short ev_res; /* result passed to event callback */ + short ev_flags; + ev_uint8_t ev_pri; /* smaller numbers are higher priority */ + ev_uint8_t ev_closure; + struct timeval ev_timeout; + + /* allows us to adopt for different types of events */ + void (*ev_callback)(evutil_socket_t, short, void *arg); + void *ev_arg; +}; + +TAILQ_HEAD (event_list, event); + +#ifdef _EVENT_DEFINED_TQENTRY +#undef TAILQ_ENTRY +#endif + +#ifdef _EVENT_DEFINED_TQHEAD +#undef TAILQ_HEAD +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_EVENT_STRUCT_H_ */ diff --git a/libevent/include/event2/http.h b/libevent/include/event2/http.h new file mode 100644 index 0000000..c6ee1db --- /dev/null +++ b/libevent/include/event2/http.h @@ -0,0 +1,863 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_HTTP_H_ +#define _EVENT2_HTTP_H_ + +/* For int types. */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* In case we haven't included the right headers yet. */ +struct evbuffer; +struct event_base; + +/** @file event2/http.h + * + * Basic support for HTTP serving. + * + * As Libevent is a library for dealing with event notification and most + * interesting applications are networked today, I have often found the + * need to write HTTP code. The following prototypes and definitions provide + * an application with a minimal interface for making HTTP requests and for + * creating a very simple HTTP server. + */ + +/* Response codes */ +#define HTTP_OK 200 /**< request completed ok */ +#define HTTP_NOCONTENT 204 /**< request does not have content */ +#define HTTP_MOVEPERM 301 /**< the uri moved permanently */ +#define HTTP_MOVETEMP 302 /**< the uri moved temporarily */ +#define HTTP_NOTMODIFIED 304 /**< page was not modified from last */ +#define HTTP_BADREQUEST 400 /**< invalid http request was made */ +#define HTTP_NOTFOUND 404 /**< could not find content for uri */ +#define HTTP_BADMETHOD 405 /**< method not allowed for this uri */ +#define HTTP_ENTITYTOOLARGE 413 /**< */ +#define HTTP_EXPECTATIONFAILED 417 /**< we can't handle this expectation */ +#define HTTP_INTERNAL 500 /**< internal error */ +#define HTTP_NOTIMPLEMENTED 501 /**< not implemented */ +#define HTTP_SERVUNAVAIL 503 /**< the server is not available */ + +struct evhttp; +struct evhttp_request; +struct evkeyvalq; +struct evhttp_bound_socket; +struct evconnlistener; + +/** + * Create a new HTTP server. + * + * @param base (optional) the event base to receive the HTTP events + * @return a pointer to a newly initialized evhttp server structure + * @see evhttp_free() + */ +struct evhttp *evhttp_new(struct event_base *base); + +/** + * Binds an HTTP server on the specified address and port. + * + * Can be called multiple times to bind the same http server + * to multiple different ports. + * + * @param http a pointer to an evhttp object + * @param address a string containing the IP address to listen(2) on + * @param port the port number to listen on + * @return 0 on success, -1 on failure. + * @see evhttp_accept_socket() + */ +int evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port); + +/** + * Like evhttp_bind_socket(), but returns a handle for referencing the socket. + * + * The returned pointer is not valid after \a http is freed. + * + * @param http a pointer to an evhttp object + * @param address a string containing the IP address to listen(2) on + * @param port the port number to listen on + * @return Handle for the socket on success, NULL on failure. + * @see evhttp_bind_socket(), evhttp_del_accept_socket() + */ +struct evhttp_bound_socket *evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port); + +/** + * Makes an HTTP server accept connections on the specified socket. + * + * This may be useful to create a socket and then fork multiple instances + * of an http server, or when a socket has been communicated via file + * descriptor passing in situations where an http servers does not have + * permissions to bind to a low-numbered port. + * + * Can be called multiple times to have the http server listen to + * multiple different sockets. + * + * @param http a pointer to an evhttp object + * @param fd a socket fd that is ready for accepting connections + * @return 0 on success, -1 on failure. + * @see evhttp_bind_socket() + */ +int evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd); + +/** + * Like evhttp_accept_socket(), but returns a handle for referencing the socket. + * + * The returned pointer is not valid after \a http is freed. + * + * @param http a pointer to an evhttp object + * @param fd a socket fd that is ready for accepting connections + * @return Handle for the socket on success, NULL on failure. + * @see evhttp_accept_socket(), evhttp_del_accept_socket() + */ +struct evhttp_bound_socket *evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd); + +/** + * The most low-level evhttp_bind/accept method: takes an evconnlistener, and + * returns an evhttp_bound_socket. The listener will be freed when the bound + * socket is freed. + */ +struct evhttp_bound_socket *evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener); + +/** + * Return the listener used to implement a bound socket. + */ +struct evconnlistener *evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound); + +/** + * Makes an HTTP server stop accepting connections on the specified socket + * + * This may be useful when a socket has been sent via file descriptor passing + * and is no longer needed by the current process. + * + * If you created this bound socket with evhttp_bind_socket_with_handle or + * evhttp_accept_socket_with_handle, this function closes the fd you provided. + * If you created this bound socket with evhttp_bind_listener, this function + * frees the listener you provided. + * + * \a bound_socket is an invalid pointer after this call returns. + * + * @param http a pointer to an evhttp object + * @param bound_socket a handle returned by evhttp_{bind,accept}_socket_with_handle + * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle() + */ +void evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound_socket); + +/** + * Get the raw file descriptor referenced by an evhttp_bound_socket. + * + * @param bound_socket a handle returned by evhttp_{bind,accept}_socket_with_handle + * @return the file descriptor used by the bound socket + * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle() + */ +evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound_socket); + +/** + * Free the previously created HTTP server. + * + * Works only if no requests are currently being served. + * + * @param http the evhttp server object to be freed + * @see evhttp_start() + */ +void evhttp_free(struct evhttp* http); + +/** XXX Document. */ +void evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size); +/** XXX Document. */ +void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size); + +/** + Sets the what HTTP methods are supported in requests accepted by this + server, and passed to user callbacks. + + If not supported they will generate a "405 Method not allowed" response. + + By default this includes the following methods: GET, POST, HEAD, PUT, DELETE + + @param http the http server on which to set the methods + @param methods bit mask constructed from evhttp_cmd_type values +*/ +void evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods); + +/** + Set a callback for a specified URI + + @param http the http sever on which to set the callback + @param path the path for which to invoke the callback + @param cb the callback function that gets invoked on requesting path + @param cb_arg an additional context argument for the callback + @return 0 on success, -1 if the callback existed already, -2 on failure +*/ +int evhttp_set_cb(struct evhttp *http, const char *path, + void (*cb)(struct evhttp_request *, void *), void *cb_arg); + +/** Removes the callback for a specified URI */ +int evhttp_del_cb(struct evhttp *, const char *); + +/** + Set a callback for all requests that are not caught by specific callbacks + + Invokes the specified callback for all requests that do not match any of + the previously specified request paths. This is catchall for requests not + specifically configured with evhttp_set_cb(). + + @param http the evhttp server object for which to set the callback + @param cb the callback to invoke for any unmatched requests + @param arg an context argument for the callback +*/ +void evhttp_set_gencb(struct evhttp *http, + void (*cb)(struct evhttp_request *, void *), void *arg); + +/** + Adds a virtual host to the http server. + + A virtual host is a newly initialized evhttp object that has request + callbacks set on it via evhttp_set_cb() or evhttp_set_gencb(). It + most not have any listing sockets associated with it. + + If the virtual host has not been removed by the time that evhttp_free() + is called on the main http server, it will be automatically freed, too. + + It is possible to have hierarchical vhosts. For example: A vhost + with the pattern *.example.com may have other vhosts with patterns + foo.example.com and bar.example.com associated with it. + + @param http the evhttp object to which to add a virtual host + @param pattern the glob pattern against which the hostname is matched. + The match is case insensitive and follows otherwise regular shell + matching. + @param vhost the virtual host to add the regular http server. + @return 0 on success, -1 on failure + @see evhttp_remove_virtual_host() +*/ +int evhttp_add_virtual_host(struct evhttp* http, const char *pattern, + struct evhttp* vhost); + +/** + Removes a virtual host from the http server. + + @param http the evhttp object from which to remove the virtual host + @param vhost the virtual host to remove from the regular http server. + @return 0 on success, -1 on failure + @see evhttp_add_virtual_host() +*/ +int evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost); + +/** + Add a server alias to an http object. The http object can be a virtual + host or the main server. + + @param http the evhttp object + @param alias the alias to add + @see evhttp_add_remove_alias() +*/ +int evhttp_add_server_alias(struct evhttp *http, const char *alias); + +/** + Remove a server alias from an http object. + + @param http the evhttp object + @param alias the alias to remove + @see evhttp_add_server_alias() +*/ +int evhttp_remove_server_alias(struct evhttp *http, const char *alias); + +/** + * Set the timeout for an HTTP request. + * + * @param http an evhttp object + * @param timeout_in_secs the timeout, in seconds + */ +void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs); + +/* Request/Response functionality */ + +/** + * Send an HTML error message to the client. + * + * @param req a request object + * @param error the HTTP error code + * @param reason a brief explanation of the error. If this is NULL, we'll + * just use the standard meaning of the error code. + */ +void evhttp_send_error(struct evhttp_request *req, int error, + const char *reason); + +/** + * Send an HTML reply to the client. + * + * The body of the reply consists of the data in databuf. After calling + * evhttp_send_reply() databuf will be empty, but the buffer is still + * owned by the caller and needs to be deallocated by the caller if + * necessary. + * + * @param req a request object + * @param code the HTTP response code to send + * @param reason a brief message to send with the response code + * @param databuf the body of the response + */ +void evhttp_send_reply(struct evhttp_request *req, int code, + const char *reason, struct evbuffer *databuf); + +/* Low-level response interface, for streaming/chunked replies */ + +/** + Initiate a reply that uses Transfer-Encoding chunked. + + This allows the caller to stream the reply back to the client and is + useful when either not all of the reply data is immediately available + or when sending very large replies. + + The caller needs to supply data chunks with evhttp_send_reply_chunk() + and complete the reply by calling evhttp_send_reply_end(). + + @param req a request object + @param code the HTTP response code to send + @param reason a brief message to send with the response code +*/ +void evhttp_send_reply_start(struct evhttp_request *req, int code, + const char *reason); + +/** + Send another data chunk as part of an ongoing chunked reply. + + The reply chunk consists of the data in databuf. After calling + evhttp_send_reply_chunk() databuf will be empty, but the buffer is + still owned by the caller and needs to be deallocated by the caller + if necessary. + + @param req a request object + @param databuf the data chunk to send as part of the reply. +*/ +void evhttp_send_reply_chunk(struct evhttp_request *req, + struct evbuffer *databuf); +/** + Complete a chunked reply, freeing the request as appropriate. + + @param req a request object +*/ +void evhttp_send_reply_end(struct evhttp_request *req); + +/* + * Interfaces for making requests + */ + +/** The different request types supported by evhttp. These are as specified + * in RFC2616, except for PATCH which is specified by RFC5789. + * + * By default, only some of these methods are accepted and passed to user + * callbacks; use evhttp_set_allowed_methods() to change which methods + * are allowed. + */ +enum evhttp_cmd_type { + EVHTTP_REQ_GET = 1 << 0, + EVHTTP_REQ_POST = 1 << 1, + EVHTTP_REQ_HEAD = 1 << 2, + EVHTTP_REQ_PUT = 1 << 3, + EVHTTP_REQ_DELETE = 1 << 4, + EVHTTP_REQ_OPTIONS = 1 << 5, + EVHTTP_REQ_TRACE = 1 << 6, + EVHTTP_REQ_CONNECT = 1 << 7, + EVHTTP_REQ_PATCH = 1 << 8 +}; + +/** a request object can represent either a request or a reply */ +enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE }; + +/** + * Creates a new request object that needs to be filled in with the request + * parameters. The callback is executed when the request completed or an + * error occurred. + */ +struct evhttp_request *evhttp_request_new( + void (*cb)(struct evhttp_request *, void *), void *arg); + +/** + * Enable delivery of chunks to requestor. + * @param cb will be called after every read of data with the same argument + * as the completion callback. Will never be called on an empty + * response. May drain the input buffer; it will be drained + * automatically on return. + */ +void evhttp_request_set_chunked_cb(struct evhttp_request *, + void (*cb)(struct evhttp_request *, void *)); + +/** Frees the request object and removes associated events. */ +void evhttp_request_free(struct evhttp_request *req); + +struct evdns_base; + +/** + * A connection object that can be used to for making HTTP requests. The + * connection object tries to resolve address and establish the connection + * when it is given an http request object. + * + * @param base the event_base to use for handling the connection + * @param dnsbase the dns_base to use for resolving host names; if not + * specified host name resolution will block. + * @param address the address to which to connect + * @param port the port to connect to + * @return an evhttp_connection object that can be used for making requests + */ +struct evhttp_connection *evhttp_connection_base_new( + struct event_base *base, struct evdns_base *dnsbase, + const char *address, unsigned short port); + +/** + * Return the bufferevent that an evhttp_connection is using. + */ +struct bufferevent *evhttp_connection_get_bufferevent( + struct evhttp_connection *evcon); + +/** Takes ownership of the request object + * + * Can be used in a request callback to keep onto the request until + * evhttp_request_free() is explicitly called by the user. + */ +void evhttp_request_own(struct evhttp_request *req); + +/** Returns 1 if the request is owned by the user */ +int evhttp_request_is_owned(struct evhttp_request *req); + +/** + * Returns the connection object associated with the request or NULL + * + * The user needs to either free the request explicitly or call + * evhttp_send_reply_end(). + */ +struct evhttp_connection *evhttp_request_get_connection(struct evhttp_request *req); + +/** + * Returns the underlying event_base for this connection + */ +struct event_base *evhttp_connection_get_base(struct evhttp_connection *req); + +void evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon, + ev_ssize_t new_max_headers_size); + +void evhttp_connection_set_max_body_size(struct evhttp_connection* evcon, + ev_ssize_t new_max_body_size); + +/** Frees an http connection */ +void evhttp_connection_free(struct evhttp_connection *evcon); + +/** sets the ip address from which http connections are made */ +void evhttp_connection_set_local_address(struct evhttp_connection *evcon, + const char *address); + +/** sets the local port from which http connections are made */ +void evhttp_connection_set_local_port(struct evhttp_connection *evcon, + ev_uint16_t port); + +/** Sets the timeout for events related to this connection */ +void evhttp_connection_set_timeout(struct evhttp_connection *evcon, + int timeout_in_secs); + +/** Sets the retry limit for this connection - -1 repeats indefinitely */ +void evhttp_connection_set_retries(struct evhttp_connection *evcon, + int retry_max); + +/** Set a callback for connection close. */ +void evhttp_connection_set_closecb(struct evhttp_connection *evcon, + void (*)(struct evhttp_connection *, void *), void *); + +/** Get the remote address and port associated with this connection. */ +void evhttp_connection_get_peer(struct evhttp_connection *evcon, + char **address, ev_uint16_t *port); + +/** + Make an HTTP request over the specified connection. + + The connection gets ownership of the request. On failure, the + request object is no longer valid as it has been freed. + + @param evcon the evhttp_connection object over which to send the request + @param req the previously created and configured request object + @param type the request type EVHTTP_REQ_GET, EVHTTP_REQ_POST, etc. + @param uri the URI associated with the request + @return 0 on success, -1 on failure + @see evhttp_cancel_request() +*/ +int evhttp_make_request(struct evhttp_connection *evcon, + struct evhttp_request *req, + enum evhttp_cmd_type type, const char *uri); + +/** + Cancels a pending HTTP request. + + Cancels an ongoing HTTP request. The callback associated with this request + is not executed and the request object is freed. If the request is + currently being processed, e.g. it is ongoing, the corresponding + evhttp_connection object is going to get reset. + + A request cannot be canceled if its callback has executed already. A request + may be canceled reentrantly from its chunked callback. + + @param req the evhttp_request to cancel; req becomes invalid after this call. +*/ +void evhttp_cancel_request(struct evhttp_request *req); + +/** + * A structure to hold a parsed URI or Relative-Ref conforming to RFC3986. + */ +struct evhttp_uri; + +/** Returns the request URI */ +const char *evhttp_request_get_uri(const struct evhttp_request *req); +/** Returns the request URI (parsed) */ +const struct evhttp_uri *evhttp_request_get_evhttp_uri(const struct evhttp_request *req); +/** Returns the request command */ +enum evhttp_cmd_type evhttp_request_get_command(const struct evhttp_request *req); + +int evhttp_request_get_response_code(const struct evhttp_request *req); + +/** Returns the input headers */ +struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req); +/** Returns the output headers */ +struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req); +/** Returns the input buffer */ +struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req); +/** Returns the output buffer */ +struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req); +/** Returns the host associated with the request. If a client sends an absolute + URI, the host part of that is preferred. Otherwise, the input headers are + searched for a Host: header. NULL is returned if no absolute URI or Host: + header is provided. */ +const char *evhttp_request_get_host(struct evhttp_request *req); + +/* Interfaces for dealing with HTTP headers */ + +/** + Finds the value belonging to a header. + + @param headers the evkeyvalq object in which to find the header + @param key the name of the header to find + @returns a pointer to the value for the header or NULL if the header + count not be found. + @see evhttp_add_header(), evhttp_remove_header() +*/ +const char *evhttp_find_header(const struct evkeyvalq *headers, + const char *key); + +/** + Removes a header from a list of existing headers. + + @param headers the evkeyvalq object from which to remove a header + @param key the name of the header to remove + @returns 0 if the header was removed, -1 otherwise. + @see evhttp_find_header(), evhttp_add_header() +*/ +int evhttp_remove_header(struct evkeyvalq *headers, const char *key); + +/** + Adds a header to a list of existing headers. + + @param headers the evkeyvalq object to which to add a header + @param key the name of the header + @param value the value belonging to the header + @returns 0 on success, -1 otherwise. + @see evhttp_find_header(), evhttp_clear_headers() +*/ +int evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value); + +/** + Removes all headers from the header list. + + @param headers the evkeyvalq object from which to remove all headers +*/ +void evhttp_clear_headers(struct evkeyvalq *headers); + +/* Miscellaneous utility functions */ + + +/** + Helper function to encode a string for inclusion in a URI. All + characters are replaced by their hex-escaped (%22) equivalents, + except for characters explicitly unreserved by RFC3986 -- that is, + ASCII alphanumeric characters, hyphen, dot, underscore, and tilde. + + The returned string must be freed by the caller. + + @param str an unencoded string + @return a newly allocated URI-encoded string or NULL on failure + */ +char *evhttp_encode_uri(const char *str); + +/** + As evhttp_encode_uri, but if 'size' is nonnegative, treat the string + as being 'size' bytes long. This allows you to encode strings that + may contain 0-valued bytes. + + The returned string must be freed by the caller. + + @param str an unencoded string + @param size the length of the string to encode, or -1 if the string + is NUL-terminated + @param space_to_plus if true, space characters in 'str' are encoded + as +, not %20. + @return a newly allocate URI-encoded string, or NULL on failure. + */ +char *evhttp_uriencode(const char *str, ev_ssize_t size, int space_to_plus); + +/** + Helper function to sort of decode a URI-encoded string. Unlike + evhttp_get_decoded_uri, it decodes all plus characters that appear + _after_ the first question mark character, but no plusses that occur + before. This is not a good way to decode URIs in whole or in part. + + The returned string must be freed by the caller + + @deprecated This function is deprecated; you probably want to use + evhttp_get_decoded_uri instead. + + @param uri an encoded URI + @return a newly allocated unencoded URI or NULL on failure + */ +char *evhttp_decode_uri(const char *uri); + +/** + Helper function to decode a URI-escaped string or HTTP parameter. + + If 'decode_plus' is 1, then we decode the string as an HTTP parameter + value, and convert all plus ('+') characters to spaces. If + 'decode_plus' is 0, we leave all plus characters unchanged. + + The returned string must be freed by the caller. + + @param uri a URI-encode encoded URI + @param decode_plus determines whether we convert '+' to sapce. + @param size_out if size_out is not NULL, *size_out is set to the size of the + returned string + @return a newly allocated unencoded URI or NULL on failure + */ +char *evhttp_uridecode(const char *uri, int decode_plus, + size_t *size_out); + +/** + Helper function to parse out arguments in a query. + + Parsing a URI like + + http://foo.com/?q=test&s=some+thing + + will result in two entries in the key value queue. + + The first entry is: key="q", value="test" + The second entry is: key="s", value="some thing" + + @deprecated This function is deprecated as of Libevent 2.0.9. Use + evhttp_uri_parse and evhttp_parse_query_str instead. + + @param uri the request URI + @param headers the head of the evkeyval queue + @return 0 on success, -1 on failure + */ +int evhttp_parse_query(const char *uri, struct evkeyvalq *headers); + +/** + Helper function to parse out arguments from the query portion of an + HTTP URI. + + Parsing a query string like + + q=test&s=some+thing + + will result in two entries in the key value queue. + + The first entry is: key="q", value="test" + The second entry is: key="s", value="some thing" + + @param query_parse the query portion of the URI + @param headers the head of the evkeyval queue + @return 0 on success, -1 on failure + */ +int evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers); + +/** + * Escape HTML character entities in a string. + * + * Replaces <, >, ", ' and & with <, >, ", + * ' and & correspondingly. + * + * The returned string needs to be freed by the caller. + * + * @param html an unescaped HTML string + * @return an escaped HTML string or NULL on error + */ +char *evhttp_htmlescape(const char *html); + +/** + * Return a new empty evhttp_uri with no fields set. + */ +struct evhttp_uri *evhttp_uri_new(void); + +/** + * Changes the flags set on a given URI. See EVHTTP_URI_* for + * a list of flags. + **/ +void evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags); + +/** Return the scheme of an evhttp_uri, or NULL if there is no scheme has + * been set and the evhttp_uri contains a Relative-Ref. */ +const char *evhttp_uri_get_scheme(const struct evhttp_uri *uri); +/** + * Return the userinfo part of an evhttp_uri, or NULL if it has no userinfo + * set. + */ +const char *evhttp_uri_get_userinfo(const struct evhttp_uri *uri); +/** + * Return the host part of an evhttp_uri, or NULL if it has no host set. + * The host may either be a regular hostname (conforming to the RFC 3986 + * "regname" production), or an IPv4 address, or the empty string, or a + * bracketed IPv6 address, or a bracketed 'IP-Future' address. + * + * Note that having a NULL host means that the URI has no authority + * section, but having an empty-string host means that the URI has an + * authority section with no host part. For example, + * "mailto:user@example.com" has a host of NULL, but "file:///etc/motd" + * has a host of "". + */ +const char *evhttp_uri_get_host(const struct evhttp_uri *uri); +/** Return the port part of an evhttp_uri, or -1 if there is no port set. */ +int evhttp_uri_get_port(const struct evhttp_uri *uri); +/** Return the path part of an evhttp_uri, or NULL if it has no path set */ +const char *evhttp_uri_get_path(const struct evhttp_uri *uri); +/** Return the query part of an evhttp_uri (excluding the leading "?"), or + * NULL if it has no query set */ +const char *evhttp_uri_get_query(const struct evhttp_uri *uri); +/** Return the fragment part of an evhttp_uri (excluding the leading "#"), + * or NULL if it has no fragment set */ +const char *evhttp_uri_get_fragment(const struct evhttp_uri *uri); + +/** Set the scheme of an evhttp_uri, or clear the scheme if scheme==NULL. + * Returns 0 on success, -1 if scheme is not well-formed. */ +int evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme); +/** Set the userinfo of an evhttp_uri, or clear the userinfo if userinfo==NULL. + * Returns 0 on success, -1 if userinfo is not well-formed. */ +int evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo); +/** Set the host of an evhttp_uri, or clear the host if host==NULL. + * Returns 0 on success, -1 if host is not well-formed. */ +int evhttp_uri_set_host(struct evhttp_uri *uri, const char *host); +/** Set the port of an evhttp_uri, or clear the port if port==-1. + * Returns 0 on success, -1 if port is not well-formed. */ +int evhttp_uri_set_port(struct evhttp_uri *uri, int port); +/** Set the path of an evhttp_uri, or clear the path if path==NULL. + * Returns 0 on success, -1 if path is not well-formed. */ +int evhttp_uri_set_path(struct evhttp_uri *uri, const char *path); +/** Set the query of an evhttp_uri, or clear the query if query==NULL. + * The query should not include a leading "?". + * Returns 0 on success, -1 if query is not well-formed. */ +int evhttp_uri_set_query(struct evhttp_uri *uri, const char *query); +/** Set the fragment of an evhttp_uri, or clear the fragment if fragment==NULL. + * The fragment should not include a leading "#". + * Returns 0 on success, -1 if fragment is not well-formed. */ +int evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment); + +/** + * Helper function to parse a URI-Reference as specified by RFC3986. + * + * This function matches the URI-Reference production from RFC3986, + * which includes both URIs like + * + * scheme://[[userinfo]@]foo.com[:port]]/[path][?query][#fragment] + * + * and relative-refs like + * + * [path][?query][#fragment] + * + * Any optional elements portions not present in the original URI are + * left set to NULL in the resulting evhttp_uri. If no port is + * specified, the port is set to -1. + * + * Note that no decoding is performed on percent-escaped characters in + * the string; if you want to parse them, use evhttp_uridecode or + * evhttp_parse_query_str as appropriate. + * + * Note also that most URI schemes will have additional constraints that + * this function does not know about, and cannot check. For example, + * mailto://www.example.com/cgi-bin/fortune.pl is not a reasonable + * mailto url, http://www.example.com:99999/ is not a reasonable HTTP + * URL, and ftp:username@example.com is not a reasonable FTP URL. + * Nevertheless, all of these URLs conform to RFC3986, and this function + * accepts all of them as valid. + * + * @param source_uri the request URI + * @param flags Zero or more EVHTTP_URI_* flags to affect the behavior + * of the parser. + * @return uri container to hold parsed data, or NULL if there is error + * @see evhttp_uri_free() + */ +struct evhttp_uri *evhttp_uri_parse_with_flags(const char *source_uri, + unsigned flags); + +/** Tolerate URIs that do not conform to RFC3986. + * + * Unfortunately, some HTTP clients generate URIs that, according to RFC3986, + * are not conformant URIs. If you need to support these URIs, you can + * do so by passing this flag to evhttp_uri_parse_with_flags. + * + * Currently, these changes are: + *
    + *
  • Nonconformant URIs are allowed to contain otherwise unreasonable + * characters in their path, query, and fragment components. + *
+ */ +#define EVHTTP_URI_NONCONFORMANT 0x01 + +/** Alias for evhttp_uri_parse_with_flags(source_uri, 0) */ +struct evhttp_uri *evhttp_uri_parse(const char *source_uri); + +/** + * Free all memory allocated for a parsed uri. Only use this for URIs + * generated by evhttp_uri_parse. + * + * @param uri container with parsed data + * @see evhttp_uri_parse() + */ +void evhttp_uri_free(struct evhttp_uri *uri); + +/** + * Join together the uri parts from parsed data to form a URI-Reference. + * + * Note that no escaping of reserved characters is done on the members + * of the evhttp_uri, so the generated string might not be a valid URI + * unless the members of evhttp_uri are themselves valid. + * + * @param uri container with parsed data + * @param buf destination buffer + * @param limit destination buffer size + * @return an joined uri as string or NULL on error + * @see evhttp_uri_parse() + */ +char *evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_HTTP_H_ */ diff --git a/libevent/include/event2/http_compat.h b/libevent/include/event2/http_compat.h new file mode 100644 index 0000000..9e902a4 --- /dev/null +++ b/libevent/include/event2/http_compat.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_HTTP_COMPAT_H_ +#define _EVENT2_HTTP_COMPAT_H_ + +/** @file event2/http_compat.h + + Potentially non-threadsafe versions of the functions in http.h: provided + only for backwards compatibility. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + * Start an HTTP server on the specified address and port + * + * @deprecated It does not allow an event base to be specified + * + * @param address the address to which the HTTP server should be bound + * @param port the port number on which the HTTP server should listen + * @return an struct evhttp object + */ +struct evhttp *evhttp_start(const char *address, unsigned short port); + +/** + * A connection object that can be used to for making HTTP requests. The + * connection object tries to establish the connection when it is given an + * http request object. + * + * @deprecated It does not allow an event base to be specified + */ +struct evhttp_connection *evhttp_connection_new( + const char *address, unsigned short port); + +/** + * Associates an event base with the connection - can only be called + * on a freshly created connection object that has not been used yet. + * + * @deprecated XXXX Why? + */ +void evhttp_connection_set_base(struct evhttp_connection *evcon, + struct event_base *base); + + +/** Returns the request URI */ +#define evhttp_request_uri evhttp_request_get_uri + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_EVENT_COMPAT_H_ */ diff --git a/libevent/include/event2/http_struct.h b/libevent/include/event2/http_struct.h new file mode 100644 index 0000000..41a92a9 --- /dev/null +++ b/libevent/include/event2/http_struct.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_HTTP_STRUCT_H_ +#define _EVENT2_HTTP_STRUCT_H_ + +/** @file event2/http_struct.h + + Data structures for http. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + * the request structure that a server receives. + * WARNING: expect this structure to change. I will try to provide + * reasonable accessors. + */ +struct evhttp_request { +#if defined(TAILQ_ENTRY) + TAILQ_ENTRY(evhttp_request) next; +#else +struct { + struct evhttp_request *tqe_next; + struct evhttp_request **tqe_prev; +} next; +#endif + + /* the connection object that this request belongs to */ + struct evhttp_connection *evcon; + int flags; +/** The request obj owns the evhttp connection and needs to free it */ +#define EVHTTP_REQ_OWN_CONNECTION 0x0001 +/** Request was made via a proxy */ +#define EVHTTP_PROXY_REQUEST 0x0002 +/** The request object is owned by the user; the user must free it */ +#define EVHTTP_USER_OWNED 0x0004 +/** The request will be used again upstack; freeing must be deferred */ +#define EVHTTP_REQ_DEFER_FREE 0x0008 +/** The request should be freed upstack */ +#define EVHTTP_REQ_NEEDS_FREE 0x0010 + + struct evkeyvalq *input_headers; + struct evkeyvalq *output_headers; + + /* address of the remote host and the port connection came from */ + char *remote_host; + ev_uint16_t remote_port; + + /* cache of the hostname for evhttp_request_get_host */ + char *host_cache; + + enum evhttp_request_kind kind; + enum evhttp_cmd_type type; + + size_t headers_size; + size_t body_size; + + char *uri; /* uri after HTTP request was parsed */ + struct evhttp_uri *uri_elems; /* uri elements */ + + char major; /* HTTP Major number */ + char minor; /* HTTP Minor number */ + + int response_code; /* HTTP Response code */ + char *response_code_line; /* Readable response */ + + struct evbuffer *input_buffer; /* read data */ + ev_int64_t ntoread; + unsigned chunked:1, /* a chunked request */ + userdone:1; /* the user has sent all data */ + + struct evbuffer *output_buffer; /* outgoing post or data */ + + /* Callback */ + void (*cb)(struct evhttp_request *, void *); + void *cb_arg; + + /* + * Chunked data callback - call for each completed chunk if + * specified. If not specified, all the data is delivered via + * the regular callback. + */ + void (*chunk_cb)(struct evhttp_request *, void *); +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_HTTP_STRUCT_H_ */ + diff --git a/libevent/include/event2/keyvalq_struct.h b/libevent/include/event2/keyvalq_struct.h new file mode 100644 index 0000000..ab8040b --- /dev/null +++ b/libevent/include/event2/keyvalq_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_EVENT_KEYVALQ_STRUCT_H_ +#define _EVENT2_EVENT_KEYVALQ_STRUCT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Fix so that people don't have to run with */ +/* XXXX This code is duplicated with event_struct.h */ +#ifndef TAILQ_ENTRY +#define _EVENT_DEFINED_TQENTRY +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ + +#ifndef TAILQ_HEAD +#define _EVENT_DEFINED_TQHEAD +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; \ + struct type **tqh_last; \ +} +#endif + +/* + * Key-Value pairs. Can be used for HTTP headers but also for + * query argument parsing. + */ +struct evkeyval { + TAILQ_ENTRY(evkeyval) next; + + char *key; + char *value; +}; + +TAILQ_HEAD (evkeyvalq, evkeyval); + +/* XXXX This code is duplicated with event_struct.h */ +#ifdef _EVENT_DEFINED_TQENTRY +#undef TAILQ_ENTRY +#endif + +#ifdef _EVENT_DEFINED_TQHEAD +#undef TAILQ_HEAD +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libevent/include/event2/listener.h b/libevent/include/event2/listener.h new file mode 100644 index 0000000..2dc64be --- /dev/null +++ b/libevent/include/event2/listener.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_LISTENER_H_ +#define _EVENT2_LISTENER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct sockaddr; +struct evconnlistener; + +/** + A callback that we invoke when a listener has a new connection. + + @param listener The evconnlistener + @param fd The new file descriptor + @param addr The source address of the connection + @param socklen The length of addr + @param user_arg the pointer passed to evconnlistener_new() + */ +typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *); + +/** + A callback that we invoke when a listener encounters a non-retriable error. + + @param listener The evconnlistener + @param user_arg the pointer passed to evconnlistener_new() + */ +typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *); + +/** Flag: Indicates that we should not make incoming sockets nonblocking + * before passing them to the callback. */ +#define LEV_OPT_LEAVE_SOCKETS_BLOCKING (1u<<0) +/** Flag: Indicates that freeing the listener should close the underlying + * socket. */ +#define LEV_OPT_CLOSE_ON_FREE (1u<<1) +/** Flag: Indicates that we should set the close-on-exec flag, if possible */ +#define LEV_OPT_CLOSE_ON_EXEC (1u<<2) +/** Flag: Indicates that we should disable the timeout (if any) between when + * this socket is closed and when we can listen again on the same port. */ +#define LEV_OPT_REUSEABLE (1u<<3) +/** Flag: Indicates that the listener should be locked so it's safe to use + * from multiple threadcs at once. */ +#define LEV_OPT_THREADSAFE (1u<<4) + +/** + Allocate a new evconnlistener object to listen for incoming TCP connections + on a given file descriptor. + + @param base The event base to associate the listener with. + @param cb A callback to be invoked when a new connection arrives. If the + callback is NULL, the listener will be treated as disabled until the + callback is set. + @param ptr A user-supplied pointer to give to the callback. + @param flags Any number of LEV_OPT_* flags + @param backlog Passed to the listen() call to determine the length of the + acceptable connection backlog. Set to -1 for a reasonable default. + Set to 0 if the socket is already listening. + @param fd The file descriptor to listen on. It must be a nonblocking + file descriptor, and it should already be bound to an appropriate + port and address. +*/ +struct evconnlistener *evconnlistener_new(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + evutil_socket_t fd); +/** + Allocate a new evconnlistener object to listen for incoming TCP connections + on a given address. + + @param base The event base to associate the listener with. + @param cb A callback to be invoked when a new connection arrives. If the + callback is NULL, the listener will be treated as disabled until the + callback is set. + @param ptr A user-supplied pointer to give to the callback. + @param flags Any number of LEV_OPT_* flags + @param backlog Passed to the listen() call to determine the length of the + acceptable connection backlog. Set to -1 for a reasonable default. + @param addr The address to listen for connections on. + @param socklen The length of the address. + */ +struct evconnlistener *evconnlistener_new_bind(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + const struct sockaddr *sa, int socklen); +/** + Disable and deallocate an evconnlistener. + */ +void evconnlistener_free(struct evconnlistener *lev); +/** + Re-enable an evconnlistener that has been disabled. + */ +int evconnlistener_enable(struct evconnlistener *lev); +/** + Stop listening for connections on an evconnlistener. + */ +int evconnlistener_disable(struct evconnlistener *lev); + +/** Return an evconnlistener's associated event_base. */ +struct event_base *evconnlistener_get_base(struct evconnlistener *lev); + +/** Return the socket that an evconnlistner is listening on. */ +evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev); + +/** Change the callback on the listener to cb and its user_data to arg. + */ +void evconnlistener_set_cb(struct evconnlistener *lev, + evconnlistener_cb cb, void *arg); + +/** Set an evconnlistener's error callback. */ +void evconnlistener_set_error_cb(struct evconnlistener *lev, + evconnlistener_errorcb errorcb); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libevent/include/event2/rpc.h b/libevent/include/event2/rpc.h new file mode 100644 index 0000000..5272edc --- /dev/null +++ b/libevent/include/event2/rpc.h @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_RPC_H_ +#define _EVENT2_RPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file rpc.h + * + * This header files provides basic support for an RPC server and client. + * + * To support RPCs in a server, every supported RPC command needs to be + * defined and registered. + * + * EVRPC_HEADER(SendCommand, Request, Reply); + * + * SendCommand is the name of the RPC command. + * Request is the name of a structure generated by event_rpcgen.py. + * It contains all parameters relating to the SendCommand RPC. The + * server needs to fill in the Reply structure. + * Reply is the name of a structure generated by event_rpcgen.py. It + * contains the answer to the RPC. + * + * To register an RPC with an HTTP server, you need to first create an RPC + * base with: + * + * struct evrpc_base *base = evrpc_init(http); + * + * A specific RPC can then be registered with + * + * EVRPC_REGISTER(base, SendCommand, Request, Reply, FunctionCB, arg); + * + * when the server receives an appropriately formatted RPC, the user callback + * is invoked. The callback needs to fill in the reply structure. + * + * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg); + * + * To send the reply, call EVRPC_REQUEST_DONE(rpc); + * + * See the regression test for an example. + */ + +/** + Determines if the member has been set in the message + + @param msg the message to inspect + @param member the member variable to test for presences + @return 1 if it's present or 0 otherwise. +*/ +#define EVTAG_HAS(msg, member) \ + ((msg)->member##_set == 1) + +#ifndef _EVENT2_RPC_COMPAT_H_ + +/** + Assigns a value to the member in the message. + + @param msg the message to which to assign a value + @param member the name of the member variable + @param value the value to assign +*/ +#define EVTAG_ASSIGN(msg, member, value) \ + (*(msg)->base->member##_assign)((msg), (value)) +/** + Assigns a value to the member in the message. + + @param msg the message to which to assign a value + @param member the name of the member variable + @param value the value to assign + @param len the length of the value +*/ +#define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len) \ + (*(msg)->base->member##_assign)((msg), (value), (len)) +/** + Returns the value for a member. + + @param msg the message from which to get the value + @param member the name of the member variable + @param pvalue a pointer to the variable to hold the value + @return 0 on success, -1 otherwise. +*/ +#define EVTAG_GET(msg, member, pvalue) \ + (*(msg)->base->member##_get)((msg), (pvalue)) +/** + Returns the value for a member. + + @param msg the message from which to get the value + @param member the name of the member variable + @param pvalue a pointer to the variable to hold the value + @param plen a pointer to the length of the value + @return 0 on success, -1 otherwise. +*/ +#define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen) \ + (*(msg)->base->member##_get)((msg), (pvalue), (plen)) + +#endif /* _EVENT2_RPC_COMPAT_H_ */ + +/** + Adds a value to an array. +*/ +#define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \ + (*(msg)->base->member##_add)((msg), (value)) +/** + Allocates a new entry in the array and returns it. +*/ +#define EVTAG_ARRAY_ADD(msg, member) \ + (*(msg)->base->member##_add)(msg) +/** + Gets a variable at the specified offset from the array. +*/ +#define EVTAG_ARRAY_GET(msg, member, offset, pvalue) \ + (*(msg)->base->member##_get)((msg), (offset), (pvalue)) +/** + Returns the number of entries in the array. +*/ +#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length) + + +struct evbuffer; +struct event_base; +struct evrpc_req_generic; +struct evrpc_request_wrapper; +struct evrpc; + +/** The type of a specific RPC Message + * + * @param rpcname the name of the RPC message + */ +#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname + +struct evhttp_request; +struct evrpc_status; +struct evrpc_hook_meta; + +/** Creates the definitions and prototypes for an RPC + * + * You need to use EVRPC_HEADER to create structures and function prototypes + * needed by the server and client implementation. The structures have to be + * defined in an .rpc file and converted to source code via event_rpcgen.py + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @see EVRPC_GENERATE() + */ +#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \ +EVRPC_STRUCT(rpcname) { \ + struct evrpc_hook_meta *hook_meta; \ + struct reqstruct* request; \ + struct rplystruct* reply; \ + struct evrpc* rpc; \ + struct evhttp_request* http_req; \ + struct evbuffer* rpc_data; \ +}; \ +int evrpc_send_request_##rpcname(struct evrpc_pool *, \ + struct reqstruct *, struct rplystruct *, \ + void (*)(struct evrpc_status *, \ + struct reqstruct *, struct rplystruct *, void *cbarg), \ + void *); + +struct evrpc_pool; + +/** use EVRPC_GENERATE instead */ +struct evrpc_request_wrapper *evrpc_make_request_ctx( + struct evrpc_pool *pool, void *request, void *reply, + const char *rpcname, + void (*req_marshal)(struct evbuffer*, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *), + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cbarg); + +/** Creates a context structure that contains rpc specific information. + * + * EVRPC_MAKE_CTX is used to populate a RPC specific context that + * contains information about marshaling the RPC data types. + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @param pool the evrpc_pool over which to make the request + * @param request a pointer to the RPC request structure object + * @param reply a pointer to the RPC reply structure object + * @param cb the callback function to call when the RPC has completed + * @param cbarg the argument to supply to the callback + */ +#define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \ + pool, request, reply, cb, cbarg) \ + evrpc_make_request_ctx(pool, request, reply, \ + #rpcname, \ + (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ + (void (*)(void *))rplystruct##_clear, \ + (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \ + (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ + cbarg) + +/** Generates the code for receiving and sending an RPC message + * + * EVRPC_GENERATE is used to create the code corresponding to sending + * and receiving a particular RPC message + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @see EVRPC_HEADER() + */ +#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \ + int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \ + struct reqstruct *request, struct rplystruct *reply, \ + void (*cb)(struct evrpc_status *, \ + struct reqstruct *, struct rplystruct *, void *cbarg), \ + void *cbarg) { \ + return evrpc_send_request_generic(pool, request, reply, \ + (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ + cbarg, \ + #rpcname, \ + (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ + (void (*)(void *))rplystruct##_clear, \ + (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \ +} + +/** Provides access to the HTTP request object underlying an RPC + * + * Access to the underlying http object; can be used to look at headers or + * for getting the remote ip address + * + * @param rpc_req the rpc request structure provided to the server callback + * @return an struct evhttp_request object that can be inspected for + * HTTP headers or sender information. + */ +#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req + +/** completes the server response to an rpc request */ +void evrpc_request_done(struct evrpc_req_generic *req); + +/** accessors for request and reply */ +void *evrpc_get_request(struct evrpc_req_generic *req); +void *evrpc_get_reply(struct evrpc_req_generic *req); + +/** Creates the reply to an RPC request + * + * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected + * to have been filled in. The request and reply pointers become invalid + * after this call has finished. + * + * @param rpc_req the rpc request structure provided to the server callback + */ +#define EVRPC_REQUEST_DONE(rpc_req) do { \ + struct evrpc_req_generic *_req = (struct evrpc_req_generic *)(rpc_req); \ + evrpc_request_done(_req); \ +} while (0) + + +struct evrpc_base; +struct evhttp; + +/* functions to start up the rpc system */ + +/** Creates a new rpc base from which RPC requests can be received + * + * @param server a pointer to an existing HTTP server + * @return a newly allocated evrpc_base struct + * @see evrpc_free() + */ +struct evrpc_base *evrpc_init(struct evhttp *server); + +/** + * Frees the evrpc base + * + * For now, you are responsible for making sure that no rpcs are ongoing. + * + * @param base the evrpc_base object to be freed + * @see evrpc_init + */ +void evrpc_free(struct evrpc_base *base); + +/** register RPCs with the HTTP Server + * + * registers a new RPC with the HTTP server, each RPC needs to have + * a unique name under which it can be identified. + * + * @param base the evrpc_base structure in which the RPC should be + * registered. + * @param name the name of the RPC + * @param request the name of the RPC request structure + * @param reply the name of the RPC reply structure + * @param callback the callback that should be invoked when the RPC + * is received. The callback has the following prototype + * void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg) + * @param cbarg an additional parameter that can be passed to the callback. + * The parameter can be used to carry around state. + */ +#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \ + evrpc_register_generic(base, #name, \ + (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \ + (void *(*)(void *))request##_new, NULL, \ + (void (*)(void *))request##_free, \ + (int (*)(void *, struct evbuffer *))request##_unmarshal, \ + (void *(*)(void *))reply##_new, NULL, \ + (void (*)(void *))reply##_free, \ + (int (*)(void *))reply##_complete, \ + (void (*)(struct evbuffer *, void *))reply##_marshal) + +/** + Low level function for registering an RPC with a server. + + Use EVRPC_REGISTER() instead. + + @see EVRPC_REGISTER() +*/ +int evrpc_register_rpc(struct evrpc_base *, struct evrpc *, + void (*)(struct evrpc_req_generic*, void *), void *); + +/** + * Unregisters an already registered RPC + * + * @param base the evrpc_base object from which to unregister an RPC + * @param name the name of the rpc to unregister + * @return -1 on error or 0 when successful. + * @see EVRPC_REGISTER() + */ +#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name) + +int evrpc_unregister_rpc(struct evrpc_base *base, const char *name); + +/* + * Client-side RPC support + */ + +struct evhttp_connection; +struct evrpc_status; + +/** launches an RPC and sends it to the server + * + * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server. + * + * @param name the name of the RPC + * @param pool the evrpc_pool that contains the connection objects over which + * the request should be sent. + * @param request a pointer to the RPC request structure - it contains the + * data to be sent to the server. + * @param reply a pointer to the RPC reply structure. It is going to be filled + * if the request was answered successfully + * @param cb the callback to invoke when the RPC request has been answered + * @param cbarg an additional argument to be passed to the client + * @return 0 on success, -1 on failure + */ +#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \ + evrpc_send_request_##name((pool), (request), (reply), (cb), (cbarg)) + +/** + Makes an RPC request based on the provided context. + + This is a low-level function and should not be used directly + unless a custom context object is provided. Use EVRPC_MAKE_REQUEST() + instead. + + @param ctx a context from EVRPC_MAKE_CTX() + @returns 0 on success, -1 otherwise. + @see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX() +*/ +int evrpc_make_request(struct evrpc_request_wrapper *ctx); + +/** creates an rpc connection pool + * + * a pool has a number of connections associated with it. + * rpc requests are always made via a pool. + * + * @param base a pointer to an struct event_based object; can be left NULL + * in singled-threaded applications + * @return a newly allocated struct evrpc_pool object + * @see evrpc_pool_free() + */ +struct evrpc_pool *evrpc_pool_new(struct event_base *base); +/** frees an rpc connection pool + * + * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new() + * @see evrpc_pool_new() + */ +void evrpc_pool_free(struct evrpc_pool *pool); + +/** + * Adds a connection over which rpc can be dispatched to the pool. + * + * The connection object must have been newly created. + * + * @param pool the pool to which to add the connection + * @param evcon the connection to add to the pool. + */ +void evrpc_pool_add_connection(struct evrpc_pool *pool, + struct evhttp_connection *evcon); + +/** + * Removes a connection from the pool. + * + * The connection object must have been newly created. + * + * @param pool the pool from which to remove the connection + * @param evcon the connection to remove from the pool. + */ +void evrpc_pool_remove_connection(struct evrpc_pool *pool, + struct evhttp_connection *evcon); + +/** + * Sets the timeout in secs after which a request has to complete. The + * RPC is completely aborted if it does not complete by then. Setting + * the timeout to 0 means that it never timeouts and can be used to + * implement callback type RPCs. + * + * Any connection already in the pool will be updated with the new + * timeout. Connections added to the pool after set_timeout has be + * called receive the pool timeout only if no timeout has been set + * for the connection itself. + * + * @param pool a pointer to a struct evrpc_pool object + * @param timeout_in_secs the number of seconds after which a request should + * timeout and a failure be returned to the callback. + */ +void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs); + +/** + * Hooks for changing the input and output of RPCs; this can be used to + * implement compression, authentication, encryption, ... + */ + +enum EVRPC_HOOK_TYPE { + EVRPC_INPUT, /**< apply the function to an input hook */ + EVRPC_OUTPUT /**< apply the function to an output hook */ +}; + +#ifndef WIN32 +/** Deprecated alias for EVRPC_INPUT. Not available on windows, where it + * conflicts with platform headers. */ +#define INPUT EVRPC_INPUT +/** Deprecated alias for EVRPC_OUTPUT. Not available on windows, where it + * conflicts with platform headers. */ +#define OUTPUT EVRPC_OUTPUT +#endif + +/** + * Return value from hook processing functions + */ + +enum EVRPC_HOOK_RESULT { + EVRPC_TERMINATE = -1, /**< indicates the rpc should be terminated */ + EVRPC_CONTINUE = 0, /**< continue processing the rpc */ + EVRPC_PAUSE = 1 /**< pause processing request until resumed */ +}; + +/** adds a processing hook to either an rpc base or rpc pool + * + * If a hook returns TERMINATE, the processing is aborted. On CONTINUE, + * the request is immediately processed after the hook returns. If the + * hook returns PAUSE, request processing stops until evrpc_resume_request() + * has been called. + * + * The add functions return handles that can be used for removing hooks. + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param hook_type either INPUT or OUTPUT + * @param cb the callback to call when the hook is activated + * @param cb_arg an additional argument for the callback + * @return a handle to the hook so it can be removed later + * @see evrpc_remove_hook() + */ +void *evrpc_add_hook(void *vbase, + enum EVRPC_HOOK_TYPE hook_type, + int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *), + void *cb_arg); + +/** removes a previously added hook + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param hook_type either INPUT or OUTPUT + * @param handle a handle returned by evrpc_add_hook() + * @return 1 on success or 0 on failure + * @see evrpc_add_hook() + */ +int evrpc_remove_hook(void *vbase, + enum EVRPC_HOOK_TYPE hook_type, + void *handle); + +/** resume a paused request + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param ctx the context pointer provided to the original hook call + */ +int +evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res); + +/** adds meta data to request + * + * evrpc_hook_add_meta() allows hooks to add meta data to a request. for + * a client request, the meta data can be inserted by an outgoing request hook + * and retrieved by the incoming request hook. + * + * @param ctx the context provided to the hook call + * @param key a NUL-terminated c-string + * @param data the data to be associated with the key + * @param data_size the size of the data + */ +void evrpc_hook_add_meta(void *ctx, const char *key, + const void *data, size_t data_size); + +/** retrieves meta data previously associated + * + * evrpc_hook_find_meta() can be used to retrieve meta data associated to a + * request by a previous hook. + * @param ctx the context provided to the hook call + * @param key a NUL-terminated c-string + * @param data pointer to a data pointer that will contain the retrieved data + * @param data_size pointer to the size of the data + * @return 0 on success or -1 on failure + */ +int evrpc_hook_find_meta(void *ctx, const char *key, + void **data, size_t *data_size); + +/** + * returns the connection object associated with the request + * + * @param ctx the context provided to the hook call + * @return a pointer to the evhttp_connection object + */ +struct evhttp_connection *evrpc_hook_get_connection(void *ctx); + +/** + Function for sending a generic RPC request. + + Do not call this function directly, use EVRPC_MAKE_REQUEST() instead. + + @see EVRPC_MAKE_REQUEST() + */ +int evrpc_send_request_generic(struct evrpc_pool *pool, + void *request, void *reply, + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cb_arg, + const char *rpcname, + void (*req_marshal)(struct evbuffer *, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *)); + +/** + Function for registering a generic RPC with the RPC base. + + Do not call this function directly, use EVRPC_REGISTER() instead. + + @see EVRPC_REGISTER() + */ +int +evrpc_register_generic(struct evrpc_base *base, const char *name, + void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, + void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)); + +/** accessors for obscure and undocumented functionality */ +struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx); +void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx, + struct evrpc_pool *pool); +void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx, + void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg), + void *cb_arg); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_RPC_H_ */ diff --git a/libevent/include/event2/rpc_compat.h b/libevent/include/event2/rpc_compat.h new file mode 100644 index 0000000..a4e24bb --- /dev/null +++ b/libevent/include/event2/rpc_compat.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_RPC_COMPAT_H_ +#define _EVENT2_RPC_COMPAT_H_ + +/** @file event2/rpc_compat.h + + Deprecated versions of the functions in rpc.h: provided only for + backwards compatibility. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** backwards compatible accessors that work only with gcc */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + +#undef EVTAG_ASSIGN +#undef EVTAG_GET +#undef EVTAG_ADD + +#define EVTAG_ASSIGN(msg, member, args...) \ + (*(msg)->base->member##_assign)(msg, ## args) +#define EVTAG_GET(msg, member, args...) \ + (*(msg)->base->member##_get)(msg, ## args) +#define EVTAG_ADD(msg, member, args...) \ + (*(msg)->base->member##_add)(msg, ## args) +#endif +#define EVTAG_LEN(msg, member) ((msg)->member##_length) + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_EVENT_COMPAT_H_ */ diff --git a/libevent/include/event2/rpc_struct.h b/libevent/include/event2/rpc_struct.h new file mode 100644 index 0000000..c339ae5 --- /dev/null +++ b/libevent/include/event2/rpc_struct.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_RPC_STRUCT_H_ +#define _EVENT2_RPC_STRUCT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file event2/rpc_struct.h + + Structures used by rpc.h. Using these structures directly may harm + forward compatibility: be careful! + + */ + +/** + * provides information about the completed RPC request. + */ +struct evrpc_status { +#define EVRPC_STATUS_ERR_NONE 0 +#define EVRPC_STATUS_ERR_TIMEOUT 1 +#define EVRPC_STATUS_ERR_BADPAYLOAD 2 +#define EVRPC_STATUS_ERR_UNSTARTED 3 +#define EVRPC_STATUS_ERR_HOOKABORTED 4 + int error; + + /* for looking at headers or other information */ + struct evhttp_request *http_req; +}; + +/* the structure below needs to be synchronized with evrpc_req_generic */ + +/* Encapsulates a request */ +struct evrpc { + TAILQ_ENTRY(evrpc) next; + + /* the URI at which the request handler lives */ + const char* uri; + + /* creates a new request structure */ + void *(*request_new)(void *); + void *request_new_arg; + + /* frees the request structure */ + void (*request_free)(void *); + + /* unmarshals the buffer into the proper request structure */ + int (*request_unmarshal)(void *, struct evbuffer *); + + /* creates a new reply structure */ + void *(*reply_new)(void *); + void *reply_new_arg; + + /* frees the reply structure */ + void (*reply_free)(void *); + + /* verifies that the reply is valid */ + int (*reply_complete)(void *); + + /* marshals the reply into a buffer */ + void (*reply_marshal)(struct evbuffer*, void *); + + /* the callback invoked for each received rpc */ + void (*cb)(struct evrpc_req_generic *, void *); + void *cb_arg; + + /* reference for further configuration */ + struct evrpc_base *base; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_RPC_STRUCT_H_ */ diff --git a/libevent/include/event2/tag.h b/libevent/include/event2/tag.h new file mode 100644 index 0000000..9e51779 --- /dev/null +++ b/libevent/include/event2/tag.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_TAG_H_ +#define _EVENT2_TAG_H_ + +/** @file event2/tag.h + + Helper functions for reading and writing tagged data onto buffers. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +struct evbuffer; + +/* + * Marshaling tagged data - We assume that all tags are inserted in their + * numeric order - so that unknown tags will always be higher than the + * known ones - and we can just ignore the end of an event buffer. + */ + +void evtag_init(void); + +/** + Unmarshals the header and returns the length of the payload + + @param evbuf the buffer from which to unmarshal data + @param ptag a pointer in which the tag id is being stored + @returns -1 on failure or the number of bytes in the remaining payload. +*/ +int evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag); + +void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data, + ev_uint32_t len); +void evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag, + struct evbuffer *data); + +/** + Encode an integer and store it in an evbuffer. + + We encode integers by nybbles; the first nibble contains the number + of significant nibbles - 1; this allows us to encode up to 64-bit + integers. This function is byte-order independent. + + @param evbuf evbuffer to store the encoded number + @param number a 32-bit integer + */ +void evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number); +void evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number); + +void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint32_t integer); +void evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint64_t integer); + +void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, + const char *string); + +void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, + struct timeval *tv); + +int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, + struct evbuffer *dst); +int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag); +int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength); +int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength); +int evtag_consume(struct evbuffer *evbuf); + +int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint32_t *pinteger); +int evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint64_t *pinteger); + +int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, + void *data, size_t len); + +int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, + char **pstring); + +int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag, + struct timeval *ptv); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_TAG_H_ */ diff --git a/libevent/include/event2/tag_compat.h b/libevent/include/event2/tag_compat.h new file mode 100644 index 0000000..73c1933 --- /dev/null +++ b/libevent/include/event2/tag_compat.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_TAG_COMPAT_H_ +#define _EVENT2_TAG_COMPAT_H_ + +/** @file event2/tag_compat.h + + Obsolete/deprecated functions from tag.h; provided only for backwards + compatibility. + */ + +/** + @name Misnamed functions + + @deprecated These macros are deprecated because their names don't follow + Libevent's naming conventions. Use evtag_encode_int and + evtag_encode_int64 instead. + + @{ +*/ +#define encode_int(evbuf, number) evtag_encode_int((evbuf), (number)) +#define encode_int64(evbuf, number) evtag_encode_int64((evbuf), (number)) +/**@}*/ + +#endif /* _EVENT2_TAG_H_ */ diff --git a/libevent/include/event2/thread.h b/libevent/include/event2/thread.h new file mode 100644 index 0000000..0b638f0 --- /dev/null +++ b/libevent/include/event2/thread.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_THREAD_H_ +#define _EVENT2_THREAD_H_ + +/** @file event2/thread.h + + Functions for multi-threaded applications using Libevent. + + When using a multi-threaded application in which multiple threads + add and delete events from a single event base, Libevent needs to + lock its data structures. + + Like the memory-management function hooks, all of the threading functions + _must_ be set up before an event_base is created if you want the base to + use them. + + Most programs will either be using Windows threads or Posix threads. You + can configure Libevent to use one of these event_use_windows_threads() or + event_use_pthreads() respectively. If you're using another threading + library, you'll need to configure threading functions manually using + evthread_set_lock_callbacks() and evthread_set_condition_callbacks(). + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + @name Flags passed to lock functions + + @{ +*/ +/** A flag passed to a locking callback when the lock was allocated as a + * read-write lock, and we want to acquire or release the lock for writing. */ +#define EVTHREAD_WRITE 0x04 +/** A flag passed to a locking callback when the lock was allocated as a + * read-write lock, and we want to acquire or release the lock for reading. */ +#define EVTHREAD_READ 0x08 +/** A flag passed to a locking callback when we don't want to block waiting + * for the lock; if we can't get the lock immediately, we will instead + * return nonzero from the locking callback. */ +#define EVTHREAD_TRY 0x10 +/**@}*/ + +#if !defined(_EVENT_DISABLE_THREAD_SUPPORT) || defined(_EVENT_IN_DOXYGEN) + +#define EVTHREAD_LOCK_API_VERSION 1 + +/** + @name Types of locks + + @{*/ +/** A recursive lock is one that can be acquired multiple times at once by the + * same thread. No other process can allocate the lock until the thread that + * has been holding it has unlocked it as many times as it locked it. */ +#define EVTHREAD_LOCKTYPE_RECURSIVE 1 +/* A read-write lock is one that allows multiple simultaneous readers, but + * where any one writer excludes all other writers and readers. */ +#define EVTHREAD_LOCKTYPE_READWRITE 2 +/**@}*/ + +/** This structure describes the interface a threading library uses for + * locking. It's used to tell evthread_set_lock_callbacks() how to use + * locking on this platform. + */ +struct evthread_lock_callbacks { + /** The current version of the locking API. Set this to + * EVTHREAD_LOCK_API_VERSION */ + int lock_api_version; + /** Which kinds of locks does this version of the locking API + * support? A bitfield of EVTHREAD_LOCKTYPE_RECURSIVE and + * EVTHREAD_LOCKTYPE_READWRITE. + * + * (Note that RECURSIVE locks are currently mandatory, and + * READWRITE locks are not currently used.) + **/ + unsigned supported_locktypes; + /** Function to allocate and initialize new lock of type 'locktype'. + * Returns NULL on failure. */ + void *(*alloc)(unsigned locktype); + /** Funtion to release all storage held in 'lock', which was created + * with type 'locktype'. */ + void (*free)(void *lock, unsigned locktype); + /** Acquire an already-allocated lock at 'lock' with mode 'mode'. + * Returns 0 on success, and nonzero on failure. */ + int (*lock)(unsigned mode, void *lock); + /** Release a lock at 'lock' using mode 'mode'. Returns 0 on success, + * and nonzero on failure. */ + int (*unlock)(unsigned mode, void *lock); +}; + +/** Sets a group of functions that Libevent should use for locking. + * For full information on the required callback API, see the + * documentation for the individual members of evthread_lock_callbacks. + * + * Note that if you're using Windows or the Pthreads threading library, you + * probably shouldn't call this function; instead, use + * evthread_use_windows_threads() or evthread_use_posix_threads() if you can. + */ +int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *); + +#define EVTHREAD_CONDITION_API_VERSION 1 + +struct timeval; + +/** This structure describes the interface a threading library uses for + * condition variables. It's used to tell evthread_set_condition_callbacks + * how to use locking on this platform. + */ +struct evthread_condition_callbacks { + /** The current version of the conditions API. Set this to + * EVTHREAD_CONDITION_API_VERSION */ + int condition_api_version; + /** Function to allocate and initialize a new condition variable. + * Returns the condition variable on success, and NULL on failure. + * The 'condtype' argument will be 0 with this API version. + */ + void *(*alloc_condition)(unsigned condtype); + /** Function to free a condition variable. */ + void (*free_condition)(void *cond); + /** Function to signal a condition variable. If 'broadcast' is 1, all + * threads waiting on 'cond' should be woken; otherwise, only on one + * thread is worken. Should return 0 on success, -1 on failure. + * This function will only be called while holding the associated + * lock for the condition. + */ + int (*signal_condition)(void *cond, int broadcast); + /** Function to wait for a condition variable. The lock 'lock' + * will be held when this function is called; should be released + * while waiting for the condition to be come signalled, and + * should be held again when this function returns. + * If timeout is provided, it is interval of seconds to wait for + * the event to become signalled; if it is NULL, the function + * should wait indefinitely. + * + * The function should return -1 on error; 0 if the condition + * was signalled, or 1 on a timeout. */ + int (*wait_condition)(void *cond, void *lock, + const struct timeval *timeout); +}; + +/** Sets a group of functions that Libevent should use for condition variables. + * For full information on the required callback API, see the + * documentation for the individual members of evthread_condition_callbacks. + * + * Note that if you're using Windows or the Pthreads threading library, you + * probably shouldn't call this function; instead, use + * evthread_use_windows_threads() or evthread_use_pthreads() if you can. + */ +int evthread_set_condition_callbacks( + const struct evthread_condition_callbacks *); + +/** + Sets the function for determining the thread id. + + @param base the event base for which to set the id function + @param id_fn the identify function Libevent should invoke to + determine the identity of a thread. +*/ +void evthread_set_id_callback( + unsigned long (*id_fn)(void)); + +#if (defined(WIN32) && !defined(_EVENT_DISABLE_THREAD_SUPPORT)) || defined(_EVENT_IN_DOXYGEN) +/** Sets up Libevent for use with Windows builtin locking and thread ID + functions. Unavailable if Libevent is not built for Windows. + + @return 0 on success, -1 on failure. */ +int evthread_use_windows_threads(void); +/** + Defined if Libevent was built with support for evthread_use_windows_threads() +*/ +#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1 +#endif + +#if defined(_EVENT_HAVE_PTHREADS) || defined(_EVENT_IN_DOXYGEN) +/** Sets up Libevent for use with Pthreads locking and thread ID functions. + Unavailable if Libevent is not build for use with pthreads. Requires + libraries to link against Libevent_pthreads as well as Libevent. + + @return 0 on success, -1 on failure. */ +int evthread_use_pthreads(void); +/** Defined if Libevent was built with support for evthread_use_pthreads() */ +#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1 + +#endif + +/** Enable debugging wrappers around the current lock callbacks. If Libevent + * makes one of several common locking errors, exit with an assertion failure. + * + * If you're going to call this function, you must do so before any locks are + * allocated. + **/ +void evthread_enable_lock_debuging(void); + +#endif /* _EVENT_DISABLE_THREAD_SUPPORT */ + +struct event_base; +/** Make sure it's safe to tell an event base to wake up from another thread + or a signal handler. + + @return 0 on success, -1 on failure. + */ +int evthread_make_base_notifiable(struct event_base *base); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT2_THREAD_H_ */ diff --git a/libevent/include/event2/util.h b/libevent/include/event2/util.h new file mode 100644 index 0000000..45d8f1d --- /dev/null +++ b/libevent/include/event2/util.h @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT2_UTIL_H_ +#define _EVENT2_UTIL_H_ + +/** @file event2/util.h + + Common convenience functions for cross-platform portability and + related socket manipulations. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#ifdef _EVENT_HAVE_STDINT_H +#include +#elif defined(_EVENT_HAVE_INTTYPES_H) +#include +#endif +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include +#endif +#ifdef _EVENT_HAVE_STDDEF_H +#include +#endif +#ifdef _MSC_VER +#include +#endif +#include +#ifdef _EVENT_HAVE_NETDB_H +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif +#include +#endif + +#ifdef WIN32 +#include +#else +#include +#endif + +/* Some openbsd autoconf versions get the name of this macro wrong. */ +#if defined(_EVENT_SIZEOF_VOID__) && !defined(_EVENT_SIZEOF_VOID_P) +#define _EVENT_SIZEOF_VOID_P _EVENT_SIZEOF_VOID__ +#endif + +/** + * @name Standard integer types. + * + * Integer type definitions for types that are supposed to be defined in the + * C99-specified stdint.h. Shamefully, some platforms do not include + * stdint.h, so we need to replace it. (If you are on a platform like this, + * your C headers are now over 10 years out of date. You should bug them to + * do something about this.) + * + * We define: + * + *
+ *
ev_uint64_t, ev_uint32_t, ev_uint16_t, ev_uint8_t
+ *
unsigned integer types of exactly 64, 32, 16, and 8 bits + * respectively.
+ *
ev_int64_t, ev_int32_t, ev_int16_t, ev_int8_t
+ *
signed integer types of exactly 64, 32, 16, and 8 bits + * respectively.
+ *
ev_uintptr_t, ev_intptr_t
+ *
unsigned/signed integers large enough + * to hold a pointer without loss of bits.
+ *
ev_ssize_t
+ *
A signed type of the same size as size_t
+ *
ev_off_t
+ *
A signed type typically used to represent offsets within a + * (potentially large) file
+ * + * @{ + */ +#ifdef _EVENT_HAVE_UINT64_T +#define ev_uint64_t uint64_t +#define ev_int64_t int64_t +#elif defined(WIN32) +#define ev_uint64_t unsigned __int64 +#define ev_int64_t signed __int64 +#elif _EVENT_SIZEOF_LONG_LONG == 8 +#define ev_uint64_t unsigned long long +#define ev_int64_t long long +#elif _EVENT_SIZEOF_LONG == 8 +#define ev_uint64_t unsigned long +#define ev_int64_t long +#elif defined(_EVENT_IN_DOXYGEN) +#define ev_uint64_t ... +#define ev_int64_t ... +#else +#error "No way to define ev_uint64_t" +#endif + +#ifdef _EVENT_HAVE_UINT32_T +#define ev_uint32_t uint32_t +#define ev_int32_t int32_t +#elif defined(WIN32) +#define ev_uint32_t unsigned int +#define ev_int32_t signed int +#elif _EVENT_SIZEOF_LONG == 4 +#define ev_uint32_t unsigned long +#define ev_int32_t signed long +#elif _EVENT_SIZEOF_INT == 4 +#define ev_uint32_t unsigned int +#define ev_int32_t signed int +#elif defined(_EVENT_IN_DOXYGEN) +#define ev_uint32_t ... +#define ev_int32_t ... +#else +#error "No way to define ev_uint32_t" +#endif + +#ifdef _EVENT_HAVE_UINT16_T +#define ev_uint16_t uint16_t +#define ev_int16_t int16_t +#elif defined(WIN32) +#define ev_uint16_t unsigned short +#define ev_int16_t signed short +#elif _EVENT_SIZEOF_INT == 2 +#define ev_uint16_t unsigned int +#define ev_int16_t signed int +#elif _EVENT_SIZEOF_SHORT == 2 +#define ev_uint16_t unsigned short +#define ev_int16_t signed short +#elif defined(_EVENT_IN_DOXYGEN) +#define ev_uint16_t ... +#define ev_int16_t ... +#else +#error "No way to define ev_uint16_t" +#endif + +#ifdef _EVENT_HAVE_UINT8_T +#define ev_uint8_t uint8_t +#define ev_int8_t int8_t +#elif defined(_EVENT_IN_DOXYGEN) +#define ev_uint8_t ... +#define ev_int8_t ... +#else +#define ev_uint8_t unsigned char +#define ev_int8_t signed char +#endif + +#ifdef _EVENT_HAVE_UINTPTR_T +#define ev_uintptr_t uintptr_t +#define ev_intptr_t intptr_t +#elif _EVENT_SIZEOF_VOID_P <= 4 +#define ev_uintptr_t ev_uint32_t +#define ev_intptr_t ev_int32_t +#elif _EVENT_SIZEOF_VOID_P <= 8 +#define ev_uintptr_t ev_uint64_t +#define ev_intptr_t ev_int64_t +#elif defined(_EVENT_IN_DOXYGEN) +#define ev_uintptr_t ... +#define ev_intptr_t ... +#else +#error "No way to define ev_uintptr_t" +#endif + +#ifdef _EVENT_ssize_t +#define ev_ssize_t _EVENT_ssize_t +#else +#define ev_ssize_t ssize_t +#endif + +#ifdef WIN32 +#define ev_off_t ev_int64_t +#else +#define ev_off_t off_t +#endif +/**@}*/ + +/* Limits for integer types. + + We're making two assumptions here: + - The compiler does constant folding properly. + - The platform does signed arithmetic in two's complement. +*/ + +/** + @name Limits for integer types + + These macros hold the largest or smallest values possible for the + ev_[u]int*_t types. + + @{ +*/ +#define EV_UINT64_MAX ((((ev_uint64_t)0xffffffffUL) << 32) | 0xffffffffUL) +#define EV_INT64_MAX ((((ev_int64_t) 0x7fffffffL) << 32) | 0xffffffffL) +#define EV_INT64_MIN ((-EV_INT64_MAX) - 1) +#define EV_UINT32_MAX ((ev_uint32_t)0xffffffffUL) +#define EV_INT32_MAX ((ev_int32_t) 0x7fffffffL) +#define EV_INT32_MIN ((-EV_INT32_MAX) - 1) +#define EV_UINT16_MAX ((ev_uint16_t)0xffffUL) +#define EV_INT16_MAX ((ev_int16_t) 0x7fffL) +#define EV_INT16_MIN ((-EV_INT16_MAX) - 1) +#define EV_UINT8_MAX 255 +#define EV_INT8_MAX 127 +#define EV_INT8_MIN ((-EV_INT8_MAX) - 1) +/** @} */ + +/** + @name Limits for SIZE_T and SSIZE_T + + @{ +*/ +#if _EVENT_SIZEOF_SIZE_T == 8 +#define EV_SIZE_MAX EV_UINT64_MAX +#define EV_SSIZE_MAX EV_INT64_MAX +#elif _EVENT_SIZEOF_SIZE_T == 4 +#define EV_SIZE_MAX EV_UINT32_MAX +#define EV_SSIZE_MAX EV_INT32_MAX +#elif defined(_EVENT_IN_DOXYGEN) +#define EV_SIZE_MAX ... +#define EV_SSIZE_MAX ... +#else +#error "No way to define SIZE_MAX" +#endif + +#define EV_SSIZE_MIN ((-EV_SSIZE_MAX) - 1) +/**@}*/ + +#ifdef WIN32 +#define ev_socklen_t int +#elif defined(_EVENT_socklen_t) +#define ev_socklen_t _EVENT_socklen_t +#else +#define ev_socklen_t socklen_t +#endif + +#ifdef _EVENT_HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY +#if !defined(_EVENT_HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY) \ + && !defined(ss_family) +#define ss_family __ss_family +#endif +#endif + +/** + * A type wide enough to hold the output of "socket()" or "accept()". On + * Windows, this is an intptr_t; elsewhere, it is an int. */ +#ifdef WIN32 +#define evutil_socket_t intptr_t +#else +#define evutil_socket_t int +#endif + +/** Create two new sockets that are connected to each other. + + On Unix, this simply calls socketpair(). On Windows, it uses the + loopback network interface on 127.0.0.1, and only + AF_INET,SOCK_STREAM are supported. + + (This may fail on some Windows hosts where firewall software has cleverly + decided to keep 127.0.0.1 from talking to itself.) + + Parameters and return values are as for socketpair() +*/ +int evutil_socketpair(int d, int type, int protocol, evutil_socket_t sv[2]); +/** Do platform-specific operations as needed to make a socket nonblocking. + + @param sock The socket to make nonblocking + @return 0 on success, -1 on failure + */ +int evutil_make_socket_nonblocking(evutil_socket_t sock); + +/** Do platform-specific operations to make a listener socket reusable. + + Specifically, we want to make sure that another program will be able + to bind this address right after we've closed the listener. + + This differs from Windows's interpretation of "reusable", which + allows multiple listeners to bind the same address at the same time. + + @param sock The socket to make reusable + @return 0 on success, -1 on failure + */ +int evutil_make_listen_socket_reuseable(evutil_socket_t sock); + +/** Do platform-specific operations as needed to close a socket upon a + successful execution of one of the exec*() functions. + + @param sock The socket to be closed + @return 0 on success, -1 on failure + */ +int evutil_make_socket_closeonexec(evutil_socket_t sock); + +/** Do the platform-specific call needed to close a socket returned from + socket() or accept(). + + @param sock The socket to be closed + @return 0 on success, -1 on failure + */ +int evutil_closesocket(evutil_socket_t sock); +#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s) + + +#ifdef WIN32 +/** Return the most recent socket error. Not idempotent on all platforms. */ +#define EVUTIL_SOCKET_ERROR() WSAGetLastError() +/** Replace the most recent socket error with errcode */ +#define EVUTIL_SET_SOCKET_ERROR(errcode) \ + do { WSASetLastError(errcode); } while (0) +/** Return the most recent socket error to occur on sock. */ +int evutil_socket_geterror(evutil_socket_t sock); +/** Convert a socket error to a string. */ +const char *evutil_socket_error_to_string(int errcode); +#elif defined(_EVENT_IN_DOXYGEN) +/** + @name Socket error functions + + These functions are needed for making programs compatible between + Windows and Unix-like platforms. + + You see, Winsock handles socket errors differently from the rest of + the world. Elsewhere, a socket error is like any other error and is + stored in errno. But winsock functions require you to retrieve the + error with a special function, and don't let you use strerror for + the error codes. And handling EWOULDBLOCK is ... different. + + @{ +*/ +/** Return the most recent socket error. Not idempotent on all platforms. */ +#define EVUTIL_SOCKET_ERROR() ... +/** Replace the most recent socket error with errcode */ +#define EVUTIL_SET_SOCKET_ERROR(errcode) ... +/** Return the most recent socket error to occur on sock. */ +#define evutil_socket_geterror(sock) ... +/** Convert a socket error to a string. */ +#define evutil_socket_error_to_string(errcode) ... +/**@}*/ +#else +#define EVUTIL_SOCKET_ERROR() (errno) +#define EVUTIL_SET_SOCKET_ERROR(errcode) \ + do { errno = (errcode); } while (0) +#define evutil_socket_geterror(sock) (errno) +#define evutil_socket_error_to_string(errcode) (strerror(errcode)) +#endif + + +/** + * @name Manipulation macros for struct timeval. + * + * We define replacements + * for timeradd, timersub, timerclear, timercmp, and timerisset. + * + * @{ + */ +#ifdef _EVENT_HAVE_TIMERADD +#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp)) +#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp)) +#else +#define evutil_timeradd(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ + if ((vvp)->tv_usec >= 1000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_usec -= 1000000; \ + } \ + } while (0) +#define evutil_timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* !_EVENT_HAVE_HAVE_TIMERADD */ + +#ifdef _EVENT_HAVE_TIMERCLEAR +#define evutil_timerclear(tvp) timerclear(tvp) +#else +#define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#endif +/**@}*/ + +/** Return true iff the tvp is related to uvp according to the relational + * operator cmp. Recognized values for cmp are ==, <=, <, >=, and >. */ +#define evutil_timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) + +#ifdef _EVENT_HAVE_TIMERISSET +#define evutil_timerisset(tvp) timerisset(tvp) +#else +#define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#endif + +/** Replacement for offsetof on platforms that don't define it. */ +#ifdef offsetof +#define evutil_offsetof(type, field) offsetof(type, field) +#else +#define evutil_offsetof(type, field) ((off_t)(&((type *)0)->field)) +#endif + +/* big-int related functions */ +/** Parse a 64-bit value from a string. Arguments are as for strtol. */ +ev_int64_t evutil_strtoll(const char *s, char **endptr, int base); + +/** Replacement for gettimeofday on platforms that lack it. */ +#ifdef _EVENT_HAVE_GETTIMEOFDAY +#define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz)) +#else +struct timezone; +int evutil_gettimeofday(struct timeval *tv, struct timezone *tz); +#endif + +/** Replacement for snprintf to get consistent behavior on platforms for + which the return value of snprintf does not conform to C99. + */ +int evutil_snprintf(char *buf, size_t buflen, const char *format, ...) +#ifdef __GNUC__ + __attribute__((format(printf, 3, 4))) +#endif +; +/** Replacement for vsnprintf to get consistent behavior on platforms for + which the return value of snprintf does not conform to C99. + */ +int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap); + +/** Replacement for inet_ntop for platforms which lack it. */ +const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len); +/** Replacement for inet_pton for platforms which lack it. */ +int evutil_inet_pton(int af, const char *src, void *dst); +struct sockaddr; + +/** Parse an IPv4 or IPv6 address, with optional port, from a string. + + Recognized formats are: + - [IPv6Address]:port + - [IPv6Address] + - IPv6Address + - IPv4Address:port + - IPv4Address + + If no port is specified, the port in the output is set to 0. + + @param str The string to parse. + @param out A struct sockaddr to hold the result. This should probably be + a struct sockaddr_storage. + @param outlen A pointer to the number of bytes that that 'out' can safely + hold. Set to the number of bytes used in 'out' on success. + @return -1 if the address is not well-formed, if the port is out of range, + or if out is not large enough to hold the result. Otherwise returns + 0 on success. +*/ +int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outlen); + +/** Compare two sockaddrs; return 0 if they are equal, or less than 0 if sa1 + * preceeds sa2, or greater than 0 if sa1 follows sa2. If include_port is + * true, consider the port as well as the address. Only implemented for + * AF_INET and AF_INET6 addresses. The ordering is not guaranteed to remain + * the same between Libevent versions. */ +int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, + int include_port); + +/** As strcasecmp, but always compares the characters in locale-independent + ASCII. That's useful if you're handling data in ASCII-based protocols. + */ +int evutil_ascii_strcasecmp(const char *str1, const char *str2); +/** As strncasecmp, but always compares the characters in locale-independent + ASCII. That's useful if you're handling data in ASCII-based protocols. + */ +int evutil_ascii_strncasecmp(const char *str1, const char *str2, size_t n); + +/* Here we define evutil_addrinfo to the native addrinfo type, or redefine it + * if this system has no getaddrinfo(). */ +#ifdef _EVENT_HAVE_STRUCT_ADDRINFO +#define evutil_addrinfo addrinfo +#else +/** A definition of struct addrinfo for systems that lack it. + + (This is just an alias for struct addrinfo if the system defines + struct addrinfo.) +*/ +struct evutil_addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for nodename */ + struct sockaddr *ai_addr; /* binary address */ + struct evutil_addrinfo *ai_next; /* next structure in linked list */ +}; +#endif +/** @name evutil_getaddrinfo() error codes + + These values are possible error codes for evutil_getaddrinfo() and + related functions. + + @{ +*/ +#ifdef EAI_ADDRFAMILY +#define EVUTIL_EAI_ADDRFAMILY EAI_ADDRFAMILY +#else +#define EVUTIL_EAI_ADDRFAMILY -901 +#endif +#ifdef EAI_AGAIN +#define EVUTIL_EAI_AGAIN EAI_AGAIN +#else +#define EVUTIL_EAI_AGAIN -902 +#endif +#ifdef EAI_BADFLAGS +#define EVUTIL_EAI_BADFLAGS EAI_BADFLAGS +#else +#define EVUTIL_EAI_BADFLAGS -903 +#endif +#ifdef EAI_FAIL +#define EVUTIL_EAI_FAIL EAI_FAIL +#else +#define EVUTIL_EAI_FAIL -904 +#endif +#ifdef EAI_FAMILY +#define EVUTIL_EAI_FAMILY EAI_FAMILY +#else +#define EVUTIL_EAI_FAMILY -905 +#endif +#ifdef EAI_MEMORY +#define EVUTIL_EAI_MEMORY EAI_MEMORY +#else +#define EVUTIL_EAI_MEMORY -906 +#endif +/* This test is a bit complicated, since some MS SDKs decide to + * remove NODATA or redefine it to be the same as NONAME, in a + * fun interpretation of RFC 2553 and RFC 3493. */ +#if defined(EAI_NODATA) && (!defined(EAI_NONAME) || EAI_NODATA != EAI_NONAME) +#define EVUTIL_EAI_NODATA EAI_NODATA +#else +#define EVUTIL_EAI_NODATA -907 +#endif +#ifdef EAI_NONAME +#define EVUTIL_EAI_NONAME EAI_NONAME +#else +#define EVUTIL_EAI_NONAME -908 +#endif +#ifdef EAI_SERVICE +#define EVUTIL_EAI_SERVICE EAI_SERVICE +#else +#define EVUTIL_EAI_SERVICE -909 +#endif +#ifdef EAI_SOCKTYPE +#define EVUTIL_EAI_SOCKTYPE EAI_SOCKTYPE +#else +#define EVUTIL_EAI_SOCKTYPE -910 +#endif +#ifdef EAI_SYSTEM +#define EVUTIL_EAI_SYSTEM EAI_SYSTEM +#else +#define EVUTIL_EAI_SYSTEM -911 +#endif + +#define EVUTIL_EAI_CANCEL -90001 + +#ifdef AI_PASSIVE +#define EVUTIL_AI_PASSIVE AI_PASSIVE +#else +#define EVUTIL_AI_PASSIVE 0x1000 +#endif +#ifdef AI_CANONNAME +#define EVUTIL_AI_CANONNAME AI_CANONNAME +#else +#define EVUTIL_AI_CANONNAME 0x2000 +#endif +#ifdef AI_NUMERICHOST +#define EVUTIL_AI_NUMERICHOST AI_NUMERICHOST +#else +#define EVUTIL_AI_NUMERICHOST 0x4000 +#endif +#ifdef AI_NUMERICSERV +#define EVUTIL_AI_NUMERICSERV AI_NUMERICSERV +#else +#define EVUTIL_AI_NUMERICSERV 0x8000 +#endif +#ifdef AI_V4MAPPED +#define EVUTIL_AI_V4MAPPED AI_V4MAPPED +#else +#define EVUTIL_AI_V4MAPPED 0x10000 +#endif +#ifdef AI_ALL +#define EVUTIL_AI_ALL AI_ALL +#else +#define EVUTIL_AI_ALL 0x20000 +#endif +#ifdef AI_ADDRCONFIG +#define EVUTIL_AI_ADDRCONFIG AI_ADDRCONFIG +#else +#define EVUTIL_AI_ADDRCONFIG 0x40000 +#endif +/**@}*/ + +struct evutil_addrinfo; +/** + * This function clones getaddrinfo for systems that don't have it. For full + * details, see RFC 3493, section 6.1. + * + * Limitations: + * - When the system has no getaddrinfo, we fall back to gethostbyname_r or + * gethostbyname, with their attendant issues. + * - The AI_V4MAPPED and AI_ALL flags are not currently implemented. + * + * For a nonblocking variant, see evdns_getaddrinfo. + */ +int evutil_getaddrinfo(const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res); + +/** Release storage allocated by evutil_getaddrinfo or evdns_getaddrinfo. */ +void evutil_freeaddrinfo(struct evutil_addrinfo *ai); + +const char *evutil_gai_strerror(int err); + +/** Generate n bytes of secure pseudorandom data, and store them in buf. + * + * By default, Libevent uses an ARC4-based random number generator, seeded + * using the platform's entropy source (/dev/urandom on Unix-like systems; + * CryptGenRandom on Windows). + */ +void evutil_secure_rng_get_bytes(void *buf, size_t n); + +/** + * Seed the secure random number generator if needed, and return 0 on + * success or -1 on failure. + * + * It is okay to call this function more than once; it will still return + * 0 if the RNG has been successfully seeded and -1 if it can't be + * seeded. + * + * Ordinarily you don't need to call this function from your own code; + * Libevent will seed the RNG itself the first time it needs good random + * numbers. You only need to call it if (a) you want to double-check + * that one of the seeding methods did succeed, or (b) you plan to drop + * the capability to seed (by chrooting, or dropping capabilities, or + * whatever), and you want to make sure that seeding happens before your + * program loses the ability to do it. + */ +int evutil_secure_rng_init(void); + +/** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be + sufficient to invoke evutil_secure_rng_init(), or let Libevent take + care of calling evutil_secure_rng_init() on its own. + + If you call this function as a _replacement_ for the regular + entropy sources, then you need to be sure that your input + contains a fairly large amount of strong entropy. Doing so is + notoriously hard: most people who try get it wrong. Watch out! + + @param dat a buffer full of a strong source of random numbers + @param datlen the number of bytes to read from datlen + */ +void evutil_secure_rng_add_bytes(const char *dat, size_t datlen); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVUTIL_H_ */ diff --git a/libevent/iocp-internal.h b/libevent/iocp-internal.h new file mode 100644 index 0000000..ae79cbc --- /dev/null +++ b/libevent/iocp-internal.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#ifndef _EVENT_IOCP_INTERNAL_H +#define _EVENT_IOCP_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct event_overlapped; +struct event_iocp_port; +struct evbuffer; +typedef void (*iocp_callback)(struct event_overlapped *, ev_uintptr_t, ev_ssize_t, int success); + +/* This whole file is actually win32 only. We wrap the structures in a win32 + * ifdef so that we can test-compile code that uses these interfaces on + * non-win32 platforms. */ +#ifdef WIN32 + +/** + Internal use only. Wraps an OVERLAPPED that we're using for libevent + functionality. Whenever an event_iocp_port gets an event for a given + OVERLAPPED*, it upcasts the pointer to an event_overlapped, and calls the + iocp_callback function with the event_overlapped, the iocp key, and the + number of bytes transferred as arguments. + */ +struct event_overlapped { + OVERLAPPED overlapped; + iocp_callback cb; +}; + +/* Mingw's headers don't define LPFN_ACCEPTEX. */ + +typedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED); +typedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED); +typedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT); + +/** Internal use only. Holds pointers to functions that only some versions of + Windows provide. + */ +struct win32_extension_fns { + AcceptExPtr AcceptEx; + ConnectExPtr ConnectEx; + GetAcceptExSockaddrsPtr GetAcceptExSockaddrs; +}; + +/** + Internal use only. Stores a Windows IO Completion port, along with + related data. + */ +struct event_iocp_port { + /** The port itself */ + HANDLE port; + /* A lock to cover internal structures. */ + CRITICAL_SECTION lock; + /** Number of threads ever open on the port. */ + short n_threads; + /** True iff we're shutting down all the threads on this port */ + short shutdown; + /** How often the threads on this port check for shutdown and other + * conditions */ + long ms; + /* The threads that are waiting for events. */ + HANDLE *threads; + /** Number of threads currently open on this port. */ + short n_live_threads; + /** A semaphore to signal when we are done shutting down. */ + HANDLE *shutdownSemaphore; +}; + +const struct win32_extension_fns *event_get_win32_extension_fns(void); +#else +/* Dummy definition so we can test-compile more things on unix. */ +struct event_overlapped { + iocp_callback cb; +}; +#endif + +/** Initialize the fields in an event_overlapped. + + @param overlapped The struct event_overlapped to initialize + @param cb The callback that should be invoked once the IO operation has + finished. + */ +void event_overlapped_init(struct event_overlapped *, iocp_callback cb); + +/** Allocate and return a new evbuffer that supports overlapped IO on a given + socket. The socket must be associated with an IO completion port using + event_iocp_port_associate. +*/ +struct evbuffer *evbuffer_overlapped_new(evutil_socket_t fd); + +/** XXXX Document (nickm) */ +evutil_socket_t _evbuffer_overlapped_get_fd(struct evbuffer *buf); + +void _evbuffer_overlapped_set_fd(struct evbuffer *buf, evutil_socket_t fd); + +/** Start reading data onto the end of an overlapped evbuffer. + + An evbuffer can only have one read pending at a time. While the read + is in progress, no other data may be added to the end of the buffer. + The buffer must be created with event_overlapped_init(). + evbuffer_commit_read() must be called in the completion callback. + + @param buf The buffer to read onto + @param n The number of bytes to try to read. + @param ol Overlapped object with associated completion callback. + @return 0 on success, -1 on error. + */ +int evbuffer_launch_read(struct evbuffer *buf, size_t n, struct event_overlapped *ol); + +/** Start writing data from the start of an evbuffer. + + An evbuffer can only have one write pending at a time. While the write is + in progress, no other data may be removed from the front of the buffer. + The buffer must be created with event_overlapped_init(). + evbuffer_commit_write() must be called in the completion callback. + + @param buf The buffer to read onto + @param n The number of bytes to try to read. + @param ol Overlapped object with associated completion callback. + @return 0 on success, -1 on error. + */ +int evbuffer_launch_write(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol); + +/** XXX document */ +void evbuffer_commit_read(struct evbuffer *, ev_ssize_t); +void evbuffer_commit_write(struct evbuffer *, ev_ssize_t); + +/** Create an IOCP, and launch its worker threads. Internal use only. + + This interface is unstable, and will change. + */ +struct event_iocp_port *event_iocp_port_launch(int n_cpus); + +/** Associate a file descriptor with an iocp, such that overlapped IO on the + fd will happen on one of the iocp's worker threads. +*/ +int event_iocp_port_associate(struct event_iocp_port *port, evutil_socket_t fd, + ev_uintptr_t key); + +/** Tell all threads serving an iocp to stop. Wait for up to waitMsec for all + the threads to finish whatever they're doing. If waitMsec is -1, wait + as long as required. If all the threads are done, free the port and return + 0. Otherwise, return -1. If you get a -1 return value, it is safe to call + this function again. +*/ +int event_iocp_shutdown(struct event_iocp_port *port, long waitMsec); + +/* FIXME document. */ +int event_iocp_activate_overlapped(struct event_iocp_port *port, + struct event_overlapped *o, + ev_uintptr_t key, ev_uint32_t n_bytes); + +struct event_base; +/* FIXME document. */ +struct event_iocp_port *event_base_get_iocp(struct event_base *base); + +/* FIXME document. */ +int event_base_start_iocp(struct event_base *base, int n_cpus); +void event_base_stop_iocp(struct event_base *base); + +/* FIXME document. */ +struct bufferevent *bufferevent_async_new(struct event_base *base, + evutil_socket_t fd, int options); + +/* FIXME document. */ +void bufferevent_async_set_connected(struct bufferevent *bev); +int bufferevent_async_can_connect(struct bufferevent *bev); +int bufferevent_async_connect(struct bufferevent *bev, evutil_socket_t fd, + const struct sockaddr *sa, int socklen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libevent/ipv6-internal.h b/libevent/ipv6-internal.h new file mode 100644 index 0000000..e373711 --- /dev/null +++ b/libevent/ipv6-internal.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +/* Internal use only: Fake IPv6 structures and values on platforms that + * do not have them */ + +#ifndef _EVENT_IPV6_INTERNAL_H +#define _EVENT_IPV6_INTERNAL_H + +#include +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif +#include "event2/event-config.h" +#include "event2/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file ipv6-internal.h + * + * Replacement types and functions for platforms that don't support ipv6 + * properly. + */ + +#ifndef _EVENT_HAVE_STRUCT_IN6_ADDR +struct in6_addr { + ev_uint8_t s6_addr[16]; +}; +#endif + +#ifndef _EVENT_HAVE_SA_FAMILY_T +typedef int sa_family_t; +#endif + +#ifndef _EVENT_HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + /* This will fail if we find a struct sockaddr that doesn't have + * sa_family as the first element. */ + sa_family_t sin6_family; + ev_uint16_t sin6_port; + struct in6_addr sin6_addr; +}; +#endif + +#ifndef AF_INET6 +#define AF_INET6 3333 +#endif +#ifndef PF_INET6 +#define PF_INET6 AF_INET6 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libevent/kqueue.c b/libevent/kqueue.c new file mode 100644 index 0000000..51984a4 --- /dev/null +++ b/libevent/kqueue.c @@ -0,0 +1,475 @@ +/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */ + +/* + * Copyright 2000-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#define _GNU_SOURCE + +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _EVENT_HAVE_INTTYPES_H +#include +#endif + +/* Some platforms apparently define the udata field of struct kevent as + * intptr_t, whereas others define it as void*. There doesn't seem to be an + * easy way to tell them apart via autoconf, so we need to use OS macros. */ +#if defined(_EVENT_HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) +#define PTR_TO_UDATA(x) ((intptr_t)(x)) +#define INT_TO_UDATA(x) ((intptr_t)(x)) +#else +#define PTR_TO_UDATA(x) (x) +#define INT_TO_UDATA(x) ((void*)(x)) +#endif + +#include "event-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "event2/thread.h" +#include "evthread-internal.h" +#include "changelist-internal.h" + +#define NEVENT 64 + +struct kqop { + struct kevent *changes; + int changes_size; + + struct kevent *events; + int events_size; + int kq; + pid_t pid; +}; + +static void kqop_free(struct kqop *kqop); + +static void *kq_init(struct event_base *); +static int kq_sig_add(struct event_base *, int, short, short, void *); +static int kq_sig_del(struct event_base *, int, short, short, void *); +static int kq_dispatch(struct event_base *, struct timeval *); +static void kq_dealloc(struct event_base *); + +const struct eventop kqops = { + "kqueue", + kq_init, + event_changelist_add, + event_changelist_del, + kq_dispatch, + kq_dealloc, + 1 /* need reinit */, + EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_FDS, + EVENT_CHANGELIST_FDINFO_SIZE +}; + +static const struct eventop kqsigops = { + "kqueue_signal", + NULL, + kq_sig_add, + kq_sig_del, + NULL, + NULL, + 1 /* need reinit */, + 0, + 0 +}; + +static void * +kq_init(struct event_base *base) +{ + int kq = -1; + struct kqop *kqueueop = NULL; + + if (!(kqueueop = mm_calloc(1, sizeof(struct kqop)))) + return (NULL); + +/* Initialize the kernel queue */ + + if ((kq = kqueue()) == -1) { + event_warn("kqueue"); + goto err; + } + + kqueueop->kq = kq; + + kqueueop->pid = getpid(); + + /* Initialize fields */ + kqueueop->changes = mm_calloc(NEVENT, sizeof(struct kevent)); + if (kqueueop->changes == NULL) + goto err; + kqueueop->events = mm_calloc(NEVENT, sizeof(struct kevent)); + if (kqueueop->events == NULL) + goto err; + kqueueop->events_size = kqueueop->changes_size = NEVENT; + + /* Check for Mac OS X kqueue bug. */ + memset(&kqueueop->changes[0], 0, sizeof kqueueop->changes[0]); + kqueueop->changes[0].ident = -1; + kqueueop->changes[0].filter = EVFILT_READ; + kqueueop->changes[0].flags = EV_ADD; + /* + * If kqueue works, then kevent will succeed, and it will + * stick an error in events[0]. If kqueue is broken, then + * kevent will fail. + */ + if (kevent(kq, + kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 || + (int)kqueueop->events[0].ident != -1 || + kqueueop->events[0].flags != EV_ERROR) { + event_warn("%s: detected broken kqueue; not using.", __func__); + goto err; + } + + base->evsigsel = &kqsigops; + + return (kqueueop); +err: + if (kqueueop) + kqop_free(kqueueop); + + return (NULL); +} + +static void +kq_sighandler(int sig) +{ + /* Do nothing here */ +} + +#define ADD_UDATA 0x30303 + +static void +kq_setup_kevent(struct kevent *out, evutil_socket_t fd, int filter, short change) +{ + memset(out, 0, sizeof(struct kevent)); + out->ident = fd; + out->filter = filter; + + if (change & EV_CHANGE_ADD) { + out->flags = EV_ADD; + /* We set a magic number here so that we can tell 'add' + * errors from 'del' errors. */ + out->udata = INT_TO_UDATA(ADD_UDATA); + if (change & EV_ET) + out->flags |= EV_CLEAR; +#ifdef NOTE_EOF + /* Make it behave like select() and poll() */ + if (filter == EVFILT_READ) + out->fflags = NOTE_EOF; +#endif + } else { + EVUTIL_ASSERT(change & EV_CHANGE_DEL); + out->flags = EV_DELETE; + } +} + +static int +kq_build_changes_list(const struct event_changelist *changelist, + struct kqop *kqop) +{ + int i; + int n_changes = 0; + + for (i = 0; i < changelist->n_changes; ++i) { + struct event_change *in_ch = &changelist->changes[i]; + struct kevent *out_ch; + if (n_changes >= kqop->changes_size - 1) { + int newsize = kqop->changes_size * 2; + struct kevent *newchanges; + + newchanges = mm_realloc(kqop->changes, + newsize * sizeof(struct kevent)); + if (newchanges == NULL) { + event_warn("%s: realloc", __func__); + return (-1); + } + kqop->changes = newchanges; + kqop->changes_size = newsize; + } + if (in_ch->read_change) { + out_ch = &kqop->changes[n_changes++]; + kq_setup_kevent(out_ch, in_ch->fd, EVFILT_READ, + in_ch->read_change); + } + if (in_ch->write_change) { + out_ch = &kqop->changes[n_changes++]; + kq_setup_kevent(out_ch, in_ch->fd, EVFILT_WRITE, + in_ch->write_change); + } + } + return n_changes; +} + +static int +kq_grow_events(struct kqop *kqop, size_t new_size) +{ + struct kevent *newresult; + + newresult = mm_realloc(kqop->events, + new_size * sizeof(struct kevent)); + + if (newresult) { + kqop->events = newresult; + kqop->events_size = new_size; + return 0; + } else { + return -1; + } +} + +static int +kq_dispatch(struct event_base *base, struct timeval *tv) +{ + struct kqop *kqop = base->evbase; + struct kevent *events = kqop->events; + struct kevent *changes; + struct timespec ts, *ts_p = NULL; + int i, n_changes, res; + + if (tv != NULL) { + TIMEVAL_TO_TIMESPEC(tv, &ts); + ts_p = &ts; + } + + /* Build "changes" from "base->changes" */ + EVUTIL_ASSERT(kqop->changes); + n_changes = kq_build_changes_list(&base->changelist, kqop); + if (n_changes < 0) + return -1; + + event_changelist_remove_all(&base->changelist, base); + + /* steal the changes array in case some broken code tries to call + * dispatch twice at once. */ + changes = kqop->changes; + kqop->changes = NULL; + + /* Make sure that 'events' is at least as long as the list of changes: + * otherwise errors in the changes can get reported as a -1 return + * value from kevent() rather than as EV_ERROR events in the events + * array. + * + * (We could instead handle -1 return values from kevent() by + * retrying with a smaller changes array or a larger events array, + * but this approach seems less risky for now.) + */ + if (kqop->events_size < n_changes) { + int new_size = kqop->events_size; + do { + new_size *= 2; + } while (new_size < n_changes); + + kq_grow_events(kqop, new_size); + events = kqop->events; + } + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = kevent(kqop->kq, changes, n_changes, + events, kqop->events_size, ts_p); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + EVUTIL_ASSERT(kqop->changes == NULL); + kqop->changes = changes; + + if (res == -1) { + if (errno != EINTR) { + event_warn("kevent"); + return (-1); + } + + return (0); + } + + event_debug(("%s: kevent reports %d", __func__, res)); + + for (i = 0; i < res; i++) { + int which = 0; + + if (events[i].flags & EV_ERROR) { + switch (events[i].data) { + + /* Can occur on delete if we are not currently + * watching any events on this fd. That can + * happen when the fd was closed and another + * file was opened with that fd. */ + case ENOENT: + /* Can occur for reasons not fully understood + * on FreeBSD. */ + case EINVAL: + continue; + + /* Can occur on a delete if the fd is closed. */ + case EBADF: + /* XXXX On NetBSD, we can also get EBADF if we + * try to add the write side of a pipe, but + * the read side has already been closed. + * Other BSDs call this situation 'EPIPE'. It + * would be good if we had a way to report + * this situation. */ + continue; + /* These two can occur on an add if the fd was one side + * of a pipe, and the other side was closed. */ + case EPERM: + case EPIPE: + /* Report read events, if we're listening for + * them, so that the user can learn about any + * add errors. (If the operation was a + * delete, then udata should be cleared.) */ + if (events[i].udata) { + /* The operation was an add: + * report the error as a read. */ + which |= EV_READ; + break; + } else { + /* The operation was a del: + * report nothing. */ + continue; + } + + /* Other errors shouldn't occur. */ + default: + errno = events[i].data; + return (-1); + } + } else if (events[i].filter == EVFILT_READ) { + which |= EV_READ; + } else if (events[i].filter == EVFILT_WRITE) { + which |= EV_WRITE; + } else if (events[i].filter == EVFILT_SIGNAL) { + which |= EV_SIGNAL; + } + + if (!which) + continue; + + if (events[i].filter == EVFILT_SIGNAL) { + evmap_signal_active(base, events[i].ident, 1); + } else { + evmap_io_active(base, events[i].ident, which | EV_ET); + } + } + + if (res == kqop->events_size) { + /* We used all the events space that we have. Maybe we should + make it bigger. */ + kq_grow_events(kqop, kqop->events_size * 2); + } + + return (0); +} + +static void +kqop_free(struct kqop *kqop) +{ + if (kqop->changes) + mm_free(kqop->changes); + if (kqop->events) + mm_free(kqop->events); + if (kqop->kq >= 0 && kqop->pid == getpid()) + close(kqop->kq); + memset(kqop, 0, sizeof(struct kqop)); + mm_free(kqop); +} + +static void +kq_dealloc(struct event_base *base) +{ + struct kqop *kqop = base->evbase; + evsig_dealloc(base); + kqop_free(kqop); +} + +/* signal handling */ +static int +kq_sig_add(struct event_base *base, int nsignal, short old, short events, void *p) +{ + struct kqop *kqop = base->evbase; + struct kevent kev; + struct timespec timeout = { 0, 0 }; + (void)p; + + EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG); + + memset(&kev, 0, sizeof(kev)); + kev.ident = nsignal; + kev.filter = EVFILT_SIGNAL; + kev.flags = EV_ADD; + + /* Be ready for the signal if it is sent any + * time between now and the next call to + * kq_dispatch. */ + if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) + return (-1); + + /* XXXX The manpage suggest we could use SIG_IGN instead of a + * do-nothing handler */ + if (_evsig_set_handler(base, nsignal, kq_sighandler) == -1) + return (-1); + + return (0); +} + +static int +kq_sig_del(struct event_base *base, int nsignal, short old, short events, void *p) +{ + struct kqop *kqop = base->evbase; + struct kevent kev; + + struct timespec timeout = { 0, 0 }; + (void)p; + + EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG); + + memset(&kev, 0, sizeof(kev)); + kev.ident = nsignal; + kev.filter = EVFILT_SIGNAL; + kev.flags = EV_DELETE; + + /* Because we insert signal events + * immediately, we need to delete them + * immediately, too */ + if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) + return (-1); + + if (_evsig_restore_handler(base, nsignal) == -1) + return (-1); + + return (0); +} diff --git a/libevent/libevent.pc.in b/libevent/libevent.pc.in new file mode 100644 index 0000000..7030884 --- /dev/null +++ b/libevent/libevent.pc.in @@ -0,0 +1,16 @@ +#libevent pkg-config source file + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libevent +Description: libevent is an asynchronous notification event loop library +Version: @VERSION@ +Requires: +Conflicts: +Libs: -L${libdir} -levent +Libs.private: @LIBS@ +Cflags: -I${includedir} + diff --git a/libevent/libevent_openssl.pc.in b/libevent/libevent_openssl.pc.in new file mode 100644 index 0000000..9624cf2 --- /dev/null +++ b/libevent/libevent_openssl.pc.in @@ -0,0 +1,16 @@ +#libevent pkg-config source file + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libevent_openssl +Description: libevent_openssl adds openssl-based TLS support to libevent +Version: @VERSION@ +Requires: libevent +Conflicts: +Libs: -L${libdir} -levent_openssl +Libs.private: @LIBS@ -lssl -lcrypto +Cflags: -I${includedir} + diff --git a/libevent/libevent_pthreads.pc.in b/libevent/libevent_pthreads.pc.in new file mode 100644 index 0000000..9bc2392 --- /dev/null +++ b/libevent/libevent_pthreads.pc.in @@ -0,0 +1,16 @@ +#libevent pkg-config source file + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libevent_pthreads +Description: libevent_pthreads adds pthreads-based threading support to libevent +Version: @VERSION@ +Requires: libevent +Conflicts: +Libs: -L${libdir} -levent_pthreads +Libs.private: @LIBS@ @PTHREAD_LIBS@ +Cflags: -I${includedir} @PTHREAD_CFLAGS@ + diff --git a/libevent/listener.c b/libevent/listener.c new file mode 100644 index 0000000..9941e1d --- /dev/null +++ b/libevent/listener.c @@ -0,0 +1,875 @@ +/* + * Copyright (c) 2009-2012 Niels Provos, Nick Mathewson + * + * 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. + */ + +#include + +#include "event2/event-config.h" + +#ifdef WIN32 +#ifndef _WIN32_WINNT +/* Minimum required for InitializeCriticalSectionAndSpinCount */ +#define _WIN32_WINNT 0x0403 +#endif +#include +#include +#include +#endif +#include +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef _EVENT_HAVE_FCNTL_H +#include +#endif +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif + +#include "event2/listener.h" +#include "event2/util.h" +#include "event2/event.h" +#include "event2/event_struct.h" +#include "mm-internal.h" +#include "util-internal.h" +#include "log-internal.h" +#include "evthread-internal.h" +#ifdef WIN32 +#include "iocp-internal.h" +#include "defer-internal.h" +#include "event-internal.h" +#endif + +struct evconnlistener_ops { + int (*enable)(struct evconnlistener *); + int (*disable)(struct evconnlistener *); + void (*destroy)(struct evconnlistener *); + void (*shutdown)(struct evconnlistener *); + evutil_socket_t (*getfd)(struct evconnlistener *); + struct event_base *(*getbase)(struct evconnlistener *); +}; + +struct evconnlistener { + const struct evconnlistener_ops *ops; + void *lock; + evconnlistener_cb cb; + evconnlistener_errorcb errorcb; + void *user_data; + unsigned flags; + short refcnt; + unsigned enabled : 1; +}; + +struct evconnlistener_event { + struct evconnlistener base; + struct event listener; +}; + +#ifdef WIN32 +struct evconnlistener_iocp { + struct evconnlistener base; + evutil_socket_t fd; + struct event_base *event_base; + struct event_iocp_port *port; + short n_accepting; + unsigned shutting_down : 1; + unsigned event_added : 1; + struct accepting_socket **accepting; +}; +#endif + +#define LOCK(listener) EVLOCK_LOCK((listener)->lock, 0) +#define UNLOCK(listener) EVLOCK_UNLOCK((listener)->lock, 0) + +struct evconnlistener * +evconnlistener_new_async(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + evutil_socket_t fd); /* XXXX export this? */ + +static int event_listener_enable(struct evconnlistener *); +static int event_listener_disable(struct evconnlistener *); +static void event_listener_destroy(struct evconnlistener *); +static evutil_socket_t event_listener_getfd(struct evconnlistener *); +static struct event_base *event_listener_getbase(struct evconnlistener *); + +#if 0 +static void +listener_incref_and_lock(struct evconnlistener *listener) +{ + LOCK(listener); + ++listener->refcnt; +} +#endif + +static int +listener_decref_and_unlock(struct evconnlistener *listener) +{ + int refcnt = --listener->refcnt; + if (refcnt == 0) { + listener->ops->destroy(listener); + UNLOCK(listener); + EVTHREAD_FREE_LOCK(listener->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + mm_free(listener); + return 1; + } else { + UNLOCK(listener); + return 0; + } +} + +static const struct evconnlistener_ops evconnlistener_event_ops = { + event_listener_enable, + event_listener_disable, + event_listener_destroy, + NULL, /* shutdown */ + event_listener_getfd, + event_listener_getbase +}; + +static void listener_read_cb(evutil_socket_t, short, void *); + +struct evconnlistener * +evconnlistener_new(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + evutil_socket_t fd) +{ + struct evconnlistener_event *lev; + +#ifdef WIN32 + if (base && event_base_get_iocp(base)) { + const struct win32_extension_fns *ext = + event_get_win32_extension_fns(); + if (ext->AcceptEx && ext->GetAcceptExSockaddrs) + return evconnlistener_new_async(base, cb, ptr, flags, + backlog, fd); + } +#endif + + if (backlog > 0) { + if (listen(fd, backlog) < 0) + return NULL; + } else if (backlog < 0) { + if (listen(fd, 128) < 0) + return NULL; + } + + lev = mm_calloc(1, sizeof(struct evconnlistener_event)); + if (!lev) + return NULL; + + lev->base.ops = &evconnlistener_event_ops; + lev->base.cb = cb; + lev->base.user_data = ptr; + lev->base.flags = flags; + lev->base.refcnt = 1; + + if (flags & LEV_OPT_THREADSAFE) { + EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); + } + + event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST, + listener_read_cb, lev); + + evconnlistener_enable(&lev->base); + + return &lev->base; +} + +struct evconnlistener * +evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, + void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, + int socklen) +{ + struct evconnlistener *listener; + evutil_socket_t fd; + int on = 1; + int family = sa ? sa->sa_family : AF_UNSPEC; + + if (backlog == 0) + return NULL; + + fd = socket(family, SOCK_STREAM, 0); + if (fd == -1) + return NULL; + + if (evutil_make_socket_nonblocking(fd) < 0) { + evutil_closesocket(fd); + return NULL; + } + + if (flags & LEV_OPT_CLOSE_ON_EXEC) { + if (evutil_make_socket_closeonexec(fd) < 0) { + evutil_closesocket(fd); + return NULL; + } + } + + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on)); + if (flags & LEV_OPT_REUSEABLE) { + evutil_make_listen_socket_reuseable(fd); + } + + if (sa) { + if (bind(fd, sa, socklen)<0) { + evutil_closesocket(fd); + return NULL; + } + } + + listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd); + if (!listener) { + evutil_closesocket(fd); + return NULL; + } + + return listener; +} + +void +evconnlistener_free(struct evconnlistener *lev) +{ + LOCK(lev); + lev->cb = NULL; + lev->errorcb = NULL; + if (lev->ops->shutdown) + lev->ops->shutdown(lev); + listener_decref_and_unlock(lev); +} + +static void +event_listener_destroy(struct evconnlistener *lev) +{ + struct evconnlistener_event *lev_e = + EVUTIL_UPCAST(lev, struct evconnlistener_event, base); + + event_del(&lev_e->listener); + if (lev->flags & LEV_OPT_CLOSE_ON_FREE) + evutil_closesocket(event_get_fd(&lev_e->listener)); + event_debug_unassign(&lev_e->listener); +} + +int +evconnlistener_enable(struct evconnlistener *lev) +{ + int r; + LOCK(lev); + lev->enabled = 1; + if (lev->cb) + r = lev->ops->enable(lev); + else + r = 0; + UNLOCK(lev); + return r; +} + +int +evconnlistener_disable(struct evconnlistener *lev) +{ + int r; + LOCK(lev); + lev->enabled = 0; + r = lev->ops->disable(lev); + UNLOCK(lev); + return r; +} + +static int +event_listener_enable(struct evconnlistener *lev) +{ + struct evconnlistener_event *lev_e = + EVUTIL_UPCAST(lev, struct evconnlistener_event, base); + return event_add(&lev_e->listener, NULL); +} + +static int +event_listener_disable(struct evconnlistener *lev) +{ + struct evconnlistener_event *lev_e = + EVUTIL_UPCAST(lev, struct evconnlistener_event, base); + return event_del(&lev_e->listener); +} + +evutil_socket_t +evconnlistener_get_fd(struct evconnlistener *lev) +{ + evutil_socket_t fd; + LOCK(lev); + fd = lev->ops->getfd(lev); + UNLOCK(lev); + return fd; +} + +static evutil_socket_t +event_listener_getfd(struct evconnlistener *lev) +{ + struct evconnlistener_event *lev_e = + EVUTIL_UPCAST(lev, struct evconnlistener_event, base); + return event_get_fd(&lev_e->listener); +} + +struct event_base * +evconnlistener_get_base(struct evconnlistener *lev) +{ + struct event_base *base; + LOCK(lev); + base = lev->ops->getbase(lev); + UNLOCK(lev); + return base; +} + +static struct event_base * +event_listener_getbase(struct evconnlistener *lev) +{ + struct evconnlistener_event *lev_e = + EVUTIL_UPCAST(lev, struct evconnlistener_event, base); + return event_get_base(&lev_e->listener); +} + +void +evconnlistener_set_cb(struct evconnlistener *lev, + evconnlistener_cb cb, void *arg) +{ + int enable = 0; + LOCK(lev); + if (lev->enabled && !lev->cb) + enable = 1; + lev->cb = cb; + lev->user_data = arg; + if (enable) + evconnlistener_enable(lev); + UNLOCK(lev); +} + +void +evconnlistener_set_error_cb(struct evconnlistener *lev, + evconnlistener_errorcb errorcb) +{ + LOCK(lev); + lev->errorcb = errorcb; + UNLOCK(lev); +} + +static void +listener_read_cb(evutil_socket_t fd, short what, void *p) +{ + struct evconnlistener *lev = p; + int err; + evconnlistener_cb cb; + evconnlistener_errorcb errorcb; + void *user_data; + LOCK(lev); + while (1) { + struct sockaddr_storage ss; +#ifdef WIN32 + int socklen = sizeof(ss); +#else + socklen_t socklen = sizeof(ss); +#endif + evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen); + if (new_fd < 0) + break; + if (socklen == 0) { + /* This can happen with some older linux kernels in + * response to nmap. */ + evutil_closesocket(new_fd); + continue; + } + + if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) + evutil_make_socket_nonblocking(new_fd); + + if (lev->cb == NULL) { + UNLOCK(lev); + return; + } + ++lev->refcnt; + cb = lev->cb; + user_data = lev->user_data; + UNLOCK(lev); + cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen, + user_data); + LOCK(lev); + if (lev->refcnt == 1) { + int freed = listener_decref_and_unlock(lev); + EVUTIL_ASSERT(freed); + return; + } + --lev->refcnt; + } + err = evutil_socket_geterror(fd); + if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) { + UNLOCK(lev); + return; + } + if (lev->errorcb != NULL) { + ++lev->refcnt; + errorcb = lev->errorcb; + user_data = lev->user_data; + UNLOCK(lev); + errorcb(lev, user_data); + LOCK(lev); + listener_decref_and_unlock(lev); + } else { + event_sock_warn(fd, "Error from accept() call"); + } +} + +#ifdef WIN32 +struct accepting_socket { + CRITICAL_SECTION lock; + struct event_overlapped overlapped; + SOCKET s; + int error; + struct deferred_cb deferred; + struct evconnlistener_iocp *lev; + ev_uint8_t buflen; + ev_uint8_t family; + unsigned free_on_cb:1; + char addrbuf[1]; +}; + +static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, + ev_ssize_t n, int ok); +static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg); + +static void +iocp_listener_event_add(struct evconnlistener_iocp *lev) +{ + if (lev->event_added) + return; + + lev->event_added = 1; + event_base_add_virtual(lev->event_base); +} + +static void +iocp_listener_event_del(struct evconnlistener_iocp *lev) +{ + if (!lev->event_added) + return; + + lev->event_added = 0; + event_base_del_virtual(lev->event_base); +} + +static struct accepting_socket * +new_accepting_socket(struct evconnlistener_iocp *lev, int family) +{ + struct accepting_socket *res; + int addrlen; + int buflen; + + if (family == AF_INET) + addrlen = sizeof(struct sockaddr_in); + else if (family == AF_INET6) + addrlen = sizeof(struct sockaddr_in6); + else + return NULL; + buflen = (addrlen+16)*2; + + res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen); + if (!res) + return NULL; + + event_overlapped_init(&res->overlapped, accepted_socket_cb); + res->s = INVALID_SOCKET; + res->lev = lev; + res->buflen = buflen; + res->family = family; + + event_deferred_cb_init(&res->deferred, + accepted_socket_invoke_user_cb, res); + + InitializeCriticalSectionAndSpinCount(&res->lock, 1000); + + return res; +} + +static void +free_and_unlock_accepting_socket(struct accepting_socket *as) +{ + /* requires lock. */ + if (as->s != INVALID_SOCKET) + closesocket(as->s); + + LeaveCriticalSection(&as->lock); + DeleteCriticalSection(&as->lock); + mm_free(as); +} + +static int +start_accepting(struct accepting_socket *as) +{ + /* requires lock */ + const struct win32_extension_fns *ext = event_get_win32_extension_fns(); + DWORD pending = 0; + SOCKET s = socket(as->family, SOCK_STREAM, 0); + int error = 0; + + if (!as->lev->base.enabled) + return 0; + + if (s == INVALID_SOCKET) { + error = WSAGetLastError(); + goto report_err; + } + + /* XXXX It turns out we need to do this again later. Does this call + * have any effect? */ + setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, + (char *)&as->lev->fd, sizeof(&as->lev->fd)); + + if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) + evutil_make_socket_nonblocking(s); + + if (event_iocp_port_associate(as->lev->port, s, 1) < 0) { + closesocket(s); + return -1; + } + + as->s = s; + + if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0, + as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped)) + { + /* Immediate success! */ + accepted_socket_cb(&as->overlapped, 1, 0, 1); + } else { + error = WSAGetLastError(); + if (error != ERROR_IO_PENDING) { + goto report_err; + } + } + + return 0; + +report_err: + as->error = error; + event_deferred_cb_schedule( + event_base_get_deferred_cb_queue(as->lev->event_base), + &as->deferred); + return 0; +} + +static void +stop_accepting(struct accepting_socket *as) +{ + /* requires lock. */ + SOCKET s = as->s; + as->s = INVALID_SOCKET; + closesocket(s); +} + +static void +accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg) +{ + struct accepting_socket *as = arg; + + struct sockaddr *sa_local=NULL, *sa_remote=NULL; + int socklen_local=0, socklen_remote=0; + const struct win32_extension_fns *ext = event_get_win32_extension_fns(); + struct evconnlistener *lev = &as->lev->base; + evutil_socket_t sock=-1; + void *data; + evconnlistener_cb cb=NULL; + evconnlistener_errorcb errorcb=NULL; + int error; + + EVUTIL_ASSERT(ext->GetAcceptExSockaddrs); + + LOCK(lev); + EnterCriticalSection(&as->lock); + if (as->free_on_cb) { + free_and_unlock_accepting_socket(as); + listener_decref_and_unlock(lev); + return; + } + + ++lev->refcnt; + + error = as->error; + if (error) { + as->error = 0; + errorcb = lev->errorcb; + } else { + ext->GetAcceptExSockaddrs( + as->addrbuf, 0, as->buflen/2, as->buflen/2, + &sa_local, &socklen_local, &sa_remote, + &socklen_remote); + sock = as->s; + cb = lev->cb; + as->s = INVALID_SOCKET; + + /* We need to call this so getsockname, getpeername, and + * shutdown work correctly on the accepted socket. */ + /* XXXX handle error? */ + setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, + (char *)&as->lev->fd, sizeof(&as->lev->fd)); + } + data = lev->user_data; + + LeaveCriticalSection(&as->lock); + UNLOCK(lev); + + if (errorcb) { + WSASetLastError(error); + errorcb(lev, data); + } else if (cb) { + cb(lev, sock, sa_remote, socklen_remote, data); + } + + LOCK(lev); + if (listener_decref_and_unlock(lev)) + return; + + EnterCriticalSection(&as->lock); + start_accepting(as); + LeaveCriticalSection(&as->lock); +} + +static void +accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok) +{ + struct accepting_socket *as = + EVUTIL_UPCAST(o, struct accepting_socket, overlapped); + + LOCK(&as->lev->base); + EnterCriticalSection(&as->lock); + if (ok) { + /* XXXX Don't do this if some EV_MT flag is set. */ + event_deferred_cb_schedule( + event_base_get_deferred_cb_queue(as->lev->event_base), + &as->deferred); + LeaveCriticalSection(&as->lock); + } else if (as->free_on_cb) { + struct evconnlistener *lev = &as->lev->base; + free_and_unlock_accepting_socket(as); + listener_decref_and_unlock(lev); + return; + } else if (as->s == INVALID_SOCKET) { + /* This is okay; we were disabled by iocp_listener_disable. */ + LeaveCriticalSection(&as->lock); + } else { + /* Some error on accept that we couldn't actually handle. */ + BOOL ok; + DWORD transfer = 0, flags=0; + event_sock_warn(as->s, "Unexpected error on AcceptEx"); + ok = WSAGetOverlappedResult(as->s, &o->overlapped, + &transfer, FALSE, &flags); + if (ok) { + /* well, that was confusing! */ + as->error = 1; + } else { + as->error = WSAGetLastError(); + } + event_deferred_cb_schedule( + event_base_get_deferred_cb_queue(as->lev->event_base), + &as->deferred); + LeaveCriticalSection(&as->lock); + } + UNLOCK(&as->lev->base); +} + +static int +iocp_listener_enable(struct evconnlistener *lev) +{ + int i; + struct evconnlistener_iocp *lev_iocp = + EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); + + LOCK(lev); + iocp_listener_event_add(lev_iocp); + for (i = 0; i < lev_iocp->n_accepting; ++i) { + struct accepting_socket *as = lev_iocp->accepting[i]; + if (!as) + continue; + EnterCriticalSection(&as->lock); + if (!as->free_on_cb && as->s == INVALID_SOCKET) + start_accepting(as); + LeaveCriticalSection(&as->lock); + } + UNLOCK(lev); + return 0; +} + +static int +iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown) +{ + int i; + struct evconnlistener_iocp *lev_iocp = + EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); + + LOCK(lev); + iocp_listener_event_del(lev_iocp); + for (i = 0; i < lev_iocp->n_accepting; ++i) { + struct accepting_socket *as = lev_iocp->accepting[i]; + if (!as) + continue; + EnterCriticalSection(&as->lock); + if (!as->free_on_cb && as->s != INVALID_SOCKET) { + if (shutdown) + as->free_on_cb = 1; + stop_accepting(as); + } + LeaveCriticalSection(&as->lock); + } + UNLOCK(lev); + return 0; +} + +static int +iocp_listener_disable(struct evconnlistener *lev) +{ + return iocp_listener_disable_impl(lev,0); +} + +static void +iocp_listener_destroy(struct evconnlistener *lev) +{ + struct evconnlistener_iocp *lev_iocp = + EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); + + if (! lev_iocp->shutting_down) { + lev_iocp->shutting_down = 1; + iocp_listener_disable_impl(lev,1); + } + +} + +static evutil_socket_t +iocp_listener_getfd(struct evconnlistener *lev) +{ + struct evconnlistener_iocp *lev_iocp = + EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); + return lev_iocp->fd; +} +static struct event_base * +iocp_listener_getbase(struct evconnlistener *lev) +{ + struct evconnlistener_iocp *lev_iocp = + EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); + return lev_iocp->event_base; +} + +static const struct evconnlistener_ops evconnlistener_iocp_ops = { + iocp_listener_enable, + iocp_listener_disable, + iocp_listener_destroy, + iocp_listener_destroy, /* shutdown */ + iocp_listener_getfd, + iocp_listener_getbase +}; + +/* XXX define some way to override this. */ +#define N_SOCKETS_PER_LISTENER 4 + +struct evconnlistener * +evconnlistener_new_async(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + evutil_socket_t fd) +{ + struct sockaddr_storage ss; + int socklen = sizeof(ss); + struct evconnlistener_iocp *lev; + int i; + + flags |= LEV_OPT_THREADSAFE; + + if (!base || !event_base_get_iocp(base)) + goto err; + + /* XXXX duplicate code */ + if (backlog > 0) { + if (listen(fd, backlog) < 0) + goto err; + } else if (backlog < 0) { + if (listen(fd, 128) < 0) + goto err; + } + if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) { + event_sock_warn(fd, "getsockname"); + goto err; + } + lev = mm_calloc(1, sizeof(struct evconnlistener_iocp)); + if (!lev) { + event_warn("calloc"); + goto err; + } + lev->base.ops = &evconnlistener_iocp_ops; + lev->base.cb = cb; + lev->base.user_data = ptr; + lev->base.flags = flags; + lev->base.refcnt = 1; + lev->base.enabled = 1; + + lev->port = event_base_get_iocp(base); + lev->fd = fd; + lev->event_base = base; + + + if (event_iocp_port_associate(lev->port, fd, 1) < 0) + goto err_free_lev; + + EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); + + lev->n_accepting = N_SOCKETS_PER_LISTENER; + lev->accepting = mm_calloc(lev->n_accepting, + sizeof(struct accepting_socket *)); + if (!lev->accepting) { + event_warn("calloc"); + goto err_delete_lock; + } + for (i = 0; i < lev->n_accepting; ++i) { + lev->accepting[i] = new_accepting_socket(lev, ss.ss_family); + if (!lev->accepting[i]) { + event_warnx("Couldn't create accepting socket"); + goto err_free_accepting; + } + if (cb && start_accepting(lev->accepting[i]) < 0) { + event_warnx("Couldn't start accepting on socket"); + EnterCriticalSection(&lev->accepting[i]->lock); + free_and_unlock_accepting_socket(lev->accepting[i]); + goto err_free_accepting; + } + ++lev->base.refcnt; + } + + iocp_listener_event_add(lev); + + return &lev->base; + +err_free_accepting: + mm_free(lev->accepting); + /* XXXX free the other elements. */ +err_delete_lock: + EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); +err_free_lev: + mm_free(lev); +err: + /* Don't close the fd, it is caller's responsibility. */ + return NULL; +} + +#endif diff --git a/libevent/log-internal.h b/libevent/log-internal.h new file mode 100644 index 0000000..211b3e1 --- /dev/null +++ b/libevent/log-internal.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _LOG_H_ +#define _LOG_H_ + +#include "event2/util.h" + +#ifdef __GNUC__ +#define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b))) +#define EV_NORETURN __attribute__((noreturn)) +#else +#define EV_CHECK_FMT(a,b) +#define EV_NORETURN +#endif + +#define _EVENT_ERR_ABORT ((int)0xdeaddead) + +void event_err(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3) EV_NORETURN; +void event_warn(const char *fmt, ...) EV_CHECK_FMT(1,2); +void event_sock_err(int eval, evutil_socket_t sock, const char *fmt, ...) EV_CHECK_FMT(3,4) EV_NORETURN; +void event_sock_warn(evutil_socket_t sock, const char *fmt, ...) EV_CHECK_FMT(2,3); +void event_errx(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3) EV_NORETURN; +void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2); +void event_msgx(const char *fmt, ...) EV_CHECK_FMT(1,2); +void _event_debugx(const char *fmt, ...) EV_CHECK_FMT(1,2); + +#ifdef USE_DEBUG +#define event_debug(x) _event_debugx x +#else +#define event_debug(x) do {;} while (0) +#endif + +#undef EV_CHECK_FMT + +#endif diff --git a/libevent/log.c b/libevent/log.c new file mode 100644 index 0000000..046e81f --- /dev/null +++ b/libevent/log.c @@ -0,0 +1,224 @@ +/* $OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ + +/* + * log.c + * + * Based on err.c, which was adapted from OpenBSD libc *err* *warn* code. + * + * Copyright (c) 2005-2012 Niels Provos and Nick Mathewson + * + * Copyright (c) 2000 Dug Song + * + * Copyright (c) 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. + */ + +#include "event2/event-config.h" + +#ifdef WIN32 +#include +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include +#include +#include "event2/event.h" +#include "event2/util.h" + +#include "log-internal.h" + +static void _warn_helper(int severity, const char *errstr, const char *fmt, + va_list ap); +static void event_log(int severity, const char *msg); +static void event_exit(int errcode) EV_NORETURN; + +static event_fatal_cb fatal_fn = NULL; + +void +event_set_fatal_callback(event_fatal_cb cb) +{ + fatal_fn = cb; +} + +static void +event_exit(int errcode) +{ + if (fatal_fn) { + fatal_fn(errcode); + exit(errcode); /* should never be reached */ + } else if (errcode == _EVENT_ERR_ABORT) + abort(); + else + exit(errcode); +} + +void +event_err(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_ERR, strerror(errno), fmt, ap); + va_end(ap); + event_exit(eval); +} + +void +event_warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_WARN, strerror(errno), fmt, ap); + va_end(ap); +} + +void +event_sock_err(int eval, evutil_socket_t sock, const char *fmt, ...) +{ + va_list ap; + int err = evutil_socket_geterror(sock); + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_ERR, evutil_socket_error_to_string(err), fmt, ap); + va_end(ap); + event_exit(eval); +} + +void +event_sock_warn(evutil_socket_t sock, const char *fmt, ...) +{ + va_list ap; + int err = evutil_socket_geterror(sock); + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_WARN, evutil_socket_error_to_string(err), fmt, ap); + va_end(ap); +} + +void +event_errx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_ERR, NULL, fmt, ap); + va_end(ap); + event_exit(eval); +} + +void +event_warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_WARN, NULL, fmt, ap); + va_end(ap); +} + +void +event_msgx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_MSG, NULL, fmt, ap); + va_end(ap); +} + +void +_event_debugx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warn_helper(_EVENT_LOG_DEBUG, NULL, fmt, ap); + va_end(ap); +} + +static void +_warn_helper(int severity, const char *errstr, const char *fmt, va_list ap) +{ + char buf[1024]; + size_t len; + + if (fmt != NULL) + evutil_vsnprintf(buf, sizeof(buf), fmt, ap); + else + buf[0] = '\0'; + + if (errstr) { + len = strlen(buf); + if (len < sizeof(buf) - 3) { + evutil_snprintf(buf + len, sizeof(buf) - len, ": %s", errstr); + } + } + + event_log(severity, buf); +} + +static event_log_cb log_fn = NULL; + +void +event_set_log_callback(event_log_cb cb) +{ + log_fn = cb; +} + +static void +event_log(int severity, const char *msg) +{ + if (log_fn) + log_fn(severity, msg); + else { + const char *severity_str; + switch (severity) { + case _EVENT_LOG_DEBUG: + severity_str = "debug"; + break; + case _EVENT_LOG_MSG: + severity_str = "msg"; + break; + case _EVENT_LOG_WARN: + severity_str = "warn"; + break; + case _EVENT_LOG_ERR: + severity_str = "err"; + break; + default: + severity_str = "???"; + break; + } + (void)fprintf(stderr, "[%s] %s\n", severity_str, msg); + } +} diff --git a/libevent/m4/acx_pthread.m4 b/libevent/m4/acx_pthread.m4 new file mode 100644 index 0000000..d2b1169 --- /dev/null +++ b/libevent/m4/acx_pthread.m4 @@ -0,0 +1,279 @@ +##### http://autoconf-archive.cryp.to/acx_pthread.html +# +# SYNOPSIS +# +# ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. +# It sets the PTHREAD_LIBS output variable to the threads library and +# linker flags, and the PTHREAD_CFLAGS output variable to any special +# C compiler flags that are needed. (The user can also force certain +# compiler flags/libs to be tested by setting these environment +# variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). +# (This is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these +# flags, but also link it with them as well. e.g. you should link +# with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS +# $LIBS +# +# If you are only building threads programs, you may wish to use +# these variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute +# constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads +# library is found, and ACTION-IF-NOT-FOUND is a list of commands to +# run it if it is not found. If ACTION-IF-FOUND is not specified, the +# default action will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or +# if you have any other suggestions or comments. This macro was based +# on work by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) +# (with help from M. Frigo), as well as ac_pthread and hb_pthread +# macros posted by Alejandro Forero Cuervo to the autoconf macro +# repository. We are also grateful for the helpful feedback of +# numerous users. +# +# LAST MODIFICATION +# +# 2007-07-29 +# +# COPYLEFT +# +# Copyright (c) 2007 Steven G. Johnson +# +# 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 3 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, see +# . +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. + +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_TRY_LINK([#include ], [int attr=$attr; return attr;], + [attr_name=$attr; break]) + done + AC_MSG_RESULT($attr_name) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) + else + PTHREAD_CC=$CC + fi +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/libevent/m4/libtool.m4 b/libevent/m4/libtool.m4 new file mode 100644 index 0000000..44e0ecf --- /dev/null +++ b/libevent/m4/libtool.m4 @@ -0,0 +1,7982 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/libevent/m4/ltoptions.m4 b/libevent/m4/ltoptions.m4 new file mode 100644 index 0000000..5d9acd8 --- /dev/null +++ b/libevent/m4/ltoptions.m4 @@ -0,0 +1,384 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/libevent/m4/ltsugar.m4 b/libevent/m4/ltsugar.m4 new file mode 100644 index 0000000..9000a05 --- /dev/null +++ b/libevent/m4/ltsugar.m4 @@ -0,0 +1,123 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/libevent/m4/ltversion.m4 b/libevent/m4/ltversion.m4 new file mode 100644 index 0000000..07a8602 --- /dev/null +++ b/libevent/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3337 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.2]) +m4_define([LT_PACKAGE_REVISION], [1.3337]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.2' +macro_revision='1.3337' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/libevent/m4/lt~obsolete.m4 b/libevent/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c573da9 --- /dev/null +++ b/libevent/m4/lt~obsolete.m4 @@ -0,0 +1,98 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/libevent/minheap-internal.h b/libevent/minheap-internal.h new file mode 100644 index 0000000..6d8e80a --- /dev/null +++ b/libevent/minheap-internal.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Copyright (c) 2006 Maxim Yegorushkin + * + * 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. + */ +#ifndef _MIN_HEAP_H_ +#define _MIN_HEAP_H_ + +#include "event2/event-config.h" +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/util.h" +#include "util-internal.h" +#include "mm-internal.h" + +typedef struct min_heap +{ + struct event** p; + unsigned n, a; +} min_heap_t; + +static inline void min_heap_ctor(min_heap_t* s); +static inline void min_heap_dtor(min_heap_t* s); +static inline void min_heap_elem_init(struct event* e); +static inline int min_heap_elt_is_top(const struct event *e); +static inline int min_heap_elem_greater(struct event *a, struct event *b); +static inline int min_heap_empty(min_heap_t* s); +static inline unsigned min_heap_size(min_heap_t* s); +static inline struct event* min_heap_top(min_heap_t* s); +static inline int min_heap_reserve(min_heap_t* s, unsigned n); +static inline int min_heap_push(min_heap_t* s, struct event* e); +static inline struct event* min_heap_pop(min_heap_t* s); +static inline int min_heap_erase(min_heap_t* s, struct event* e); +static inline void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e); +static inline void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e); + +int min_heap_elem_greater(struct event *a, struct event *b) +{ + return evutil_timercmp(&a->ev_timeout, &b->ev_timeout, >); +} + +void min_heap_ctor(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; } +void min_heap_dtor(min_heap_t* s) { if (s->p) mm_free(s->p); } +void min_heap_elem_init(struct event* e) { e->ev_timeout_pos.min_heap_idx = -1; } +int min_heap_empty(min_heap_t* s) { return 0u == s->n; } +unsigned min_heap_size(min_heap_t* s) { return s->n; } +struct event* min_heap_top(min_heap_t* s) { return s->n ? *s->p : 0; } + +int min_heap_push(min_heap_t* s, struct event* e) +{ + if (min_heap_reserve(s, s->n + 1)) + return -1; + min_heap_shift_up_(s, s->n++, e); + return 0; +} + +struct event* min_heap_pop(min_heap_t* s) +{ + if (s->n) + { + struct event* e = *s->p; + min_heap_shift_down_(s, 0u, s->p[--s->n]); + e->ev_timeout_pos.min_heap_idx = -1; + return e; + } + return 0; +} + +int min_heap_elt_is_top(const struct event *e) +{ + return e->ev_timeout_pos.min_heap_idx == 0; +} + +int min_heap_erase(min_heap_t* s, struct event* e) +{ + if (-1 != e->ev_timeout_pos.min_heap_idx) + { + struct event *last = s->p[--s->n]; + unsigned parent = (e->ev_timeout_pos.min_heap_idx - 1) / 2; + /* we replace e with the last element in the heap. We might need to + shift it upward if it is less than its parent, or downward if it is + greater than one or both its children. Since the children are known + to be less than the parent, it can't need to shift both up and + down. */ + if (e->ev_timeout_pos.min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last)) + min_heap_shift_up_(s, e->ev_timeout_pos.min_heap_idx, last); + else + min_heap_shift_down_(s, e->ev_timeout_pos.min_heap_idx, last); + e->ev_timeout_pos.min_heap_idx = -1; + return 0; + } + return -1; +} + +int min_heap_reserve(min_heap_t* s, unsigned n) +{ + if (s->a < n) + { + struct event** p; + unsigned a = s->a ? s->a * 2 : 8; + if (a < n) + a = n; + if (!(p = (struct event**)mm_realloc(s->p, a * sizeof *p))) + return -1; + s->p = p; + s->a = a; + } + return 0; +} + +void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e) +{ + unsigned parent = (hole_index - 1) / 2; + while (hole_index && min_heap_elem_greater(s->p[parent], e)) + { + (s->p[hole_index] = s->p[parent])->ev_timeout_pos.min_heap_idx = hole_index; + hole_index = parent; + parent = (hole_index - 1) / 2; + } + (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; +} + +void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e) +{ + unsigned min_child = 2 * (hole_index + 1); + while (min_child <= s->n) + { + min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]); + if (!(min_heap_elem_greater(e, s->p[min_child]))) + break; + (s->p[hole_index] = s->p[min_child])->ev_timeout_pos.min_heap_idx = hole_index; + hole_index = min_child; + min_child = 2 * (hole_index + 1); + } + (s->p[hole_index] = e)->ev_timeout_pos.min_heap_idx = hole_index; +} + +#endif /* _MIN_HEAP_H_ */ diff --git a/libevent/mm-internal.h b/libevent/mm-internal.h new file mode 100644 index 0000000..b375155 --- /dev/null +++ b/libevent/mm-internal.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _EVENT_MM_INTERNAL_H +#define _EVENT_MM_INTERNAL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _EVENT_DISABLE_MM_REPLACEMENT +/* Internal use only: Memory allocation functions. We give them nice short + * mm_names for our own use, but make sure that the symbols have longer names + * so they don't conflict with other libraries (like, say, libmm). */ +void *event_mm_malloc_(size_t sz); +void *event_mm_calloc_(size_t count, size_t size); +char *event_mm_strdup_(const char *s); +void *event_mm_realloc_(void *p, size_t sz); +void event_mm_free_(void *p); +#define mm_malloc(sz) event_mm_malloc_(sz) +#define mm_calloc(count, size) event_mm_calloc_((count), (size)) +#define mm_strdup(s) event_mm_strdup_(s) +#define mm_realloc(p, sz) event_mm_realloc_((p), (sz)) +#define mm_free(p) event_mm_free_(p) +#else +#define mm_malloc(sz) malloc(sz) +#define mm_calloc(n, sz) calloc((n), (sz)) +#define mm_strdup(s) strdup(s) +#define mm_realloc(p, sz) realloc((p), (sz)) +#define mm_free(p) free(p) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libevent/poll.c b/libevent/poll.c new file mode 100644 index 0000000..04d311b --- /dev/null +++ b/libevent/poll.c @@ -0,0 +1,333 @@ +/* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ + +/* + * Copyright 2000-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "event-internal.h" +#include "evsignal-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "event2/thread.h" +#include "evthread-internal.h" + +struct pollidx { + int idxplus1; +}; + +struct pollop { + int event_count; /* Highest number alloc */ + int nfds; /* Highest number used */ + int realloc_copy; /* True iff we must realloc + * event_set_copy */ + struct pollfd *event_set; + struct pollfd *event_set_copy; +}; + +static void *poll_init(struct event_base *); +static int poll_add(struct event_base *, int, short old, short events, void *_idx); +static int poll_del(struct event_base *, int, short old, short events, void *_idx); +static int poll_dispatch(struct event_base *, struct timeval *); +static void poll_dealloc(struct event_base *); + +const struct eventop pollops = { + "poll", + poll_init, + poll_add, + poll_del, + poll_dispatch, + poll_dealloc, + 0, /* doesn't need_reinit */ + EV_FEATURE_FDS, + sizeof(struct pollidx), +}; + +static void * +poll_init(struct event_base *base) +{ + struct pollop *pollop; + + if (!(pollop = mm_calloc(1, sizeof(struct pollop)))) + return (NULL); + + evsig_init(base); + + return (pollop); +} + +#ifdef CHECK_INVARIANTS +static void +poll_check_ok(struct pollop *pop) +{ + int i, idx; + struct event *ev; + + for (i = 0; i < pop->fd_count; ++i) { + idx = pop->idxplus1_by_fd[i]-1; + if (idx < 0) + continue; + EVUTIL_ASSERT(pop->event_set[idx].fd == i); + } + for (i = 0; i < pop->nfds; ++i) { + struct pollfd *pfd = &pop->event_set[i]; + EVUTIL_ASSERT(pop->idxplus1_by_fd[pfd->fd] == i+1); + } +} +#else +#define poll_check_ok(pop) +#endif + +static int +poll_dispatch(struct event_base *base, struct timeval *tv) +{ + int res, i, j, nfds; + long msec = -1; + struct pollop *pop = base->evbase; + struct pollfd *event_set; + + poll_check_ok(pop); + + nfds = pop->nfds; + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT + if (base->th_base_lock) { + /* If we're using this backend in a multithreaded setting, + * then we need to work on a copy of event_set, so that we can + * let other threads modify the main event_set while we're + * polling. If we're not multithreaded, then we'll skip the + * copy step here to save memory and time. */ + if (pop->realloc_copy) { + struct pollfd *tmp = mm_realloc(pop->event_set_copy, + pop->event_count * sizeof(struct pollfd)); + if (tmp == NULL) { + event_warn("realloc"); + return -1; + } + pop->event_set_copy = tmp; + pop->realloc_copy = 0; + } + memcpy(pop->event_set_copy, pop->event_set, + sizeof(struct pollfd)*nfds); + event_set = pop->event_set_copy; + } else { + event_set = pop->event_set; + } +#else + event_set = pop->event_set; +#endif + + if (tv != NULL) { + msec = evutil_tv_to_msec(tv); + if (msec < 0 || msec > INT_MAX) + msec = INT_MAX; + } + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = poll(event_set, nfds, msec); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + if (res == -1) { + if (errno != EINTR) { + event_warn("poll"); + return (-1); + } + + return (0); + } + + event_debug(("%s: poll reports %d", __func__, res)); + + if (res == 0 || nfds == 0) + return (0); + + i = random() % nfds; + for (j = 0; j < nfds; j++) { + int what; + if (++i == nfds) + i = 0; + what = event_set[i].revents; + if (!what) + continue; + + res = 0; + + /* If the file gets closed notify */ + if (what & (POLLHUP|POLLERR)) + what |= POLLIN|POLLOUT; + if (what & POLLIN) + res |= EV_READ; + if (what & POLLOUT) + res |= EV_WRITE; + if (res == 0) + continue; + + evmap_io_active(base, event_set[i].fd, res); + } + + return (0); +} + +static int +poll_add(struct event_base *base, int fd, short old, short events, void *_idx) +{ + struct pollop *pop = base->evbase; + struct pollfd *pfd = NULL; + struct pollidx *idx = _idx; + int i; + + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); + if (!(events & (EV_READ|EV_WRITE))) + return (0); + + poll_check_ok(pop); + if (pop->nfds + 1 >= pop->event_count) { + struct pollfd *tmp_event_set; + int tmp_event_count; + + if (pop->event_count < 32) + tmp_event_count = 32; + else + tmp_event_count = pop->event_count * 2; + + /* We need more file descriptors */ + tmp_event_set = mm_realloc(pop->event_set, + tmp_event_count * sizeof(struct pollfd)); + if (tmp_event_set == NULL) { + event_warn("realloc"); + return (-1); + } + pop->event_set = tmp_event_set; + + pop->event_count = tmp_event_count; + pop->realloc_copy = 1; + } + + i = idx->idxplus1 - 1; + + if (i >= 0) { + pfd = &pop->event_set[i]; + } else { + i = pop->nfds++; + pfd = &pop->event_set[i]; + pfd->events = 0; + pfd->fd = fd; + idx->idxplus1 = i + 1; + } + + pfd->revents = 0; + if (events & EV_WRITE) + pfd->events |= POLLOUT; + if (events & EV_READ) + pfd->events |= POLLIN; + poll_check_ok(pop); + + return (0); +} + +/* + * Nothing to be done here. + */ + +static int +poll_del(struct event_base *base, int fd, short old, short events, void *_idx) +{ + struct pollop *pop = base->evbase; + struct pollfd *pfd = NULL; + struct pollidx *idx = _idx; + int i; + + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); + if (!(events & (EV_READ|EV_WRITE))) + return (0); + + poll_check_ok(pop); + i = idx->idxplus1 - 1; + if (i < 0) + return (-1); + + /* Do we still want to read or write? */ + pfd = &pop->event_set[i]; + if (events & EV_READ) + pfd->events &= ~POLLIN; + if (events & EV_WRITE) + pfd->events &= ~POLLOUT; + poll_check_ok(pop); + if (pfd->events) + /* Another event cares about that fd. */ + return (0); + + /* Okay, so we aren't interested in that fd anymore. */ + idx->idxplus1 = 0; + + --pop->nfds; + if (i != pop->nfds) { + /* + * Shift the last pollfd down into the now-unoccupied + * position. + */ + memcpy(&pop->event_set[i], &pop->event_set[pop->nfds], + sizeof(struct pollfd)); + idx = evmap_io_get_fdinfo(&base->io, pop->event_set[i].fd); + EVUTIL_ASSERT(idx); + EVUTIL_ASSERT(idx->idxplus1 == pop->nfds + 1); + idx->idxplus1 = i + 1; + } + + poll_check_ok(pop); + return (0); +} + +static void +poll_dealloc(struct event_base *base) +{ + struct pollop *pop = base->evbase; + + evsig_dealloc(base); + if (pop->event_set) + mm_free(pop->event_set); + if (pop->event_set_copy) + mm_free(pop->event_set_copy); + + memset(pop, 0, sizeof(struct pollop)); + mm_free(pop); +} diff --git a/libevent/ratelim-internal.h b/libevent/ratelim-internal.h new file mode 100644 index 0000000..4e3f8c4 --- /dev/null +++ b/libevent/ratelim-internal.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _RATELIM_INTERNAL_H_ +#define _RATELIM_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event2/util.h" + +/** A token bucket is an internal structure that tracks how many bytes we are + * currently willing to read or write on a given bufferevent or group of + * bufferevents */ +struct ev_token_bucket { + /** How many bytes are we willing to read or write right now? These + * values are signed so that we can do "defecit spending" */ + ev_ssize_t read_limit, write_limit; + /** When was this bucket last updated? Measured in abstract 'ticks' + * relative to the token bucket configuration. */ + ev_uint32_t last_updated; +}; + +/** Configuration info for a token bucket or set of token buckets. */ +struct ev_token_bucket_cfg { + /** How many bytes are we willing to read on average per tick? */ + size_t read_rate; + /** How many bytes are we willing to read at most in any one tick? */ + size_t read_maximum; + /** How many bytes are we willing to write on average per tick? */ + size_t write_rate; + /** How many bytes are we willing to write at most in any one tick? */ + size_t write_maximum; + + /* How long is a tick? Note that fractions of a millisecond are + * ignored. */ + struct timeval tick_timeout; + + /* How long is a tick, in milliseconds? Derived from tick_timeout. */ + unsigned msec_per_tick; +}; + +/** The current tick is 'current_tick': add bytes to 'bucket' as specified in + * 'cfg'. */ +int ev_token_bucket_update(struct ev_token_bucket *bucket, + const struct ev_token_bucket_cfg *cfg, + ev_uint32_t current_tick); + +/** In which tick does 'tv' fall according to 'cfg'? Note that ticks can + * overflow easily; your code needs to handle this. */ +ev_uint32_t ev_token_bucket_get_tick(const struct timeval *tv, + const struct ev_token_bucket_cfg *cfg); + +/** Adjust 'bucket' to respect 'cfg', and note that it was last updated in + * 'current_tick'. If 'reinitialize' is true, we are changing the + * configuration of 'bucket'; otherwise, we are setting it up for the first + * time. + */ +int ev_token_bucket_init(struct ev_token_bucket *bucket, + const struct ev_token_bucket_cfg *cfg, + ev_uint32_t current_tick, + int reinitialize); + +int bufferevent_remove_from_rate_limit_group_internal(struct bufferevent *bev, + int unsuspend); + +/** Decrease the read limit of 'b' by 'n' bytes */ +#define ev_token_bucket_decrement_read(b,n) \ + do { \ + (b)->read_limit -= (n); \ + } while (0) +/** Decrease the write limit of 'b' by 'n' bytes */ +#define ev_token_bucket_decrement_write(b,n) \ + do { \ + (b)->write_limit -= (n); \ + } while (0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libevent/sample/Makefile.am b/libevent/sample/Makefile.am new file mode 100644 index 0000000..c926f4e --- /dev/null +++ b/libevent/sample/Makefile.am @@ -0,0 +1,29 @@ +# sample/Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + +AUTOMAKE_OPTIONS = foreign no-dependencies + +LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include + +noinst_PROGRAMS = event-test time-test signal-test dns-example hello-world http-server + +event_test_SOURCES = event-test.c +time_test_SOURCES = time-test.c +signal_test_SOURCES = signal-test.c +dns_example_SOURCES = dns-example.c +hello_world_SOURCES = hello-world.c +http_server_SOURCES = http-server.c + +if OPENSSL +noinst_PROGRAMS += le-proxy +le_proxy_SOURCES = le-proxy.c +le_proxy_LDADD = $(LDADD) ../libevent_openssl.la -lssl -lcrypto ${OPENSSL_LIBADD} +endif + +verify: + +DISTCLEANFILES = *~ diff --git a/libevent/sample/Makefile.in b/libevent/sample/Makefile.in new file mode 100644 index 0000000..1acb3e5 --- /dev/null +++ b/libevent/sample/Makefile.in @@ -0,0 +1,605 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# sample/Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = event-test$(EXEEXT) time-test$(EXEEXT) \ + signal-test$(EXEEXT) dns-example$(EXEEXT) hello-world$(EXEEXT) \ + http-server$(EXEEXT) $(am__EXEEXT_1) +@OPENSSL_TRUE@am__append_1 = le-proxy +subdir = sample +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@OPENSSL_TRUE@am__EXEEXT_1 = le-proxy$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_dns_example_OBJECTS = dns-example.$(OBJEXT) +dns_example_OBJECTS = $(am_dns_example_OBJECTS) +dns_example_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +dns_example_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_event_test_OBJECTS = event-test.$(OBJEXT) +event_test_OBJECTS = $(am_event_test_OBJECTS) +event_test_LDADD = $(LDADD) +event_test_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +am_hello_world_OBJECTS = hello-world.$(OBJEXT) +hello_world_OBJECTS = $(am_hello_world_OBJECTS) +hello_world_LDADD = $(LDADD) +hello_world_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +am_http_server_OBJECTS = http-server.$(OBJEXT) +http_server_OBJECTS = $(am_http_server_OBJECTS) +http_server_LDADD = $(LDADD) +http_server_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +am__le_proxy_SOURCES_DIST = le-proxy.c +@OPENSSL_TRUE@am_le_proxy_OBJECTS = le-proxy.$(OBJEXT) +le_proxy_OBJECTS = $(am_le_proxy_OBJECTS) +am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) ../libevent.la +@OPENSSL_TRUE@le_proxy_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@OPENSSL_TRUE@ ../libevent_openssl.la $(am__DEPENDENCIES_1) +am_signal_test_OBJECTS = signal-test.$(OBJEXT) +signal_test_OBJECTS = $(am_signal_test_OBJECTS) +signal_test_LDADD = $(LDADD) +signal_test_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +am_time_test_OBJECTS = time-test.$(OBJEXT) +time_test_OBJECTS = $(am_time_test_OBJECTS) +time_test_LDADD = $(LDADD) +time_test_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = +am__depfiles_maybe = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(dns_example_SOURCES) $(event_test_SOURCES) \ + $(hello_world_SOURCES) $(http_server_SOURCES) \ + $(le_proxy_SOURCES) $(signal_test_SOURCES) \ + $(time_test_SOURCES) +DIST_SOURCES = $(dns_example_SOURCES) $(event_test_SOURCES) \ + $(hello_world_SOURCES) $(http_server_SOURCES) \ + $(am__le_proxy_SOURCES_DIST) $(signal_test_SOURCES) \ + $(time_test_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EV_LIB_GDI = @EV_LIB_GDI@ +EV_LIB_WS32 = @EV_LIB_WS32@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBEVENT_GC_SECTIONS = @LIBEVENT_GC_SECTIONS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIBADD = @OPENSSL_LIBADD@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acx_pthread_config = @acx_pthread_config@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign no-dependencies +LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include +event_test_SOURCES = event-test.c +time_test_SOURCES = time-test.c +signal_test_SOURCES = signal-test.c +dns_example_SOURCES = dns-example.c +hello_world_SOURCES = hello-world.c +http_server_SOURCES = http-server.c +@OPENSSL_TRUE@le_proxy_SOURCES = le-proxy.c +@OPENSSL_TRUE@le_proxy_LDADD = $(LDADD) ../libevent_openssl.la -lssl -lcrypto ${OPENSSL_LIBADD} +DISTCLEANFILES = *~ +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sample/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign sample/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +dns-example$(EXEEXT): $(dns_example_OBJECTS) $(dns_example_DEPENDENCIES) $(EXTRA_dns_example_DEPENDENCIES) + @rm -f dns-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dns_example_OBJECTS) $(dns_example_LDADD) $(LIBS) +event-test$(EXEEXT): $(event_test_OBJECTS) $(event_test_DEPENDENCIES) $(EXTRA_event_test_DEPENDENCIES) + @rm -f event-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(event_test_OBJECTS) $(event_test_LDADD) $(LIBS) +hello-world$(EXEEXT): $(hello_world_OBJECTS) $(hello_world_DEPENDENCIES) $(EXTRA_hello_world_DEPENDENCIES) + @rm -f hello-world$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(hello_world_OBJECTS) $(hello_world_LDADD) $(LIBS) +http-server$(EXEEXT): $(http_server_OBJECTS) $(http_server_DEPENDENCIES) $(EXTRA_http_server_DEPENDENCIES) + @rm -f http-server$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(http_server_OBJECTS) $(http_server_LDADD) $(LIBS) +le-proxy$(EXEEXT): $(le_proxy_OBJECTS) $(le_proxy_DEPENDENCIES) $(EXTRA_le_proxy_DEPENDENCIES) + @rm -f le-proxy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(le_proxy_OBJECTS) $(le_proxy_LDADD) $(LIBS) +signal-test$(EXEEXT): $(signal_test_OBJECTS) $(signal_test_DEPENDENCIES) $(EXTRA_signal_test_DEPENDENCIES) + @rm -f signal-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(signal_test_OBJECTS) $(signal_test_LDADD) $(LIBS) +time-test$(EXEEXT): $(time_test_OBJECTS) $(time_test_DEPENDENCIES) $(EXTRA_time_test_DEPENDENCIES) + @rm -f time-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(time_test_OBJECTS) $(time_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +verify: + +# 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/libevent/sample/dns-example.c b/libevent/sample/dns-example.c new file mode 100644 index 0000000..f97a0c6 --- /dev/null +++ b/libevent/sample/dns-example.c @@ -0,0 +1,239 @@ +/* + This example code shows how to use the high-level, low-level, and + server-level interfaces of evdns. + + XXX It's pretty ugly and should probably be cleaned up. + */ + +#include + +/* Compatibility for possible missing IPv6 declarations */ +#include "../ipv6-internal.h" + +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#endif + +#include +#include +#include +#include + +#ifdef _EVENT_HAVE_NETINET_IN6_H +#include +#endif + +#include +#include +#include + +#define u32 ev_uint32_t +#define u8 ev_uint8_t + +static const char * +debug_ntoa(u32 address) +{ + static char buf[32]; + u32 a = ntohl(address); + evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d", + (int)(u8)((a>>24)&0xff), + (int)(u8)((a>>16)&0xff), + (int)(u8)((a>>8 )&0xff), + (int)(u8)((a )&0xff)); + return buf; +} + +static void +main_callback(int result, char type, int count, int ttl, + void *addrs, void *orig) { + char *n = (char*)orig; + int i; + for (i = 0; i < count; ++i) { + if (type == DNS_IPv4_A) { + printf("%s: %s\n", n, debug_ntoa(((u32*)addrs)[i])); + } else if (type == DNS_PTR) { + printf("%s: %s\n", n, ((char**)addrs)[i]); + } + } + if (!count) { + printf("%s: No answer (%d)\n", n, result); + } + fflush(stdout); +} + +static void +gai_callback(int err, struct evutil_addrinfo *ai, void *arg) +{ + const char *name = arg; + int i; + if (err) { + printf("%s: %s\n", name, evutil_gai_strerror(err)); + } + if (ai && ai->ai_canonname) + printf(" %s ==> %s\n", name, ai->ai_canonname); + for (i=0; ai; ai = ai->ai_next, ++i) { + char buf[128]; + if (ai->ai_family == PF_INET) { + struct sockaddr_in *sin = + (struct sockaddr_in*)ai->ai_addr; + evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, + sizeof(buf)); + printf("[%d] %s: %s\n",i,name,buf); + } else { + struct sockaddr_in6 *sin6 = + (struct sockaddr_in6*)ai->ai_addr; + evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, + sizeof(buf)); + printf("[%d] %s: %s\n",i,name,buf); + } + } +} + +static void +evdns_server_callback(struct evdns_server_request *req, void *data) +{ + int i, r; + (void)data; + /* dummy; give 192.168.11.11 as an answer for all A questions, + * give foo.bar.example.com as an answer for all PTR questions. */ + for (i = 0; i < req->nquestions; ++i) { + u32 ans = htonl(0xc0a80b0bUL); + if (req->questions[i]->type == EVDNS_TYPE_A && + req->questions[i]->dns_question_class == EVDNS_CLASS_INET) { + printf(" -- replying for %s (A)\n", req->questions[i]->name); + r = evdns_server_request_add_a_reply(req, req->questions[i]->name, + 1, &ans, 10); + if (r<0) + printf("eeep, didn't work.\n"); + } else if (req->questions[i]->type == EVDNS_TYPE_PTR && + req->questions[i]->dns_question_class == EVDNS_CLASS_INET) { + printf(" -- replying for %s (PTR)\n", req->questions[i]->name); + r = evdns_server_request_add_ptr_reply(req, NULL, req->questions[i]->name, + "foo.bar.example.com", 10); + if (r<0) + printf("ugh, no luck"); + } else { + printf(" -- skipping %s [%d %d]\n", req->questions[i]->name, + req->questions[i]->type, req->questions[i]->dns_question_class); + } + } + + r = evdns_server_request_respond(req, 0); + if (r<0) + printf("eeek, couldn't send reply.\n"); +} + +static int verbose = 0; + +static void +logfn(int is_warn, const char *msg) { + if (!is_warn && !verbose) + return; + fprintf(stderr, "%s: %s\n", is_warn?"WARN":"INFO", msg); +} + +int +main(int c, char **v) { + int idx; + int reverse = 0, servertest = 0, use_getaddrinfo = 0; + struct event_base *event_base = NULL; + struct evdns_base *evdns_base = NULL; + if (c<2) { + fprintf(stderr, "syntax: %s [-x] [-v] hostname\n", v[0]); + fprintf(stderr, "syntax: %s [-servertest]\n", v[0]); + return 1; + } + idx = 1; + while (idx < c && v[idx][0] == '-') { + if (!strcmp(v[idx], "-x")) + reverse = 1; + else if (!strcmp(v[idx], "-v")) + verbose = 1; + else if (!strcmp(v[idx], "-g")) + use_getaddrinfo = 1; + else if (!strcmp(v[idx], "-servertest")) + servertest = 1; + else + fprintf(stderr, "Unknown option %s\n", v[idx]); + ++idx; + } + +#ifdef WIN32 + { + WSADATA WSAData; + WSAStartup(0x101, &WSAData); + } +#endif + + event_base = event_base_new(); + evdns_base = evdns_base_new(event_base, 0); + evdns_set_log_fn(logfn); + + if (servertest) { + evutil_socket_t sock; + struct sockaddr_in my_addr; + sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock == -1) { + perror("socket"); + exit(1); + } + evutil_make_socket_nonblocking(sock); + my_addr.sin_family = AF_INET; + my_addr.sin_port = htons(10053); + my_addr.sin_addr.s_addr = INADDR_ANY; + if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr))<0) { + perror("bind"); + exit(1); + } + evdns_add_server_port_with_base(event_base, sock, 0, evdns_server_callback, NULL); + } + if (idx < c) { + int res; +#ifdef WIN32 + res = evdns_base_config_windows_nameservers(evdns_base); +#else + res = evdns_base_resolv_conf_parse(evdns_base, DNS_OPTION_NAMESERVERS, + "/etc/resolv.conf"); +#endif + if (res < 0) { + fprintf(stderr, "Couldn't configure nameservers"); + return 1; + } + } + + printf("EVUTIL_AI_CANONNAME in example = %d\n", EVUTIL_AI_CANONNAME); + for (; idx < c; ++idx) { + if (reverse) { + struct in_addr addr; + if (evutil_inet_pton(AF_INET, v[idx], &addr)!=1) { + fprintf(stderr, "Skipping non-IP %s\n", v[idx]); + continue; + } + fprintf(stderr, "resolving %s...\n",v[idx]); + evdns_base_resolve_reverse(evdns_base, &addr, 0, main_callback, v[idx]); + } else if (use_getaddrinfo) { + struct evutil_addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = EVUTIL_AI_CANONNAME; + fprintf(stderr, "resolving (fwd) %s...\n",v[idx]); + evdns_getaddrinfo(evdns_base, v[idx], NULL, &hints, + gai_callback, v[idx]); + } else { + fprintf(stderr, "resolving (fwd) %s...\n",v[idx]); + evdns_base_resolve_ipv4(evdns_base, v[idx], 0, main_callback, v[idx]); + } + } + fflush(stdout); + event_base_dispatch(event_base); + return 0; +} + diff --git a/libevent/sample/event-test.c b/libevent/sample/event-test.c new file mode 100644 index 0000000..e4d7a42 --- /dev/null +++ b/libevent/sample/event-test.c @@ -0,0 +1,143 @@ +/* + * XXX This sample code was once meant to show how to use the basic Libevent + * interfaces, but it never worked on non-Unix platforms, and some of the + * interfaces have changed since it was first written. It should probably + * be removed or replaced with something better. + * + * Compile with: + * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent + */ + +#include + +#include +#include +#ifndef WIN32 +#include +#include +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include + +#include + +static void +fifo_read(int fd, short event, void *arg) +{ + char buf[255]; + int len; + struct event *ev = arg; +#ifdef WIN32 + DWORD dwBytesRead; +#endif + + /* Reschedule this event */ + event_add(ev, NULL); + + fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n", + fd, event, arg); +#ifdef WIN32 + len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL); + + /* Check for end of file. */ + if (len && dwBytesRead == 0) { + fprintf(stderr, "End Of File"); + event_del(ev); + return; + } + + buf[dwBytesRead] = '\0'; +#else + len = read(fd, buf, sizeof(buf) - 1); + + if (len == -1) { + perror("read"); + return; + } else if (len == 0) { + fprintf(stderr, "Connection closed\n"); + return; + } + + buf[len] = '\0'; +#endif + fprintf(stdout, "Read: %s\n", buf); +} + +int +main(int argc, char **argv) +{ + struct event evfifo; +#ifdef WIN32 + HANDLE socket; + /* Open a file. */ + socket = CreateFileA("test.txt", /* open File */ + GENERIC_READ, /* open for reading */ + 0, /* do not share */ + NULL, /* no security */ + OPEN_EXISTING, /* existing file only */ + FILE_ATTRIBUTE_NORMAL, /* normal file */ + NULL); /* no attr. template */ + + if (socket == INVALID_HANDLE_VALUE) + return 1; + +#else + struct stat st; + const char *fifo = "event.fifo"; + int socket; + + if (lstat(fifo, &st) == 0) { + if ((st.st_mode & S_IFMT) == S_IFREG) { + errno = EEXIST; + perror("lstat"); + exit(1); + } + } + + unlink(fifo); + if (mkfifo(fifo, 0600) == -1) { + perror("mkfifo"); + exit(1); + } + + /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */ +#ifdef __linux + socket = open(fifo, O_RDWR | O_NONBLOCK, 0); +#else + socket = open(fifo, O_RDONLY | O_NONBLOCK, 0); +#endif + + if (socket == -1) { + perror("open"); + exit(1); + } + + fprintf(stderr, "Write data to %s\n", fifo); +#endif + /* Initalize the event library */ + event_init(); + + /* Initalize one event */ +#ifdef WIN32 + event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo); +#else + event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo); +#endif + + /* Add it to the active events, without a timeout */ + event_add(&evfifo, NULL); + + event_dispatch(); +#ifdef WIN32 + CloseHandle(socket); +#endif + return (0); +} + diff --git a/libevent/sample/hello-world.c b/libevent/sample/hello-world.c new file mode 100644 index 0000000..d40af52 --- /dev/null +++ b/libevent/sample/hello-world.c @@ -0,0 +1,141 @@ +/* + This exmple program provides a trivial server program that listens for TCP + connections on port 9995. When they arrive, it writes a short message to + each client connection, and closes each connection once it is flushed. + + Where possible, it exits cleanly in response to a SIGINT (ctrl-c). +*/ + + +#include +#include +#include +#include +#ifndef WIN32 +#include +# ifdef _XOPEN_SOURCE_EXTENDED +# include +# endif +#include +#endif + +#include +#include +#include +#include +#include + +static const char MESSAGE[] = "Hello, World!\n"; + +static const int PORT = 9995; + +static void listener_cb(struct evconnlistener *, evutil_socket_t, + struct sockaddr *, int socklen, void *); +static void conn_writecb(struct bufferevent *, void *); +static void conn_eventcb(struct bufferevent *, short, void *); +static void signal_cb(evutil_socket_t, short, void *); + +int +main(int argc, char **argv) +{ + struct event_base *base; + struct evconnlistener *listener; + struct event *signal_event; + + struct sockaddr_in sin; +#ifdef WIN32 + WSADATA wsa_data; + WSAStartup(0x0201, &wsa_data); +#endif + + base = event_base_new(); + if (!base) { + fprintf(stderr, "Could not initialize libevent!\n"); + return 1; + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(PORT); + + listener = evconnlistener_new_bind(base, listener_cb, (void *)base, + LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, + (struct sockaddr*)&sin, + sizeof(sin)); + + if (!listener) { + fprintf(stderr, "Could not create a listener!\n"); + return 1; + } + + signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base); + + if (!signal_event || event_add(signal_event, NULL)<0) { + fprintf(stderr, "Could not create/add a signal event!\n"); + return 1; + } + + event_base_dispatch(base); + + evconnlistener_free(listener); + event_free(signal_event); + event_base_free(base); + + printf("done\n"); + return 0; +} + +static void +listener_cb(struct evconnlistener *listener, evutil_socket_t fd, + struct sockaddr *sa, int socklen, void *user_data) +{ + struct event_base *base = user_data; + struct bufferevent *bev; + + bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); + if (!bev) { + fprintf(stderr, "Error constructing bufferevent!"); + event_base_loopbreak(base); + return; + } + bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL); + bufferevent_enable(bev, EV_WRITE); + bufferevent_disable(bev, EV_READ); + + bufferevent_write(bev, MESSAGE, strlen(MESSAGE)); +} + +static void +conn_writecb(struct bufferevent *bev, void *user_data) +{ + struct evbuffer *output = bufferevent_get_output(bev); + if (evbuffer_get_length(output) == 0) { + printf("flushed answer\n"); + bufferevent_free(bev); + } +} + +static void +conn_eventcb(struct bufferevent *bev, short events, void *user_data) +{ + if (events & BEV_EVENT_EOF) { + printf("Connection closed.\n"); + } else if (events & BEV_EVENT_ERROR) { + printf("Got an error on the connection: %s\n", + strerror(errno));/*XXX win32*/ + } + /* None of the other events can happen here, since we haven't enabled + * timeouts */ + bufferevent_free(bev); +} + +static void +signal_cb(evutil_socket_t sig, short events, void *user_data) +{ + struct event_base *base = user_data; + struct timeval delay = { 2, 0 }; + + printf("Caught an interrupt signal; exiting cleanly in two seconds.\n"); + + event_base_loopexit(base, &delay); +} diff --git a/libevent/sample/http-server.c b/libevent/sample/http-server.c new file mode 100644 index 0000000..fb45579 --- /dev/null +++ b/libevent/sample/http-server.c @@ -0,0 +1,405 @@ +/* + A trivial static http webserver using Libevent's evhttp. + + This is not the best code in the world, and it does some fairly stupid stuff + that you would never want to do in a production webserver. Caveat hackor! + + */ + +#include +#include +#include + +#include +#include + +#ifdef WIN32 +#include +#include +#include +#include +#include +#ifndef S_ISDIR +#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR) +#endif +#else +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef _EVENT_HAVE_NETINET_IN_H +#include +# ifdef _XOPEN_SOURCE_EXTENDED +# include +# endif +#endif + +/* Compatibility for possible missing IPv6 declarations */ +#include "../util-internal.h" + +#ifdef WIN32 +#define stat _stat +#define fstat _fstat +#define open _open +#define close _close +#define O_RDONLY _O_RDONLY +#endif + +char uri_root[512]; + +static const struct table_entry { + const char *extension; + const char *content_type; +} content_type_table[] = { + { "txt", "text/plain" }, + { "c", "text/plain" }, + { "h", "text/plain" }, + { "html", "text/html" }, + { "htm", "text/htm" }, + { "css", "text/css" }, + { "gif", "image/gif" }, + { "jpg", "image/jpeg" }, + { "jpeg", "image/jpeg" }, + { "png", "image/png" }, + { "pdf", "application/pdf" }, + { "ps", "application/postsript" }, + { NULL, NULL }, +}; + +/* Try to guess a good content-type for 'path' */ +static const char * +guess_content_type(const char *path) +{ + const char *last_period, *extension; + const struct table_entry *ent; + last_period = strrchr(path, '.'); + if (!last_period || strchr(last_period, '/')) + goto not_found; /* no exension */ + extension = last_period + 1; + for (ent = &content_type_table[0]; ent->extension; ++ent) { + if (!evutil_ascii_strcasecmp(ent->extension, extension)) + return ent->content_type; + } + +not_found: + return "application/misc"; +} + +/* Callback used for the /dump URI, and for every non-GET request: + * dumps all information to stdout and gives back a trivial 200 ok */ +static void +dump_request_cb(struct evhttp_request *req, void *arg) +{ + const char *cmdtype; + struct evkeyvalq *headers; + struct evkeyval *header; + struct evbuffer *buf; + + switch (evhttp_request_get_command(req)) { + case EVHTTP_REQ_GET: cmdtype = "GET"; break; + case EVHTTP_REQ_POST: cmdtype = "POST"; break; + case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break; + case EVHTTP_REQ_PUT: cmdtype = "PUT"; break; + case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break; + case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break; + case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break; + case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break; + case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break; + default: cmdtype = "unknown"; break; + } + + printf("Received a %s request for %s\nHeaders:\n", + cmdtype, evhttp_request_get_uri(req)); + + headers = evhttp_request_get_input_headers(req); + for (header = headers->tqh_first; header; + header = header->next.tqe_next) { + printf(" %s: %s\n", header->key, header->value); + } + + buf = evhttp_request_get_input_buffer(req); + puts("Input data: <<<"); + while (evbuffer_get_length(buf)) { + int n; + char cbuf[128]; + n = evbuffer_remove(buf, cbuf, sizeof(buf)-1); + if (n > 0) + (void) fwrite(cbuf, 1, n, stdout); + } + puts(">>>"); + + evhttp_send_reply(req, 200, "OK", NULL); +} + +/* This callback gets invoked when we get any http request that doesn't match + * any other callback. Like any evhttp server callback, it has a simple job: + * it must eventually call evhttp_send_error() or evhttp_send_reply(). + */ +static void +send_document_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *evb = NULL; + const char *docroot = arg; + const char *uri = evhttp_request_get_uri(req); + struct evhttp_uri *decoded = NULL; + const char *path; + char *decoded_path; + char *whole_path = NULL; + size_t len; + int fd = -1; + struct stat st; + + if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) { + dump_request_cb(req, arg); + return; + } + + printf("Got a GET request for <%s>\n", uri); + + /* Decode the URI */ + decoded = evhttp_uri_parse(uri); + if (!decoded) { + printf("It's not a good URI. Sending BADREQUEST\n"); + evhttp_send_error(req, HTTP_BADREQUEST, 0); + return; + } + + /* Let's see what path the user asked for. */ + path = evhttp_uri_get_path(decoded); + if (!path) path = "/"; + + /* We need to decode it, to see what path the user really wanted. */ + decoded_path = evhttp_uridecode(path, 0, NULL); + if (decoded_path == NULL) + goto err; + /* Don't allow any ".."s in the path, to avoid exposing stuff outside + * of the docroot. This test is both overzealous and underzealous: + * it forbids aceptable paths like "/this/one..here", but it doesn't + * do anything to prevent symlink following." */ + if (strstr(decoded_path, "..")) + goto err; + + len = strlen(decoded_path)+strlen(docroot)+2; + if (!(whole_path = malloc(len))) { + perror("malloc"); + goto err; + } + evutil_snprintf(whole_path, len, "%s/%s", docroot, decoded_path); + + if (stat(whole_path, &st)<0) { + goto err; + } + + /* This holds the content we're sending. */ + evb = evbuffer_new(); + + if (S_ISDIR(st.st_mode)) { + /* If it's a directory, read the comments and make a little + * index page */ +#ifdef WIN32 + HANDLE d; + WIN32_FIND_DATAA ent; + char *pattern; + size_t dirlen; +#else + DIR *d; + struct dirent *ent; +#endif + const char *trailing_slash = ""; + + if (!strlen(path) || path[strlen(path)-1] != '/') + trailing_slash = "/"; + +#ifdef WIN32 + dirlen = strlen(whole_path); + pattern = malloc(dirlen+3); + memcpy(pattern, whole_path, dirlen); + pattern[dirlen] = '\\'; + pattern[dirlen+1] = '*'; + pattern[dirlen+2] = '\0'; + d = FindFirstFileA(pattern, &ent); + free(pattern); + if (d == INVALID_HANDLE_VALUE) + goto err; +#else + if (!(d = opendir(whole_path))) + goto err; +#endif + + evbuffer_add_printf(evb, "\n \n" + " %s\n" + " \n" + " \n" + " \n" + "

%s

\n" + "
    \n", + decoded_path, /* XXX html-escape this. */ + uri_root, path, /* XXX html-escape this? */ + trailing_slash, + decoded_path /* XXX html-escape this */); +#ifdef WIN32 + do { + const char *name = ent.cFileName; +#else + while ((ent = readdir(d))) { + const char *name = ent->d_name; +#endif + evbuffer_add_printf(evb, + "
  • %s\n", + name, name);/* XXX escape this */ +#ifdef WIN32 + } while (FindNextFileA(d, &ent)); +#else + } +#endif + evbuffer_add_printf(evb, "
\n"); +#ifdef WIN32 + CloseHandle(d); +#else + closedir(d); +#endif + evhttp_add_header(evhttp_request_get_output_headers(req), + "Content-Type", "text/html"); + } else { + /* Otherwise it's a file; add it to the buffer to get + * sent via sendfile */ + const char *type = guess_content_type(decoded_path); + if ((fd = open(whole_path, O_RDONLY)) < 0) { + perror("open"); + goto err; + } + + if (fstat(fd, &st)<0) { + /* Make sure the length still matches, now that we + * opened the file :/ */ + perror("fstat"); + goto err; + } + evhttp_add_header(evhttp_request_get_output_headers(req), + "Content-Type", type); + evbuffer_add_file(evb, fd, 0, st.st_size); + } + + evhttp_send_reply(req, 200, "OK", evb); + goto done; +err: + evhttp_send_error(req, 404, "Document was not found"); + if (fd>=0) + close(fd); +done: + if (decoded) + evhttp_uri_free(decoded); + if (decoded_path) + free(decoded_path); + if (whole_path) + free(whole_path); + if (evb) + evbuffer_free(evb); +} + +static void +syntax(void) +{ + fprintf(stdout, "Syntax: http-server \n"); +} + +int +main(int argc, char **argv) +{ + struct event_base *base; + struct evhttp *http; + struct evhttp_bound_socket *handle; + + unsigned short port = 0; +#ifdef WIN32 + WSADATA WSAData; + WSAStartup(0x101, &WSAData); +#else + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + return (1); +#endif + if (argc < 2) { + syntax(); + return 1; + } + + base = event_base_new(); + if (!base) { + fprintf(stderr, "Couldn't create an event_base: exiting\n"); + return 1; + } + + /* Create a new evhttp object to handle requests. */ + http = evhttp_new(base); + if (!http) { + fprintf(stderr, "couldn't create evhttp. Exiting.\n"); + return 1; + } + + /* The /dump URI will dump all requests to stdout and say 200 ok. */ + evhttp_set_cb(http, "/dump", dump_request_cb, NULL); + + /* We want to accept arbitrary requests, so we need to set a "generic" + * cb. We can also add callbacks for specific paths. */ + evhttp_set_gencb(http, send_document_cb, argv[1]); + + /* Now we tell the evhttp what port to listen on */ + handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", port); + if (!handle) { + fprintf(stderr, "couldn't bind to port %d. Exiting.\n", + (int)port); + return 1; + } + + { + /* Extract and display the address we're listening on. */ + struct sockaddr_storage ss; + evutil_socket_t fd; + ev_socklen_t socklen = sizeof(ss); + char addrbuf[128]; + void *inaddr; + const char *addr; + int got_port = -1; + fd = evhttp_bound_socket_get_fd(handle); + memset(&ss, 0, sizeof(ss)); + if (getsockname(fd, (struct sockaddr *)&ss, &socklen)) { + perror("getsockname() failed"); + return 1; + } + if (ss.ss_family == AF_INET) { + got_port = ntohs(((struct sockaddr_in*)&ss)->sin_port); + inaddr = &((struct sockaddr_in*)&ss)->sin_addr; + } else if (ss.ss_family == AF_INET6) { + got_port = ntohs(((struct sockaddr_in6*)&ss)->sin6_port); + inaddr = &((struct sockaddr_in6*)&ss)->sin6_addr; + } else { + fprintf(stderr, "Weird address family %d\n", + ss.ss_family); + return 1; + } + addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf, + sizeof(addrbuf)); + if (addr) { + printf("Listening on %s:%d\n", addr, got_port); + evutil_snprintf(uri_root, sizeof(uri_root), + "http://%s:%d",addr,got_port); + } else { + fprintf(stderr, "evutil_inet_ntop failed\n"); + return 1; + } + } + + event_base_dispatch(base); + + return 0; +} diff --git a/libevent/sample/le-proxy.c b/libevent/sample/le-proxy.c new file mode 100644 index 0000000..446bfb5 --- /dev/null +++ b/libevent/sample/le-proxy.c @@ -0,0 +1,278 @@ +/* + This example code shows how to write an (optionally encrypting) SSL proxy + with Libevent's bufferevent layer. + + XXX It's a little ugly and should probably be cleaned up. + */ + +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct event_base *base; +static struct sockaddr_storage listen_on_addr; +static struct sockaddr_storage connect_to_addr; +static int connect_to_addrlen; +static int use_wrapper = 1; + +static SSL_CTX *ssl_ctx = NULL; + +#define MAX_OUTPUT (512*1024) + +static void drained_writecb(struct bufferevent *bev, void *ctx); +static void eventcb(struct bufferevent *bev, short what, void *ctx); + +static void +readcb(struct bufferevent *bev, void *ctx) +{ + struct bufferevent *partner = ctx; + struct evbuffer *src, *dst; + size_t len; + src = bufferevent_get_input(bev); + len = evbuffer_get_length(src); + if (!partner) { + evbuffer_drain(src, len); + return; + } + dst = bufferevent_get_output(partner); + evbuffer_add_buffer(dst, src); + + if (evbuffer_get_length(dst) >= MAX_OUTPUT) { + /* We're giving the other side data faster than it can + * pass it on. Stop reading here until we have drained the + * other side to MAX_OUTPUT/2 bytes. */ + bufferevent_setcb(partner, readcb, drained_writecb, + eventcb, bev); + bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2, + MAX_OUTPUT); + bufferevent_disable(bev, EV_READ); + } +} + +static void +drained_writecb(struct bufferevent *bev, void *ctx) +{ + struct bufferevent *partner = ctx; + + /* We were choking the other side until we drained our outbuf a bit. + * Now it seems drained. */ + bufferevent_setcb(bev, readcb, NULL, eventcb, partner); + bufferevent_setwatermark(bev, EV_WRITE, 0, 0); + if (partner) + bufferevent_enable(partner, EV_READ); +} + +static void +close_on_finished_writecb(struct bufferevent *bev, void *ctx) +{ + struct evbuffer *b = bufferevent_get_output(bev); + + if (evbuffer_get_length(b) == 0) { + bufferevent_free(bev); + } +} + +static void +eventcb(struct bufferevent *bev, short what, void *ctx) +{ + struct bufferevent *partner = ctx; + + if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) { + if (what & BEV_EVENT_ERROR) { + unsigned long err; + while ((err = (bufferevent_get_openssl_error(bev)))) { + const char *msg = (const char*) + ERR_reason_error_string(err); + const char *lib = (const char*) + ERR_lib_error_string(err); + const char *func = (const char*) + ERR_func_error_string(err); + fprintf(stderr, + "%s in %s %s\n", msg, lib, func); + } + if (errno) + perror("connection error"); + } + + if (partner) { + /* Flush all pending data */ + readcb(bev, ctx); + + if (evbuffer_get_length( + bufferevent_get_output(partner))) { + /* We still have to flush data from the other + * side, but when that's done, close the other + * side. */ + bufferevent_setcb(partner, + NULL, close_on_finished_writecb, + eventcb, NULL); + bufferevent_disable(partner, EV_READ); + } else { + /* We have nothing left to say to the other + * side; close it. */ + bufferevent_free(partner); + } + } + bufferevent_free(bev); + } +} + +static void +syntax(void) +{ + fputs("Syntax:\n", stderr); + fputs(" le-proxy [-s] [-W] \n", stderr); + fputs("Example:\n", stderr); + fputs(" le-proxy 127.0.0.1:8888 1.2.3.4:80\n", stderr); + + exit(1); +} + +static void +accept_cb(struct evconnlistener *listener, evutil_socket_t fd, + struct sockaddr *a, int slen, void *p) +{ + struct bufferevent *b_out, *b_in; + /* Create two linked bufferevent objects: one to connect, one for the + * new connection */ + b_in = bufferevent_socket_new(base, fd, + BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); + + if (!ssl_ctx || use_wrapper) + b_out = bufferevent_socket_new(base, -1, + BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); + else { + SSL *ssl = SSL_new(ssl_ctx); + b_out = bufferevent_openssl_socket_new(base, -1, ssl, + BUFFEREVENT_SSL_CONNECTING, + BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); + } + + assert(b_in && b_out); + + if (bufferevent_socket_connect(b_out, + (struct sockaddr*)&connect_to_addr, connect_to_addrlen)<0) { + perror("bufferevent_socket_connect"); + bufferevent_free(b_out); + bufferevent_free(b_in); + return; + } + + if (ssl_ctx && use_wrapper) { + struct bufferevent *b_ssl; + SSL *ssl = SSL_new(ssl_ctx); + b_ssl = bufferevent_openssl_filter_new(base, + b_out, ssl, BUFFEREVENT_SSL_CONNECTING, + BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); + if (!b_ssl) { + perror("Bufferevent_openssl_new"); + bufferevent_free(b_out); + bufferevent_free(b_in); + } + b_out = b_ssl; + } + + bufferevent_setcb(b_in, readcb, NULL, eventcb, b_out); + bufferevent_setcb(b_out, readcb, NULL, eventcb, b_in); + + bufferevent_enable(b_in, EV_READ|EV_WRITE); + bufferevent_enable(b_out, EV_READ|EV_WRITE); +} + +int +main(int argc, char **argv) +{ + int i; + int socklen; + + int use_ssl = 0; + struct evconnlistener *listener; + + if (argc < 3) + syntax(); + + for (i=1; i < argc; ++i) { + if (!strcmp(argv[i], "-s")) { + use_ssl = 1; + } else if (!strcmp(argv[i], "-W")) { + use_wrapper = 0; + } else if (argv[i][0] == '-') { + syntax(); + } else + break; + } + + if (i+2 != argc) + syntax(); + + memset(&listen_on_addr, 0, sizeof(listen_on_addr)); + socklen = sizeof(listen_on_addr); + if (evutil_parse_sockaddr_port(argv[i], + (struct sockaddr*)&listen_on_addr, &socklen)<0) { + int p = atoi(argv[i]); + struct sockaddr_in *sin = (struct sockaddr_in*)&listen_on_addr; + if (p < 1 || p > 65535) + syntax(); + sin->sin_port = htons(p); + sin->sin_addr.s_addr = htonl(0x7f000001); + sin->sin_family = AF_INET; + socklen = sizeof(struct sockaddr_in); + } + + memset(&connect_to_addr, 0, sizeof(connect_to_addr)); + connect_to_addrlen = sizeof(connect_to_addr); + if (evutil_parse_sockaddr_port(argv[i+1], + (struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) + syntax(); + + base = event_base_new(); + if (!base) { + perror("event_base_new()"); + return 1; + } + + if (use_ssl) { + int r; + SSL_library_init(); + ERR_load_crypto_strings(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + r = RAND_poll(); + if (r == 0) { + fprintf(stderr, "RAND_poll() failed.\n"); + return 1; + } + ssl_ctx = SSL_CTX_new(SSLv23_method()); + } + + listener = evconnlistener_new_bind(base, accept_cb, NULL, + LEV_OPT_CLOSE_ON_FREE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_REUSEABLE, + -1, (struct sockaddr*)&listen_on_addr, socklen); + + event_base_dispatch(base); + + evconnlistener_free(listener); + event_base_free(base); + + return 0; +} diff --git a/libevent/sample/signal-test.c b/libevent/sample/signal-test.c new file mode 100644 index 0000000..53c025f --- /dev/null +++ b/libevent/sample/signal-test.c @@ -0,0 +1,77 @@ +/* + * Compile with: + * cc -I/usr/local/include -o signal-test \ + * signal-test.c -L/usr/local/lib -levent + */ + +#include + +#include + +#include +#ifndef WIN32 +#include +#include +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include + +#ifdef _EVENT___func__ +#define __func__ _EVENT___func__ +#endif + +int called = 0; + +static void +signal_cb(evutil_socket_t fd, short event, void *arg) +{ + struct event *signal = arg; + + printf("%s: got signal %d\n", __func__, EVENT_SIGNAL(signal)); + + if (called >= 2) + event_del(signal); + + called++; +} + +int +main(int argc, char **argv) +{ + struct event signal_int; + struct event_base* base; +#ifdef WIN32 + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); +#endif + + /* Initalize the event library */ + base = event_base_new(); + + /* Initalize one event */ + event_assign(&signal_int, base, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, + &signal_int); + + event_add(&signal_int, NULL); + + event_base_dispatch(base); + event_base_free(base); + + return (0); +} + diff --git a/libevent/sample/time-test.c b/libevent/sample/time-test.c new file mode 100644 index 0000000..61b4a6c --- /dev/null +++ b/libevent/sample/time-test.c @@ -0,0 +1,108 @@ +/* + * XXX This sample code was once meant to show how to use the basic Libevent + * interfaces, but it never worked on non-Unix platforms, and some of the + * interfaces have changed since it was first written. It should probably + * be removed or replaced with something better. + * + * Compile with: + * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent + */ + +#include + +#include + +#include +#ifndef WIN32 +#include +#include +#endif +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef WIN32 +#include +#endif + +struct timeval lasttime; + +int event_is_persistent; + +static void +timeout_cb(evutil_socket_t fd, short event, void *arg) +{ + struct timeval newtime, difference; + struct event *timeout = arg; + double elapsed; + + evutil_gettimeofday(&newtime, NULL); + evutil_timersub(&newtime, &lasttime, &difference); + elapsed = difference.tv_sec + + (difference.tv_usec / 1.0e6); + + printf("timeout_cb called at %d: %.3f seconds elapsed.\n", + (int)newtime.tv_sec, elapsed); + lasttime = newtime; + + if (! event_is_persistent) { + struct timeval tv; + evutil_timerclear(&tv); + tv.tv_sec = 2; + event_add(timeout, &tv); + } +} + +int +main(int argc, char **argv) +{ + struct event timeout; + struct timeval tv; + struct event_base *base; + int flags; + +#ifdef WIN32 + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); +#endif + + if (argc == 2 && !strcmp(argv[1], "-p")) { + event_is_persistent = 1; + flags = EV_PERSIST; + } else { + event_is_persistent = 0; + flags = 0; + } + + /* Initalize the event library */ + base = event_base_new(); + + /* Initalize one event */ + event_assign(&timeout, base, -1, flags, timeout_cb, (void*) &timeout); + + evutil_timerclear(&tv); + tv.tv_sec = 2; + event_add(&timeout, &tv); + + evutil_gettimeofday(&lasttime, NULL); + + event_base_dispatch(base); + + return (0); +} + diff --git a/libevent/select.c b/libevent/select.c new file mode 100644 index 0000000..afba6d3 --- /dev/null +++ b/libevent/select.c @@ -0,0 +1,333 @@ +/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ + +/* + * Copyright 2000-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#ifdef _EVENT_HAVE_SYS_SELECT_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "event-internal.h" +#include "evsignal-internal.h" +#include "event2/thread.h" +#include "evthread-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" + +#ifndef _EVENT_HAVE_FD_MASK +/* This type is mandatory, but Android doesn't define it. */ +typedef unsigned long fd_mask; +#endif + +#ifndef NFDBITS +#define NFDBITS (sizeof(fd_mask)*8) +#endif + +/* Divide positive x by y, rounding up. */ +#define DIV_ROUNDUP(x, y) (((x)+((y)-1))/(y)) + +/* How many bytes to allocate for N fds? */ +#define SELECT_ALLOC_SIZE(n) \ + (DIV_ROUNDUP(n, NFDBITS) * sizeof(fd_mask)) + +struct selectop { + int event_fds; /* Highest fd in fd set */ + int event_fdsz; + int resize_out_sets; + fd_set *event_readset_in; + fd_set *event_writeset_in; + fd_set *event_readset_out; + fd_set *event_writeset_out; +}; + +static void *select_init(struct event_base *); +static int select_add(struct event_base *, int, short old, short events, void*); +static int select_del(struct event_base *, int, short old, short events, void*); +static int select_dispatch(struct event_base *, struct timeval *); +static void select_dealloc(struct event_base *); + +const struct eventop selectops = { + "select", + select_init, + select_add, + select_del, + select_dispatch, + select_dealloc, + 0, /* doesn't need reinit. */ + EV_FEATURE_FDS, + 0, +}; + +static int select_resize(struct selectop *sop, int fdsz); +static void select_free_selectop(struct selectop *sop); + +static void * +select_init(struct event_base *base) +{ + struct selectop *sop; + + if (!(sop = mm_calloc(1, sizeof(struct selectop)))) + return (NULL); + + if (select_resize(sop, SELECT_ALLOC_SIZE(32 + 1))) { + select_free_selectop(sop); + return (NULL); + } + + evsig_init(base); + + return (sop); +} + +#ifdef CHECK_INVARIANTS +static void +check_selectop(struct selectop *sop) +{ + /* nothing to be done here */ +} +#else +#define check_selectop(sop) do { (void) sop; } while (0) +#endif + +static int +select_dispatch(struct event_base *base, struct timeval *tv) +{ + int res=0, i, j, nfds; + struct selectop *sop = base->evbase; + + check_selectop(sop); + if (sop->resize_out_sets) { + fd_set *readset_out=NULL, *writeset_out=NULL; + size_t sz = sop->event_fdsz; + if (!(readset_out = mm_realloc(sop->event_readset_out, sz))) + return (-1); + sop->event_readset_out = readset_out; + if (!(writeset_out = mm_realloc(sop->event_writeset_out, sz))) { + /* We don't free readset_out here, since it was + * already successfully reallocated. The next time + * we call select_dispatch, the realloc will be a + * no-op. */ + return (-1); + } + sop->event_writeset_out = writeset_out; + sop->resize_out_sets = 0; + } + + memcpy(sop->event_readset_out, sop->event_readset_in, + sop->event_fdsz); + memcpy(sop->event_writeset_out, sop->event_writeset_in, + sop->event_fdsz); + + nfds = sop->event_fds+1; + + EVBASE_RELEASE_LOCK(base, th_base_lock); + + res = select(nfds, sop->event_readset_out, + sop->event_writeset_out, NULL, tv); + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + + check_selectop(sop); + + if (res == -1) { + if (errno != EINTR) { + event_warn("select"); + return (-1); + } + + return (0); + } + + event_debug(("%s: select reports %d", __func__, res)); + + check_selectop(sop); + i = random() % nfds; + for (j = 0; j < nfds; ++j) { + if (++i >= nfds) + i = 0; + res = 0; + if (FD_ISSET(i, sop->event_readset_out)) + res |= EV_READ; + if (FD_ISSET(i, sop->event_writeset_out)) + res |= EV_WRITE; + + if (res == 0) + continue; + + evmap_io_active(base, i, res); + } + check_selectop(sop); + + return (0); +} + +static int +select_resize(struct selectop *sop, int fdsz) +{ + fd_set *readset_in = NULL; + fd_set *writeset_in = NULL; + + if (sop->event_readset_in) + check_selectop(sop); + + if ((readset_in = mm_realloc(sop->event_readset_in, fdsz)) == NULL) + goto error; + sop->event_readset_in = readset_in; + if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL) { + /* Note that this will leave event_readset_in expanded. + * That's okay; we wouldn't want to free it, since that would + * change the semantics of select_resize from "expand the + * readset_in and writeset_in, or return -1" to "expand the + * *set_in members, or trash them and return -1." + */ + goto error; + } + sop->event_writeset_in = writeset_in; + sop->resize_out_sets = 1; + + memset((char *)sop->event_readset_in + sop->event_fdsz, 0, + fdsz - sop->event_fdsz); + memset((char *)sop->event_writeset_in + sop->event_fdsz, 0, + fdsz - sop->event_fdsz); + + sop->event_fdsz = fdsz; + check_selectop(sop); + + return (0); + + error: + event_warn("malloc"); + return (-1); +} + + +static int +select_add(struct event_base *base, int fd, short old, short events, void *p) +{ + struct selectop *sop = base->evbase; + (void) p; + + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); + check_selectop(sop); + /* + * Keep track of the highest fd, so that we can calculate the size + * of the fd_sets for select(2) + */ + if (sop->event_fds < fd) { + int fdsz = sop->event_fdsz; + + if (fdsz < (int)sizeof(fd_mask)) + fdsz = (int)sizeof(fd_mask); + + /* In theory we should worry about overflow here. In + * reality, though, the highest fd on a unixy system will + * not overflow here. XXXX */ + while (fdsz < (int) SELECT_ALLOC_SIZE(fd + 1)) + fdsz *= 2; + + if (fdsz != sop->event_fdsz) { + if (select_resize(sop, fdsz)) { + check_selectop(sop); + return (-1); + } + } + + sop->event_fds = fd; + } + + if (events & EV_READ) + FD_SET(fd, sop->event_readset_in); + if (events & EV_WRITE) + FD_SET(fd, sop->event_writeset_in); + check_selectop(sop); + + return (0); +} + +/* + * Nothing to be done here. + */ + +static int +select_del(struct event_base *base, int fd, short old, short events, void *p) +{ + struct selectop *sop = base->evbase; + (void)p; + + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); + check_selectop(sop); + + if (sop->event_fds < fd) { + check_selectop(sop); + return (0); + } + + if (events & EV_READ) + FD_CLR(fd, sop->event_readset_in); + + if (events & EV_WRITE) + FD_CLR(fd, sop->event_writeset_in); + + check_selectop(sop); + return (0); +} + +static void +select_free_selectop(struct selectop *sop) +{ + if (sop->event_readset_in) + mm_free(sop->event_readset_in); + if (sop->event_writeset_in) + mm_free(sop->event_writeset_in); + if (sop->event_readset_out) + mm_free(sop->event_readset_out); + if (sop->event_writeset_out) + mm_free(sop->event_writeset_out); + + memset(sop, 0, sizeof(struct selectop)); + mm_free(sop); +} + +static void +select_dealloc(struct event_base *base) +{ + evsig_dealloc(base); + + select_free_selectop(base->evbase); +} diff --git a/libevent/signal.c b/libevent/signal.c new file mode 100644 index 0000000..d40da0e --- /dev/null +++ b/libevent/signal.c @@ -0,0 +1,444 @@ +/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ + +/* + * Copyright 2000-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "event2/event-config.h" + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#undef WIN32_LEAN_AND_MEAN +#endif +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#include +#include +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#include +#ifdef _EVENT_HAVE_FCNTL_H +#include +#endif + +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event-internal.h" +#include "event2/util.h" +#include "evsignal-internal.h" +#include "log-internal.h" +#include "evmap-internal.h" +#include "evthread-internal.h" + +/* + signal.c + + This is the signal-handling implementation we use for backends that don't + have a better way to do signal handling. It uses sigaction() or signal() + to set a signal handler, and a socket pair to tell the event base when + + Note that I said "the event base" : only one event base can be set up to use + this at a time. For historical reasons and backward compatibility, if you + add an event for a signal to event_base A, then add an event for a signal + (any signal!) to event_base B, event_base B will get informed about the + signal, but event_base A won't. + + It would be neat to change this behavior in some future version of Libevent. + kqueue already does something far more sensible. We can make all backends + on Linux do a reasonable thing using signalfd. +*/ + +#ifndef WIN32 +/* Windows wants us to call our signal handlers as __cdecl. Nobody else + * expects you to do anything crazy like this. */ +#define __cdecl +#endif + +static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *); +static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *); + +static const struct eventop evsigops = { + "signal", + NULL, + evsig_add, + evsig_del, + NULL, + NULL, + 0, 0, 0 +}; + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT +/* Lock for evsig_base and evsig_base_n_signals_added fields. */ +static void *evsig_base_lock = NULL; +#endif +/* The event base that's currently getting informed about signals. */ +static struct event_base *evsig_base = NULL; +/* A copy of evsig_base->sigev_n_signals_added. */ +static int evsig_base_n_signals_added = 0; +static evutil_socket_t evsig_base_fd = -1; + +static void __cdecl evsig_handler(int sig); + +#define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0) +#define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0) + +void +evsig_set_base(struct event_base *base) +{ + EVSIGBASE_LOCK(); + evsig_base = base; + evsig_base_n_signals_added = base->sig.ev_n_signals_added; + evsig_base_fd = base->sig.ev_signal_pair[0]; + EVSIGBASE_UNLOCK(); +} + +/* Callback for when the signal handler write a byte to our signaling socket */ +static void +evsig_cb(evutil_socket_t fd, short what, void *arg) +{ + static char signals[1024]; + ev_ssize_t n; + int i; + int ncaught[NSIG]; + struct event_base *base; + + base = arg; + + memset(&ncaught, 0, sizeof(ncaught)); + + while (1) { + n = recv(fd, signals, sizeof(signals), 0); + if (n == -1) { + int err = evutil_socket_geterror(fd); + if (! EVUTIL_ERR_RW_RETRIABLE(err)) + event_sock_err(1, fd, "%s: recv", __func__); + break; + } else if (n == 0) { + /* XXX warn? */ + break; + } + for (i = 0; i < n; ++i) { + ev_uint8_t sig = signals[i]; + if (sig < NSIG) + ncaught[sig]++; + } + } + + EVBASE_ACQUIRE_LOCK(base, th_base_lock); + for (i = 0; i < NSIG; ++i) { + if (ncaught[i]) + evmap_signal_active(base, i, ncaught[i]); + } + EVBASE_RELEASE_LOCK(base, th_base_lock); +} + +int +evsig_init(struct event_base *base) +{ + /* + * Our signal handler is going to write to one end of the socket + * pair to wake up our event loop. The event loop then scans for + * signals that got delivered. + */ + if (evutil_socketpair( + AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) { +#ifdef WIN32 + /* Make this nonfatal on win32, where sometimes people + have localhost firewalled. */ + event_sock_warn(-1, "%s: socketpair", __func__); +#else + event_sock_err(1, -1, "%s: socketpair", __func__); +#endif + return -1; + } + + evutil_make_socket_closeonexec(base->sig.ev_signal_pair[0]); + evutil_make_socket_closeonexec(base->sig.ev_signal_pair[1]); + base->sig.sh_old = NULL; + base->sig.sh_old_max = 0; + + evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]); + evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]); + + event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1], + EV_READ | EV_PERSIST, evsig_cb, base); + + base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; + event_priority_set(&base->sig.ev_signal, 0); + + base->evsigsel = &evsigops; + + return 0; +} + +/* Helper: set the signal handler for evsignal to handler in base, so that + * we can restore the original handler when we clear the current one. */ +int +_evsig_set_handler(struct event_base *base, + int evsignal, void (__cdecl *handler)(int)) +{ +#ifdef _EVENT_HAVE_SIGACTION + struct sigaction sa; +#else + ev_sighandler_t sh; +#endif + struct evsig_info *sig = &base->sig; + void *p; + + /* + * resize saved signal handler array up to the highest signal number. + * a dynamic array is used to keep footprint on the low side. + */ + if (evsignal >= sig->sh_old_max) { + int new_max = evsignal + 1; + event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing", + __func__, evsignal, sig->sh_old_max)); + p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old)); + if (p == NULL) { + event_warn("realloc"); + return (-1); + } + + memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old), + 0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old)); + + sig->sh_old_max = new_max; + sig->sh_old = p; + } + + /* allocate space for previous handler out of dynamic array */ + sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]); + if (sig->sh_old[evsignal] == NULL) { + event_warn("malloc"); + return (-1); + } + + /* save previous handler and setup new handler */ +#ifdef _EVENT_HAVE_SIGACTION + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handler; + sa.sa_flags |= SA_RESTART; + sigfillset(&sa.sa_mask); + + if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) { + event_warn("sigaction"); + mm_free(sig->sh_old[evsignal]); + sig->sh_old[evsignal] = NULL; + return (-1); + } +#else + if ((sh = signal(evsignal, handler)) == SIG_ERR) { + event_warn("signal"); + mm_free(sig->sh_old[evsignal]); + sig->sh_old[evsignal] = NULL; + return (-1); + } + *sig->sh_old[evsignal] = sh; +#endif + + return (0); +} + +static int +evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) +{ + struct evsig_info *sig = &base->sig; + (void)p; + + EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); + + /* catch signals if they happen quickly */ + EVSIGBASE_LOCK(); + if (evsig_base != base && evsig_base_n_signals_added) { + event_warnx("Added a signal to event base %p with signals " + "already added to event_base %p. Only one can have " + "signals at a time with the %s backend. The base with " + "the most recently added signal or the most recent " + "event_base_loop() call gets preference; do " + "not rely on this behavior in future Libevent versions.", + base, evsig_base, base->evsel->name); + } + evsig_base = base; + evsig_base_n_signals_added = ++sig->ev_n_signals_added; + evsig_base_fd = base->sig.ev_signal_pair[0]; + EVSIGBASE_UNLOCK(); + + event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal)); + if (_evsig_set_handler(base, (int)evsignal, evsig_handler) == -1) { + goto err; + } + + + if (!sig->ev_signal_added) { + if (event_add(&sig->ev_signal, NULL)) + goto err; + sig->ev_signal_added = 1; + } + + return (0); + +err: + EVSIGBASE_LOCK(); + --evsig_base_n_signals_added; + --sig->ev_n_signals_added; + EVSIGBASE_UNLOCK(); + return (-1); +} + +int +_evsig_restore_handler(struct event_base *base, int evsignal) +{ + int ret = 0; + struct evsig_info *sig = &base->sig; +#ifdef _EVENT_HAVE_SIGACTION + struct sigaction *sh; +#else + ev_sighandler_t *sh; +#endif + + /* restore previous handler */ + sh = sig->sh_old[evsignal]; + sig->sh_old[evsignal] = NULL; +#ifdef _EVENT_HAVE_SIGACTION + if (sigaction(evsignal, sh, NULL) == -1) { + event_warn("sigaction"); + ret = -1; + } +#else + if (signal(evsignal, *sh) == SIG_ERR) { + event_warn("signal"); + ret = -1; + } +#endif + + mm_free(sh); + + return ret; +} + +static int +evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) +{ + EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); + + event_debug(("%s: %d: restoring signal handler", __func__, evsignal)); + + EVSIGBASE_LOCK(); + --evsig_base_n_signals_added; + --base->sig.ev_n_signals_added; + EVSIGBASE_UNLOCK(); + + return (_evsig_restore_handler(base, (int)evsignal)); +} + +static void __cdecl +evsig_handler(int sig) +{ + int save_errno = errno; +#ifdef WIN32 + int socket_errno = EVUTIL_SOCKET_ERROR(); +#endif + ev_uint8_t msg; + + if (evsig_base == NULL) { + event_warnx( + "%s: received signal %d, but have no base configured", + __func__, sig); + return; + } + +#ifndef _EVENT_HAVE_SIGACTION + signal(sig, evsig_handler); +#endif + + /* Wake up our notification mechanism */ + msg = sig; + send(evsig_base_fd, (char*)&msg, 1, 0); + errno = save_errno; +#ifdef WIN32 + EVUTIL_SET_SOCKET_ERROR(socket_errno); +#endif +} + +void +evsig_dealloc(struct event_base *base) +{ + int i = 0; + if (base->sig.ev_signal_added) { + event_del(&base->sig.ev_signal); + base->sig.ev_signal_added = 0; + } + /* debug event is created in evsig_init/event_assign even when + * ev_signal_added == 0, so unassign is required */ + event_debug_unassign(&base->sig.ev_signal); + + for (i = 0; i < NSIG; ++i) { + if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL) + _evsig_restore_handler(base, i); + } + EVSIGBASE_LOCK(); + if (base == evsig_base) { + evsig_base = NULL; + evsig_base_n_signals_added = 0; + evsig_base_fd = -1; + } + EVSIGBASE_UNLOCK(); + + if (base->sig.ev_signal_pair[0] != -1) { + evutil_closesocket(base->sig.ev_signal_pair[0]); + base->sig.ev_signal_pair[0] = -1; + } + if (base->sig.ev_signal_pair[1] != -1) { + evutil_closesocket(base->sig.ev_signal_pair[1]); + base->sig.ev_signal_pair[1] = -1; + } + base->sig.sh_old_max = 0; + + /* per index frees are handled in evsig_del() */ + if (base->sig.sh_old) { + mm_free(base->sig.sh_old); + base->sig.sh_old = NULL; + } +} + +#ifndef _EVENT_DISABLE_THREAD_SUPPORT +int +evsig_global_setup_locks_(const int enable_locks) +{ + EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0); + return 0; +} +#endif diff --git a/libevent/strlcpy-internal.h b/libevent/strlcpy-internal.h new file mode 100644 index 0000000..1968c00 --- /dev/null +++ b/libevent/strlcpy-internal.h @@ -0,0 +1,21 @@ +#ifndef _STRLCPY_INTERNAL_H_ +#define _STRLCPY_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event2/event-config.h" + +#ifndef _EVENT_HAVE_STRLCPY +#include +size_t _event_strlcpy(char *dst, const char *src, size_t siz); +#define strlcpy _event_strlcpy +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/libevent/strlcpy.c b/libevent/strlcpy.c new file mode 100644 index 0000000..11053c3 --- /dev/null +++ b/libevent/strlcpy.c @@ -0,0 +1,74 @@ +/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * 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. 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 ``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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include "event2/event-config.h" + +#ifndef _EVENT_HAVE_STRLCPY +#include "strlcpy-internal.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +_event_strlcpy(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return (s - src - 1); /* count does not include NUL */ +} +#endif diff --git a/libevent/test/Makefile.am b/libevent/test/Makefile.am new file mode 100644 index 0000000..5904b64 --- /dev/null +++ b/libevent/test/Makefile.am @@ -0,0 +1,98 @@ +# test/Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + +AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include -DTINYTEST_LOCAL + +EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c rpcgen_wrapper.sh test.sh + +noinst_PROGRAMS = test-init test-eof test-weof test-time \ + bench bench_cascade bench_http bench_httpclient test-ratelim \ + test-changelist +if BUILD_REGRESS +noinst_PROGRAMS += regress +endif +EXTRA_PROGRAMS = regress +noinst_HEADERS = tinytest.h tinytest_macros.h regress.h tinytest_local.h + +# TESTS = $(top_srcdir)/test/test.sh + +BUILT_SOURCES = +if BUILD_REGRESS +BUILT_SOURCES += regress.gen.c regress.gen.h +endif + +test_init_SOURCES = test-init.c +test_init_LDADD = ../libevent_core.la +test_eof_SOURCES = test-eof.c +test_eof_LDADD = ../libevent_core.la +test_changelist_SOURCES = test-changelist.c +test_changelist_LDADD = ../libevent_core.la +test_weof_SOURCES = test-weof.c +test_weof_LDADD = ../libevent_core.la +test_time_SOURCES = test-time.c +test_time_LDADD = ../libevent_core.la +test_ratelim_SOURCES = test-ratelim.c +test_ratelim_LDADD = ../libevent_core.la -lm + +regress_SOURCES = regress.c regress_buffer.c regress_http.c regress_dns.c \ + regress_testutils.c regress_testutils.h \ + regress_rpc.c regress.gen.c regress.gen.h regress_et.c \ + regress_bufferevent.c regress_listener.c \ + regress_util.c tinytest.c regress_main.c regress_minheap.c \ + $(regress_thread_SOURCES) $(regress_zlib_SOURCES) +if PTHREADS +regress_thread_SOURCES = regress_thread.c +PTHREAD_LIBS += ../libevent_pthreads.la +endif +if BUILD_WIN32 +regress_thread_SOURCES = regress_thread.c +endif +if ZLIB_REGRESS +regress_zlib_SOURCES = regress_zlib.c +endif +if BUILD_WIN32 +regress_SOURCES += regress_iocp.c +endif + +regress_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la $(PTHREAD_LIBS) $(ZLIB_LIBS) +regress_CPPFLAGS = $(AM_CPPFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) +regress_LDFLAGS = $(PTHREAD_CFLAGS) + +if OPENSSL +regress_SOURCES += regress_ssl.c +regress_LDADD += ../libevent_openssl.la -lssl -lcrypto ${OPENSSL_LIBADD} +endif + +bench_SOURCES = bench.c +bench_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +bench_cascade_SOURCES = bench_cascade.c +bench_cascade_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +bench_http_SOURCES = bench_http.c +bench_http_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +bench_httpclient_SOURCES = bench_httpclient.c +bench_httpclient_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent_core.la + +regress.gen.c regress.gen.h: rpcgen-attempted + +rpcgen-attempted: $(srcdir)/regress.rpc $(srcdir)/../event_rpcgen.py $(srcdir)/rpcgen_wrapper.sh + date -u > $@ + if $(srcdir)/rpcgen_wrapper.sh $(srcdir); then \ + echo "rpcgen okay"; \ + else \ + echo "No Python installed; stubbing out RPC test." >&2; \ + echo " "> regress.gen.c; \ + echo "#define NO_PYTHON_EXISTS" > regress.gen.h; \ + fi + +CLEANFILES = rpcgen-attempted + +DISTCLEANFILES = *~ + +verify: check + +bench test-init test-eof test-weof test-time test-changelist: ../libevent.la diff --git a/libevent/test/Makefile.in b/libevent/test/Makefile.in new file mode 100644 index 0000000..2588c0c --- /dev/null +++ b/libevent/test/Makefile.in @@ -0,0 +1,1012 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# test/Makefile.am for libevent +# Copyright 2000-2007 Niels Provos +# Copyright 2007-2012 Niels Provos and Nick Mathewson +# +# See LICENSE for copying information. + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-init$(EXEEXT) test-eof$(EXEEXT) \ + test-weof$(EXEEXT) test-time$(EXEEXT) bench$(EXEEXT) \ + bench_cascade$(EXEEXT) bench_http$(EXEEXT) \ + bench_httpclient$(EXEEXT) test-ratelim$(EXEEXT) \ + test-changelist$(EXEEXT) $(am__EXEEXT_1) +@BUILD_REGRESS_TRUE@am__append_1 = regress +EXTRA_PROGRAMS = regress$(EXEEXT) +@BUILD_REGRESS_TRUE@am__append_2 = regress.gen.c regress.gen.h +@PTHREADS_TRUE@am__append_3 = ../libevent_pthreads.la +@BUILD_WIN32_TRUE@am__append_4 = regress_iocp.c +@OPENSSL_TRUE@am__append_5 = regress_ssl.c +@OPENSSL_TRUE@am__append_6 = ../libevent_openssl.la -lssl -lcrypto ${OPENSSL_LIBADD} +subdir = test +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/../depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@BUILD_REGRESS_TRUE@am__EXEEXT_1 = regress$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_bench_OBJECTS = bench.$(OBJEXT) +bench_OBJECTS = $(am_bench_OBJECTS) +am__DEPENDENCIES_1 = +bench_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_bench_cascade_OBJECTS = bench_cascade.$(OBJEXT) +bench_cascade_OBJECTS = $(am_bench_cascade_OBJECTS) +bench_cascade_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +am_bench_http_OBJECTS = bench_http.$(OBJEXT) +bench_http_OBJECTS = $(am_bench_http_OBJECTS) +bench_http_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la +am_bench_httpclient_OBJECTS = bench_httpclient.$(OBJEXT) +bench_httpclient_OBJECTS = $(am_bench_httpclient_OBJECTS) +bench_httpclient_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + ../libevent_core.la +am__regress_SOURCES_DIST = regress.c regress_buffer.c regress_http.c \ + regress_dns.c regress_testutils.c regress_testutils.h \ + regress_rpc.c regress.gen.c regress.gen.h regress_et.c \ + regress_bufferevent.c regress_listener.c regress_util.c \ + tinytest.c regress_main.c regress_minheap.c regress_thread.c \ + regress_zlib.c regress_iocp.c regress_ssl.c +@BUILD_WIN32_FALSE@@PTHREADS_TRUE@am__objects_1 = regress-regress_thread.$(OBJEXT) +@BUILD_WIN32_TRUE@am__objects_1 = regress-regress_thread.$(OBJEXT) +@ZLIB_REGRESS_TRUE@am__objects_2 = regress-regress_zlib.$(OBJEXT) +@BUILD_WIN32_TRUE@am__objects_3 = regress-regress_iocp.$(OBJEXT) +@OPENSSL_TRUE@am__objects_4 = regress-regress_ssl.$(OBJEXT) +am_regress_OBJECTS = regress-regress.$(OBJEXT) \ + regress-regress_buffer.$(OBJEXT) \ + regress-regress_http.$(OBJEXT) regress-regress_dns.$(OBJEXT) \ + regress-regress_testutils.$(OBJEXT) \ + regress-regress_rpc.$(OBJEXT) regress-regress.gen.$(OBJEXT) \ + regress-regress_et.$(OBJEXT) \ + regress-regress_bufferevent.$(OBJEXT) \ + regress-regress_listener.$(OBJEXT) \ + regress-regress_util.$(OBJEXT) regress-tinytest.$(OBJEXT) \ + regress-regress_main.$(OBJEXT) \ + regress-regress_minheap.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) +regress_OBJECTS = $(am_regress_OBJECTS) +am__DEPENDENCIES_2 = $(am__append_3) +@OPENSSL_TRUE@am__DEPENDENCIES_3 = ../libevent_openssl.la \ +@OPENSSL_TRUE@ $(am__DEPENDENCIES_1) +regress_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libevent.la \ + $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_3) +regress_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(regress_LDFLAGS) $(LDFLAGS) -o $@ +am_test_changelist_OBJECTS = test-changelist.$(OBJEXT) +test_changelist_OBJECTS = $(am_test_changelist_OBJECTS) +test_changelist_DEPENDENCIES = ../libevent_core.la +am_test_eof_OBJECTS = test-eof.$(OBJEXT) +test_eof_OBJECTS = $(am_test_eof_OBJECTS) +test_eof_DEPENDENCIES = ../libevent_core.la +am_test_init_OBJECTS = test-init.$(OBJEXT) +test_init_OBJECTS = $(am_test_init_OBJECTS) +test_init_DEPENDENCIES = ../libevent_core.la +am_test_ratelim_OBJECTS = test-ratelim.$(OBJEXT) +test_ratelim_OBJECTS = $(am_test_ratelim_OBJECTS) +test_ratelim_DEPENDENCIES = ../libevent_core.la +am_test_time_OBJECTS = test-time.$(OBJEXT) +test_time_OBJECTS = $(am_test_time_OBJECTS) +test_time_DEPENDENCIES = ../libevent_core.la +am_test_weof_OBJECTS = test-weof.$(OBJEXT) +test_weof_OBJECTS = $(am_test_weof_OBJECTS) +test_weof_DEPENDENCIES = ../libevent_core.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/../depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(bench_SOURCES) $(bench_cascade_SOURCES) \ + $(bench_http_SOURCES) $(bench_httpclient_SOURCES) \ + $(regress_SOURCES) $(test_changelist_SOURCES) \ + $(test_eof_SOURCES) $(test_init_SOURCES) \ + $(test_ratelim_SOURCES) $(test_time_SOURCES) \ + $(test_weof_SOURCES) +DIST_SOURCES = $(bench_SOURCES) $(bench_cascade_SOURCES) \ + $(bench_http_SOURCES) $(bench_httpclient_SOURCES) \ + $(am__regress_SOURCES_DIST) $(test_changelist_SOURCES) \ + $(test_eof_SOURCES) $(test_init_SOURCES) \ + $(test_ratelim_SOURCES) $(test_time_SOURCES) \ + $(test_weof_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EV_LIB_GDI = @EV_LIB_GDI@ +EV_LIB_WS32 = @EV_LIB_WS32@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBEVENT_GC_SECTIONS = @LIBEVENT_GC_SECTIONS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIBADD = @OPENSSL_LIBADD@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ $(am__append_3) +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acx_pthread_config = @acx_pthread_config@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include -DTINYTEST_LOCAL +EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c rpcgen_wrapper.sh test.sh +noinst_HEADERS = tinytest.h tinytest_macros.h regress.h tinytest_local.h + +# TESTS = $(top_srcdir)/test/test.sh +BUILT_SOURCES = $(am__append_2) +test_init_SOURCES = test-init.c +test_init_LDADD = ../libevent_core.la +test_eof_SOURCES = test-eof.c +test_eof_LDADD = ../libevent_core.la +test_changelist_SOURCES = test-changelist.c +test_changelist_LDADD = ../libevent_core.la +test_weof_SOURCES = test-weof.c +test_weof_LDADD = ../libevent_core.la +test_time_SOURCES = test-time.c +test_time_LDADD = ../libevent_core.la +test_ratelim_SOURCES = test-ratelim.c +test_ratelim_LDADD = ../libevent_core.la -lm +regress_SOURCES = regress.c regress_buffer.c regress_http.c \ + regress_dns.c regress_testutils.c regress_testutils.h \ + regress_rpc.c regress.gen.c regress.gen.h regress_et.c \ + regress_bufferevent.c regress_listener.c regress_util.c \ + tinytest.c regress_main.c regress_minheap.c \ + $(regress_thread_SOURCES) $(regress_zlib_SOURCES) \ + $(am__append_4) $(am__append_5) +@BUILD_WIN32_TRUE@regress_thread_SOURCES = regress_thread.c +@PTHREADS_TRUE@regress_thread_SOURCES = regress_thread.c +@ZLIB_REGRESS_TRUE@regress_zlib_SOURCES = regress_zlib.c +regress_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la $(PTHREAD_LIBS) \ + $(ZLIB_LIBS) $(am__append_6) +regress_CPPFLAGS = $(AM_CPPFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) +regress_LDFLAGS = $(PTHREAD_CFLAGS) +bench_SOURCES = bench.c +bench_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +bench_cascade_SOURCES = bench_cascade.c +bench_cascade_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +bench_http_SOURCES = bench_http.c +bench_http_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la +bench_httpclient_SOURCES = bench_httpclient.c +bench_httpclient_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent_core.la +CLEANFILES = rpcgen-attempted +DISTCLEANFILES = *~ +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign test/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +bench$(EXEEXT): $(bench_OBJECTS) $(bench_DEPENDENCIES) $(EXTRA_bench_DEPENDENCIES) + @rm -f bench$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bench_OBJECTS) $(bench_LDADD) $(LIBS) +bench_cascade$(EXEEXT): $(bench_cascade_OBJECTS) $(bench_cascade_DEPENDENCIES) $(EXTRA_bench_cascade_DEPENDENCIES) + @rm -f bench_cascade$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bench_cascade_OBJECTS) $(bench_cascade_LDADD) $(LIBS) +bench_http$(EXEEXT): $(bench_http_OBJECTS) $(bench_http_DEPENDENCIES) $(EXTRA_bench_http_DEPENDENCIES) + @rm -f bench_http$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bench_http_OBJECTS) $(bench_http_LDADD) $(LIBS) +bench_httpclient$(EXEEXT): $(bench_httpclient_OBJECTS) $(bench_httpclient_DEPENDENCIES) $(EXTRA_bench_httpclient_DEPENDENCIES) + @rm -f bench_httpclient$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bench_httpclient_OBJECTS) $(bench_httpclient_LDADD) $(LIBS) +regress$(EXEEXT): $(regress_OBJECTS) $(regress_DEPENDENCIES) $(EXTRA_regress_DEPENDENCIES) + @rm -f regress$(EXEEXT) + $(AM_V_CCLD)$(regress_LINK) $(regress_OBJECTS) $(regress_LDADD) $(LIBS) +test-changelist$(EXEEXT): $(test_changelist_OBJECTS) $(test_changelist_DEPENDENCIES) $(EXTRA_test_changelist_DEPENDENCIES) + @rm -f test-changelist$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_changelist_OBJECTS) $(test_changelist_LDADD) $(LIBS) +test-eof$(EXEEXT): $(test_eof_OBJECTS) $(test_eof_DEPENDENCIES) $(EXTRA_test_eof_DEPENDENCIES) + @rm -f test-eof$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_eof_OBJECTS) $(test_eof_LDADD) $(LIBS) +test-init$(EXEEXT): $(test_init_OBJECTS) $(test_init_DEPENDENCIES) $(EXTRA_test_init_DEPENDENCIES) + @rm -f test-init$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_init_OBJECTS) $(test_init_LDADD) $(LIBS) +test-ratelim$(EXEEXT): $(test_ratelim_OBJECTS) $(test_ratelim_DEPENDENCIES) $(EXTRA_test_ratelim_DEPENDENCIES) + @rm -f test-ratelim$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ratelim_OBJECTS) $(test_ratelim_LDADD) $(LIBS) +test-time$(EXEEXT): $(test_time_OBJECTS) $(test_time_DEPENDENCIES) $(EXTRA_test_time_DEPENDENCIES) + @rm -f test-time$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_time_OBJECTS) $(test_time_LDADD) $(LIBS) +test-weof$(EXEEXT): $(test_weof_OBJECTS) $(test_weof_DEPENDENCIES) $(EXTRA_test_weof_DEPENDENCIES) + @rm -f test-weof$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_weof_OBJECTS) $(test_weof_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bench.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bench_cascade.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bench_http.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bench_httpclient.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress.gen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_buffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_bufferevent.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_dns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_et.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_http.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_iocp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_listener.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_minheap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_rpc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_ssl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_testutils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_thread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-regress_zlib.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regress-tinytest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-changelist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-eof.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ratelim.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-time.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-weof.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +regress-regress.o: regress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress.o -MD -MP -MF $(DEPDIR)/regress-regress.Tpo -c -o regress-regress.o `test -f 'regress.c' || echo '$(srcdir)/'`regress.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress.Tpo $(DEPDIR)/regress-regress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress.c' object='regress-regress.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress.o `test -f 'regress.c' || echo '$(srcdir)/'`regress.c + +regress-regress.obj: regress.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress.obj -MD -MP -MF $(DEPDIR)/regress-regress.Tpo -c -o regress-regress.obj `if test -f 'regress.c'; then $(CYGPATH_W) 'regress.c'; else $(CYGPATH_W) '$(srcdir)/regress.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress.Tpo $(DEPDIR)/regress-regress.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress.c' object='regress-regress.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress.obj `if test -f 'regress.c'; then $(CYGPATH_W) 'regress.c'; else $(CYGPATH_W) '$(srcdir)/regress.c'; fi` + +regress-regress_buffer.o: regress_buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_buffer.o -MD -MP -MF $(DEPDIR)/regress-regress_buffer.Tpo -c -o regress-regress_buffer.o `test -f 'regress_buffer.c' || echo '$(srcdir)/'`regress_buffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_buffer.Tpo $(DEPDIR)/regress-regress_buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_buffer.c' object='regress-regress_buffer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_buffer.o `test -f 'regress_buffer.c' || echo '$(srcdir)/'`regress_buffer.c + +regress-regress_buffer.obj: regress_buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_buffer.obj -MD -MP -MF $(DEPDIR)/regress-regress_buffer.Tpo -c -o regress-regress_buffer.obj `if test -f 'regress_buffer.c'; then $(CYGPATH_W) 'regress_buffer.c'; else $(CYGPATH_W) '$(srcdir)/regress_buffer.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_buffer.Tpo $(DEPDIR)/regress-regress_buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_buffer.c' object='regress-regress_buffer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_buffer.obj `if test -f 'regress_buffer.c'; then $(CYGPATH_W) 'regress_buffer.c'; else $(CYGPATH_W) '$(srcdir)/regress_buffer.c'; fi` + +regress-regress_http.o: regress_http.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_http.o -MD -MP -MF $(DEPDIR)/regress-regress_http.Tpo -c -o regress-regress_http.o `test -f 'regress_http.c' || echo '$(srcdir)/'`regress_http.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_http.Tpo $(DEPDIR)/regress-regress_http.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_http.c' object='regress-regress_http.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_http.o `test -f 'regress_http.c' || echo '$(srcdir)/'`regress_http.c + +regress-regress_http.obj: regress_http.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_http.obj -MD -MP -MF $(DEPDIR)/regress-regress_http.Tpo -c -o regress-regress_http.obj `if test -f 'regress_http.c'; then $(CYGPATH_W) 'regress_http.c'; else $(CYGPATH_W) '$(srcdir)/regress_http.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_http.Tpo $(DEPDIR)/regress-regress_http.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_http.c' object='regress-regress_http.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_http.obj `if test -f 'regress_http.c'; then $(CYGPATH_W) 'regress_http.c'; else $(CYGPATH_W) '$(srcdir)/regress_http.c'; fi` + +regress-regress_dns.o: regress_dns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_dns.o -MD -MP -MF $(DEPDIR)/regress-regress_dns.Tpo -c -o regress-regress_dns.o `test -f 'regress_dns.c' || echo '$(srcdir)/'`regress_dns.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_dns.Tpo $(DEPDIR)/regress-regress_dns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_dns.c' object='regress-regress_dns.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_dns.o `test -f 'regress_dns.c' || echo '$(srcdir)/'`regress_dns.c + +regress-regress_dns.obj: regress_dns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_dns.obj -MD -MP -MF $(DEPDIR)/regress-regress_dns.Tpo -c -o regress-regress_dns.obj `if test -f 'regress_dns.c'; then $(CYGPATH_W) 'regress_dns.c'; else $(CYGPATH_W) '$(srcdir)/regress_dns.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_dns.Tpo $(DEPDIR)/regress-regress_dns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_dns.c' object='regress-regress_dns.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_dns.obj `if test -f 'regress_dns.c'; then $(CYGPATH_W) 'regress_dns.c'; else $(CYGPATH_W) '$(srcdir)/regress_dns.c'; fi` + +regress-regress_testutils.o: regress_testutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_testutils.o -MD -MP -MF $(DEPDIR)/regress-regress_testutils.Tpo -c -o regress-regress_testutils.o `test -f 'regress_testutils.c' || echo '$(srcdir)/'`regress_testutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_testutils.Tpo $(DEPDIR)/regress-regress_testutils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_testutils.c' object='regress-regress_testutils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_testutils.o `test -f 'regress_testutils.c' || echo '$(srcdir)/'`regress_testutils.c + +regress-regress_testutils.obj: regress_testutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_testutils.obj -MD -MP -MF $(DEPDIR)/regress-regress_testutils.Tpo -c -o regress-regress_testutils.obj `if test -f 'regress_testutils.c'; then $(CYGPATH_W) 'regress_testutils.c'; else $(CYGPATH_W) '$(srcdir)/regress_testutils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_testutils.Tpo $(DEPDIR)/regress-regress_testutils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_testutils.c' object='regress-regress_testutils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_testutils.obj `if test -f 'regress_testutils.c'; then $(CYGPATH_W) 'regress_testutils.c'; else $(CYGPATH_W) '$(srcdir)/regress_testutils.c'; fi` + +regress-regress_rpc.o: regress_rpc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_rpc.o -MD -MP -MF $(DEPDIR)/regress-regress_rpc.Tpo -c -o regress-regress_rpc.o `test -f 'regress_rpc.c' || echo '$(srcdir)/'`regress_rpc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_rpc.Tpo $(DEPDIR)/regress-regress_rpc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_rpc.c' object='regress-regress_rpc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_rpc.o `test -f 'regress_rpc.c' || echo '$(srcdir)/'`regress_rpc.c + +regress-regress_rpc.obj: regress_rpc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_rpc.obj -MD -MP -MF $(DEPDIR)/regress-regress_rpc.Tpo -c -o regress-regress_rpc.obj `if test -f 'regress_rpc.c'; then $(CYGPATH_W) 'regress_rpc.c'; else $(CYGPATH_W) '$(srcdir)/regress_rpc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_rpc.Tpo $(DEPDIR)/regress-regress_rpc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_rpc.c' object='regress-regress_rpc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_rpc.obj `if test -f 'regress_rpc.c'; then $(CYGPATH_W) 'regress_rpc.c'; else $(CYGPATH_W) '$(srcdir)/regress_rpc.c'; fi` + +regress-regress.gen.o: regress.gen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress.gen.o -MD -MP -MF $(DEPDIR)/regress-regress.gen.Tpo -c -o regress-regress.gen.o `test -f 'regress.gen.c' || echo '$(srcdir)/'`regress.gen.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress.gen.Tpo $(DEPDIR)/regress-regress.gen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress.gen.c' object='regress-regress.gen.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress.gen.o `test -f 'regress.gen.c' || echo '$(srcdir)/'`regress.gen.c + +regress-regress.gen.obj: regress.gen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress.gen.obj -MD -MP -MF $(DEPDIR)/regress-regress.gen.Tpo -c -o regress-regress.gen.obj `if test -f 'regress.gen.c'; then $(CYGPATH_W) 'regress.gen.c'; else $(CYGPATH_W) '$(srcdir)/regress.gen.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress.gen.Tpo $(DEPDIR)/regress-regress.gen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress.gen.c' object='regress-regress.gen.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress.gen.obj `if test -f 'regress.gen.c'; then $(CYGPATH_W) 'regress.gen.c'; else $(CYGPATH_W) '$(srcdir)/regress.gen.c'; fi` + +regress-regress_et.o: regress_et.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_et.o -MD -MP -MF $(DEPDIR)/regress-regress_et.Tpo -c -o regress-regress_et.o `test -f 'regress_et.c' || echo '$(srcdir)/'`regress_et.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_et.Tpo $(DEPDIR)/regress-regress_et.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_et.c' object='regress-regress_et.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_et.o `test -f 'regress_et.c' || echo '$(srcdir)/'`regress_et.c + +regress-regress_et.obj: regress_et.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_et.obj -MD -MP -MF $(DEPDIR)/regress-regress_et.Tpo -c -o regress-regress_et.obj `if test -f 'regress_et.c'; then $(CYGPATH_W) 'regress_et.c'; else $(CYGPATH_W) '$(srcdir)/regress_et.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_et.Tpo $(DEPDIR)/regress-regress_et.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_et.c' object='regress-regress_et.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_et.obj `if test -f 'regress_et.c'; then $(CYGPATH_W) 'regress_et.c'; else $(CYGPATH_W) '$(srcdir)/regress_et.c'; fi` + +regress-regress_bufferevent.o: regress_bufferevent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_bufferevent.o -MD -MP -MF $(DEPDIR)/regress-regress_bufferevent.Tpo -c -o regress-regress_bufferevent.o `test -f 'regress_bufferevent.c' || echo '$(srcdir)/'`regress_bufferevent.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_bufferevent.Tpo $(DEPDIR)/regress-regress_bufferevent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_bufferevent.c' object='regress-regress_bufferevent.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_bufferevent.o `test -f 'regress_bufferevent.c' || echo '$(srcdir)/'`regress_bufferevent.c + +regress-regress_bufferevent.obj: regress_bufferevent.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_bufferevent.obj -MD -MP -MF $(DEPDIR)/regress-regress_bufferevent.Tpo -c -o regress-regress_bufferevent.obj `if test -f 'regress_bufferevent.c'; then $(CYGPATH_W) 'regress_bufferevent.c'; else $(CYGPATH_W) '$(srcdir)/regress_bufferevent.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_bufferevent.Tpo $(DEPDIR)/regress-regress_bufferevent.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_bufferevent.c' object='regress-regress_bufferevent.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_bufferevent.obj `if test -f 'regress_bufferevent.c'; then $(CYGPATH_W) 'regress_bufferevent.c'; else $(CYGPATH_W) '$(srcdir)/regress_bufferevent.c'; fi` + +regress-regress_listener.o: regress_listener.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_listener.o -MD -MP -MF $(DEPDIR)/regress-regress_listener.Tpo -c -o regress-regress_listener.o `test -f 'regress_listener.c' || echo '$(srcdir)/'`regress_listener.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_listener.Tpo $(DEPDIR)/regress-regress_listener.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_listener.c' object='regress-regress_listener.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_listener.o `test -f 'regress_listener.c' || echo '$(srcdir)/'`regress_listener.c + +regress-regress_listener.obj: regress_listener.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_listener.obj -MD -MP -MF $(DEPDIR)/regress-regress_listener.Tpo -c -o regress-regress_listener.obj `if test -f 'regress_listener.c'; then $(CYGPATH_W) 'regress_listener.c'; else $(CYGPATH_W) '$(srcdir)/regress_listener.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_listener.Tpo $(DEPDIR)/regress-regress_listener.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_listener.c' object='regress-regress_listener.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_listener.obj `if test -f 'regress_listener.c'; then $(CYGPATH_W) 'regress_listener.c'; else $(CYGPATH_W) '$(srcdir)/regress_listener.c'; fi` + +regress-regress_util.o: regress_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_util.o -MD -MP -MF $(DEPDIR)/regress-regress_util.Tpo -c -o regress-regress_util.o `test -f 'regress_util.c' || echo '$(srcdir)/'`regress_util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_util.Tpo $(DEPDIR)/regress-regress_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_util.c' object='regress-regress_util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_util.o `test -f 'regress_util.c' || echo '$(srcdir)/'`regress_util.c + +regress-regress_util.obj: regress_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_util.obj -MD -MP -MF $(DEPDIR)/regress-regress_util.Tpo -c -o regress-regress_util.obj `if test -f 'regress_util.c'; then $(CYGPATH_W) 'regress_util.c'; else $(CYGPATH_W) '$(srcdir)/regress_util.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_util.Tpo $(DEPDIR)/regress-regress_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_util.c' object='regress-regress_util.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_util.obj `if test -f 'regress_util.c'; then $(CYGPATH_W) 'regress_util.c'; else $(CYGPATH_W) '$(srcdir)/regress_util.c'; fi` + +regress-tinytest.o: tinytest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-tinytest.o -MD -MP -MF $(DEPDIR)/regress-tinytest.Tpo -c -o regress-tinytest.o `test -f 'tinytest.c' || echo '$(srcdir)/'`tinytest.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-tinytest.Tpo $(DEPDIR)/regress-tinytest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tinytest.c' object='regress-tinytest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-tinytest.o `test -f 'tinytest.c' || echo '$(srcdir)/'`tinytest.c + +regress-tinytest.obj: tinytest.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-tinytest.obj -MD -MP -MF $(DEPDIR)/regress-tinytest.Tpo -c -o regress-tinytest.obj `if test -f 'tinytest.c'; then $(CYGPATH_W) 'tinytest.c'; else $(CYGPATH_W) '$(srcdir)/tinytest.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-tinytest.Tpo $(DEPDIR)/regress-tinytest.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tinytest.c' object='regress-tinytest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-tinytest.obj `if test -f 'tinytest.c'; then $(CYGPATH_W) 'tinytest.c'; else $(CYGPATH_W) '$(srcdir)/tinytest.c'; fi` + +regress-regress_main.o: regress_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_main.o -MD -MP -MF $(DEPDIR)/regress-regress_main.Tpo -c -o regress-regress_main.o `test -f 'regress_main.c' || echo '$(srcdir)/'`regress_main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_main.Tpo $(DEPDIR)/regress-regress_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_main.c' object='regress-regress_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_main.o `test -f 'regress_main.c' || echo '$(srcdir)/'`regress_main.c + +regress-regress_main.obj: regress_main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_main.obj -MD -MP -MF $(DEPDIR)/regress-regress_main.Tpo -c -o regress-regress_main.obj `if test -f 'regress_main.c'; then $(CYGPATH_W) 'regress_main.c'; else $(CYGPATH_W) '$(srcdir)/regress_main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_main.Tpo $(DEPDIR)/regress-regress_main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_main.c' object='regress-regress_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_main.obj `if test -f 'regress_main.c'; then $(CYGPATH_W) 'regress_main.c'; else $(CYGPATH_W) '$(srcdir)/regress_main.c'; fi` + +regress-regress_minheap.o: regress_minheap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_minheap.o -MD -MP -MF $(DEPDIR)/regress-regress_minheap.Tpo -c -o regress-regress_minheap.o `test -f 'regress_minheap.c' || echo '$(srcdir)/'`regress_minheap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_minheap.Tpo $(DEPDIR)/regress-regress_minheap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_minheap.c' object='regress-regress_minheap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_minheap.o `test -f 'regress_minheap.c' || echo '$(srcdir)/'`regress_minheap.c + +regress-regress_minheap.obj: regress_minheap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_minheap.obj -MD -MP -MF $(DEPDIR)/regress-regress_minheap.Tpo -c -o regress-regress_minheap.obj `if test -f 'regress_minheap.c'; then $(CYGPATH_W) 'regress_minheap.c'; else $(CYGPATH_W) '$(srcdir)/regress_minheap.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_minheap.Tpo $(DEPDIR)/regress-regress_minheap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_minheap.c' object='regress-regress_minheap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_minheap.obj `if test -f 'regress_minheap.c'; then $(CYGPATH_W) 'regress_minheap.c'; else $(CYGPATH_W) '$(srcdir)/regress_minheap.c'; fi` + +regress-regress_thread.o: regress_thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_thread.o -MD -MP -MF $(DEPDIR)/regress-regress_thread.Tpo -c -o regress-regress_thread.o `test -f 'regress_thread.c' || echo '$(srcdir)/'`regress_thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_thread.Tpo $(DEPDIR)/regress-regress_thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_thread.c' object='regress-regress_thread.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_thread.o `test -f 'regress_thread.c' || echo '$(srcdir)/'`regress_thread.c + +regress-regress_thread.obj: regress_thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_thread.obj -MD -MP -MF $(DEPDIR)/regress-regress_thread.Tpo -c -o regress-regress_thread.obj `if test -f 'regress_thread.c'; then $(CYGPATH_W) 'regress_thread.c'; else $(CYGPATH_W) '$(srcdir)/regress_thread.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_thread.Tpo $(DEPDIR)/regress-regress_thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_thread.c' object='regress-regress_thread.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_thread.obj `if test -f 'regress_thread.c'; then $(CYGPATH_W) 'regress_thread.c'; else $(CYGPATH_W) '$(srcdir)/regress_thread.c'; fi` + +regress-regress_zlib.o: regress_zlib.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_zlib.o -MD -MP -MF $(DEPDIR)/regress-regress_zlib.Tpo -c -o regress-regress_zlib.o `test -f 'regress_zlib.c' || echo '$(srcdir)/'`regress_zlib.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_zlib.Tpo $(DEPDIR)/regress-regress_zlib.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_zlib.c' object='regress-regress_zlib.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_zlib.o `test -f 'regress_zlib.c' || echo '$(srcdir)/'`regress_zlib.c + +regress-regress_zlib.obj: regress_zlib.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_zlib.obj -MD -MP -MF $(DEPDIR)/regress-regress_zlib.Tpo -c -o regress-regress_zlib.obj `if test -f 'regress_zlib.c'; then $(CYGPATH_W) 'regress_zlib.c'; else $(CYGPATH_W) '$(srcdir)/regress_zlib.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_zlib.Tpo $(DEPDIR)/regress-regress_zlib.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_zlib.c' object='regress-regress_zlib.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_zlib.obj `if test -f 'regress_zlib.c'; then $(CYGPATH_W) 'regress_zlib.c'; else $(CYGPATH_W) '$(srcdir)/regress_zlib.c'; fi` + +regress-regress_iocp.o: regress_iocp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_iocp.o -MD -MP -MF $(DEPDIR)/regress-regress_iocp.Tpo -c -o regress-regress_iocp.o `test -f 'regress_iocp.c' || echo '$(srcdir)/'`regress_iocp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_iocp.Tpo $(DEPDIR)/regress-regress_iocp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_iocp.c' object='regress-regress_iocp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_iocp.o `test -f 'regress_iocp.c' || echo '$(srcdir)/'`regress_iocp.c + +regress-regress_iocp.obj: regress_iocp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_iocp.obj -MD -MP -MF $(DEPDIR)/regress-regress_iocp.Tpo -c -o regress-regress_iocp.obj `if test -f 'regress_iocp.c'; then $(CYGPATH_W) 'regress_iocp.c'; else $(CYGPATH_W) '$(srcdir)/regress_iocp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_iocp.Tpo $(DEPDIR)/regress-regress_iocp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_iocp.c' object='regress-regress_iocp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_iocp.obj `if test -f 'regress_iocp.c'; then $(CYGPATH_W) 'regress_iocp.c'; else $(CYGPATH_W) '$(srcdir)/regress_iocp.c'; fi` + +regress-regress_ssl.o: regress_ssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_ssl.o -MD -MP -MF $(DEPDIR)/regress-regress_ssl.Tpo -c -o regress-regress_ssl.o `test -f 'regress_ssl.c' || echo '$(srcdir)/'`regress_ssl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_ssl.Tpo $(DEPDIR)/regress-regress_ssl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_ssl.c' object='regress-regress_ssl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_ssl.o `test -f 'regress_ssl.c' || echo '$(srcdir)/'`regress_ssl.c + +regress-regress_ssl.obj: regress_ssl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regress-regress_ssl.obj -MD -MP -MF $(DEPDIR)/regress-regress_ssl.Tpo -c -o regress-regress_ssl.obj `if test -f 'regress_ssl.c'; then $(CYGPATH_W) 'regress_ssl.c'; else $(CYGPATH_W) '$(srcdir)/regress_ssl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regress-regress_ssl.Tpo $(DEPDIR)/regress-regress_ssl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regress_ssl.c' object='regress-regress_ssl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(regress_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regress-regress_ssl.obj `if test -f 'regress_ssl.c'; then $(CYGPATH_W) 'regress_ssl.c'; else $(CYGPATH_W) '$(srcdir)/regress_ssl.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +regress.gen.c regress.gen.h: rpcgen-attempted + +rpcgen-attempted: $(srcdir)/regress.rpc $(srcdir)/../event_rpcgen.py $(srcdir)/rpcgen_wrapper.sh + date -u > $@ + if $(srcdir)/rpcgen_wrapper.sh $(srcdir); then \ + echo "rpcgen okay"; \ + else \ + echo "No Python installed; stubbing out RPC test." >&2; \ + echo " "> regress.gen.c; \ + echo "#define NO_PYTHON_EXISTS" > regress.gen.h; \ + fi + +verify: check + +bench test-init test-eof test-weof test-time test-changelist: ../libevent.la + +# 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/libevent/test/Makefile.nmake b/libevent/test/Makefile.nmake new file mode 100644 index 0000000..a899941 --- /dev/null +++ b/libevent/test/Makefile.nmake @@ -0,0 +1,61 @@ + +CFLAGS=/I.. /I../WIN32-Code /I../include /I../compat /DWIN32 /DHAVE_CONFIG_H /DTINYTEST_LOCAL + +CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo + +REGRESS_OBJS=regress.obj regress_buffer.obj regress_http.obj regress_dns.obj \ + regress_testutils.obj \ + regress_rpc.obj regress.gen.obj \ + regress_et.obj regress_bufferevent.obj \ + regress_listener.obj regress_util.obj tinytest.obj \ + regress_main.obj regress_minheap.obj regress_iocp.obj \ + regress_thread.obj + +OTHER_OBJS=test-init.obj test-eof.obj test-weof.obj test-time.obj \ + bench.obj bench_cascade.obj bench_http.obj bench_httpclient.obj \ + test-changelist.obj + +PROGRAMS=regress.exe \ + test-init.exe test-eof.exe test-weof.exe test-time.exe \ + test-changelist.exe + +# Disabled for now: +# bench.exe bench_cascade.exe bench_http.exe bench_httpclient.exe + + +LIBS=..\libevent.lib ws2_32.lib shell32.lib advapi32.lib + +all: $(PROGRAMS) + +regress.exe: $(REGRESS_OBJS) + $(CC) $(CFLAGS) $(LIBS) $(REGRESS_OBJS) + +test-init.exe: test-init.obj + $(CC) $(CFLAGS) $(LIBS) test-init.obj +test-eof.exe: test-eof.obj + $(CC) $(CFLAGS) $(LIBS) test-eof.obj +test-changelist.exe: test-changelist.obj + $(CC) $(CFLAGS) $(LIBS) test-changelist.obj +test-weof.exe: test-weof.obj + $(CC) $(CFLAGS) $(LIBS) test-weof.obj +test-time.exe: test-time.obj + $(CC) $(CFLAGS) $(LIBS) test-time.obj + +bench.exe: bench.obj + $(CC) $(CFLAGS) $(LIBS) bench.obj +bench_cascade.exe: bench_cascade.obj + $(CC) $(CFLAGS) $(LIBS) bench_cascade.obj +bench_http.exe: bench_http.obj + $(CC) $(CFLAGS) $(LIBS) bench_http.obj +bench_httpclient.exe: bench_httpclient.obj + $(CC) $(CFLAGS) $(LIBS) bench_httpclient.obj + +regress.gen.c regress.gen.h: regress.rpc ../event_rpcgen.py + echo // > regress.gen.c + echo #define NO_PYTHON_EXISTS > regress.gen.h + -python ..\event_rpcgen.py regress.rpc + +clean: + -del $(REGRESS_OBJS) + -del $(OTHER_OBJS) + -del regress.exe diff --git a/libevent/test/bench.c b/libevent/test/bench.c new file mode 100644 index 0000000..66b7d71 --- /dev/null +++ b/libevent/test/bench.c @@ -0,0 +1,196 @@ +/* + * Copyright 2003-2007 Niels Provos + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + * 4. 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. + * + * + * Mon 03/10/2003 - Modified by Davide Libenzi + * + * Added chain event propagation to improve the sensitivity of + * the measure respect to the event loop efficency. + * + * + */ + +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#include +#endif +#include +#include +#include +#include +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#include + +#include +#include + +static int count, writes, fired; +static int *pipes; +static int num_pipes, num_active, num_writes; +static struct event *events; + + +static void +read_cb(evutil_socket_t fd, short which, void *arg) +{ + long idx = (long) arg, widx = idx + 1; + u_char ch; + + count += recv(fd, (char*)&ch, sizeof(ch), 0); + if (writes) { + if (widx >= num_pipes) + widx -= num_pipes; + send(pipes[2 * widx + 1], "e", 1, 0); + writes--; + fired++; + } +} + +static struct timeval * +run_once(void) +{ + int *cp, space; + long i; + static struct timeval ts, te; + + for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { + if (event_initialized(&events[i])) + event_del(&events[i]); + event_set(&events[i], cp[0], EV_READ | EV_PERSIST, read_cb, (void *) i); + event_add(&events[i], NULL); + } + + event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); + + fired = 0; + space = num_pipes / num_active; + space = space * 2; + for (i = 0; i < num_active; i++, fired++) + send(pipes[i * space + 1], "e", 1, 0); + + count = 0; + writes = num_writes; + { int xcount = 0; + evutil_gettimeofday(&ts, NULL); + do { + event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); + xcount++; + } while (count != fired); + evutil_gettimeofday(&te, NULL); + + if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count); + } + + evutil_timersub(&te, &ts, &te); + + return (&te); +} + +int +main(int argc, char **argv) +{ +#ifndef WIN32 + struct rlimit rl; +#endif + int i, c; + struct timeval *tv; + int *cp; + +#ifdef WIN32 + WSADATA WSAData; + WSAStartup(0x101, &WSAData); +#endif + num_pipes = 100; + num_active = 1; + num_writes = num_pipes; + while ((c = getopt(argc, argv, "n:a:w:")) != -1) { + switch (c) { + case 'n': + num_pipes = atoi(optarg); + break; + case 'a': + num_active = atoi(optarg); + break; + case 'w': + num_writes = atoi(optarg); + break; + default: + fprintf(stderr, "Illegal argument \"%c\"\n", c); + exit(1); + } + } + +#ifndef WIN32 + rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; + if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { + perror("setrlimit"); + exit(1); + } +#endif + + events = calloc(num_pipes, sizeof(struct event)); + pipes = calloc(num_pipes * 2, sizeof(int)); + if (events == NULL || pipes == NULL) { + perror("malloc"); + exit(1); + } + + event_init(); + + for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { +#ifdef USE_PIPES + if (pipe(cp) == -1) { +#else + if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { +#endif + perror("pipe"); + exit(1); + } + } + + for (i = 0; i < 25; i++) { + tv = run_once(); + if (tv == NULL) + exit(1); + fprintf(stdout, "%ld\n", + tv->tv_sec * 1000000L + tv->tv_usec); + } + + exit(0); +} diff --git a/libevent/test/bench_cascade.c b/libevent/test/bench_cascade.c new file mode 100644 index 0000000..08b7f94 --- /dev/null +++ b/libevent/test/bench_cascade.c @@ -0,0 +1,174 @@ +/* + * Copyright 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + * 4. 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. + * + */ + +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include +#ifdef _EVENT_HAVE_UNISTD_H +#include +#endif +#include + +#include +#include + +/* + * This benchmark tests how quickly we can propagate a write down a chain + * of socket pairs. We start by writing to the first socket pair and all + * events will fire subsequently until the last socket pair has been reached + * and the benchmark terminates. + */ + +static int fired; +static int *pipes; +static struct event *events; + +static void +read_cb(evutil_socket_t fd, short which, void *arg) +{ + char ch; + long idx = (long) arg; + + recv(fd, &ch, sizeof(ch), 0); + if (idx >= 0) + send(idx, "e", 1, 0); + fired++; +} + +static struct timeval * +run_once(int num_pipes) +{ + int *cp, i; + static struct timeval ts, te, tv_timeout; + + events = calloc(num_pipes, sizeof(struct event)); + pipes = calloc(num_pipes * 2, sizeof(int)); + + if (events == NULL || pipes == NULL) { + perror("malloc"); + exit(1); + } + + for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { + if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { + perror("socketpair"); + exit(1); + } + } + + /* measurements includes event setup */ + evutil_gettimeofday(&ts, NULL); + + /* provide a default timeout for events */ + evutil_timerclear(&tv_timeout); + tv_timeout.tv_sec = 60; + + for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { + long fd = i < num_pipes - 1 ? cp[3] : -1; + event_set(&events[i], cp[0], EV_READ, read_cb, (void *) fd); + event_add(&events[i], &tv_timeout); + } + + fired = 0; + + /* kick everything off with a single write */ + send(pipes[1], "e", 1, 0); + + event_dispatch(); + + evutil_gettimeofday(&te, NULL); + evutil_timersub(&te, &ts, &te); + + for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { + event_del(&events[i]); + close(cp[0]); + close(cp[1]); + } + + free(pipes); + free(events); + + return (&te); +} + +int +main(int argc, char **argv) +{ +#ifndef WIN32 + struct rlimit rl; +#endif + int i, c; + struct timeval *tv; + + int num_pipes = 100; + while ((c = getopt(argc, argv, "n:")) != -1) { + switch (c) { + case 'n': + num_pipes = atoi(optarg); + break; + default: + fprintf(stderr, "Illegal argument \"%c\"\n", c); + exit(1); + } + } + +#ifndef WIN32 + rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; + if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { + perror("setrlimit"); + exit(1); + } +#endif + + event_init(); + + for (i = 0; i < 25; i++) { + tv = run_once(num_pipes); + if (tv == NULL) + exit(1); + fprintf(stdout, "%ld\n", + tv->tv_sec * 1000000L + tv->tv_usec); + } + + exit(0); +} diff --git a/libevent/test/bench_http.c b/libevent/test/bench_http.c new file mode 100644 index 0000000..f6fd81b --- /dev/null +++ b/libevent/test/bench_http.c @@ -0,0 +1,191 @@ +/* + * Copyright 2008-2012 Niels Provos and Nick Mathewson + * + * 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. + * 4. 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. + * + */ + +#include +#include +#ifdef WIN32 +#include +#else +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "event2/event.h" +#include "event2/buffer.h" +#include "event2/util.h" +#include "event2/http.h" +#include "event2/thread.h" + +static void http_basic_cb(struct evhttp_request *req, void *arg); + +static char *content; +static size_t content_len = 0; + +static void +http_basic_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *evb = evbuffer_new(); + + evbuffer_add(evb, content, content_len); + + /* allow sending of an empty reply */ + evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); + + evbuffer_free(evb); +} + +#if LIBEVENT_VERSION_NUMBER >= 0x02000200 +static void +http_ref_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *evb = evbuffer_new(); + + evbuffer_add_reference(evb, content, content_len, NULL, NULL); + + /* allow sending of an empty reply */ + evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); + + evbuffer_free(evb); +} +#endif + +int +main(int argc, char **argv) +{ + struct event_config *cfg = event_config_new(); + struct event_base *base; + struct evhttp *http; + int i; + int c; + int use_iocp = 0; + unsigned short port = 8080; + char *endptr = NULL; + +#ifdef WIN32 + WSADATA WSAData; + WSAStartup(0x101, &WSAData); +#else + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + return (1); +#endif + + for (i = 1; i < argc; ++i) { + if (*argv[i] != '-') + continue; + + c = argv[i][1]; + + if ((c == 'p' || c == 'l') && i + 1 >= argc) { + fprintf(stderr, "-%c requires argument.\n", c); + exit(1); + } + + switch (c) { + case 'p': + if (i+1 >= argc || !argv[i+1]) { + fprintf(stderr, "Missing port\n"); + exit(1); + } + port = (int)strtol(argv[i+1], &endptr, 10); + if (*endptr != '\0') { + fprintf(stderr, "Bad port\n"); + exit(1); + } + break; + case 'l': + if (i+1 >= argc || !argv[i+1]) { + fprintf(stderr, "Missing content length\n"); + exit(1); + } + content_len = (size_t)strtol(argv[i+1], &endptr, 10); + if (*endptr != '\0' || content_len == 0) { + fprintf(stderr, "Bad content length\n"); + exit(1); + } + break; +#ifdef WIN32 + case 'i': + use_iocp = 1; + evthread_use_windows_threads(); + event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP); + break; +#endif + default: + fprintf(stderr, "Illegal argument \"%c\"\n", c); + exit(1); + } + } + + base = event_base_new_with_config(cfg); + if (!base) { + fprintf(stderr, "creating event_base failed. Exiting.\n"); + return 1; + } + + http = evhttp_new(base); + + content = malloc(content_len); + if (content == NULL) { + fprintf(stderr, "Cannot allocate content\n"); + exit(1); + } else { + int i = 0; + for (i = 0; i < (int)content_len; ++i) + content[i] = (i & 255); + } + + evhttp_set_cb(http, "/ind", http_basic_cb, NULL); + fprintf(stderr, "/ind - basic content (memory copy)\n"); + +#ifdef _EVENT2_EVENT_H_ + evhttp_set_cb(http, "/ref", http_ref_cb, NULL); + fprintf(stderr, "/ref - basic content (reference)\n"); +#endif + + fprintf(stderr, "Serving %d bytes on port %d using %s\n", + (int)content_len, port, + use_iocp? "IOCP" : event_base_get_method(base)); + + evhttp_bind_socket(http, "0.0.0.0", port); + + if (use_iocp) { + struct timeval tv={99999999,0}; + event_base_loopexit(base, &tv); + } + event_base_dispatch(base); + + /* NOTREACHED */ + return (0); +} diff --git a/libevent/test/bench_httpclient.c b/libevent/test/bench_httpclient.c new file mode 100644 index 0000000..cf66753 --- /dev/null +++ b/libevent/test/bench_httpclient.c @@ -0,0 +1,222 @@ +/* + * Copyright 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + * 4. 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. + * + */ + +#include +#ifdef WIN32 +#include +#else +#include +#include +# ifdef _XOPEN_SOURCE_EXTENDED +# include +# endif +#endif +#include +#include +#include + +#include "event2/event.h" +#include "event2/bufferevent.h" +#include "event2/buffer.h" +#include "event2/util.h" + +/* for EVUTIL_ERR_CONNECT_RETRIABLE macro */ +#include "util-internal.h" + +const char *resource = NULL; +struct event_base *base = NULL; + +int total_n_handled = 0; +int total_n_errors = 0; +int total_n_launched = 0; +size_t total_n_bytes = 0; +struct timeval total_time = {0,0}; +int n_errors = 0; + +const int PARALLELISM = 200; +const int N_REQUESTS = 20000; + +struct request_info { + size_t n_read; + struct timeval started; +}; + +static int launch_request(void); +static void readcb(struct bufferevent *b, void *arg); +static void errorcb(struct bufferevent *b, short what, void *arg); + +static void +readcb(struct bufferevent *b, void *arg) +{ + struct request_info *ri = arg; + struct evbuffer *input = bufferevent_get_input(b); + size_t n = evbuffer_get_length(input); + + ri->n_read += n; + evbuffer_drain(input, n); +} + +static void +errorcb(struct bufferevent *b, short what, void *arg) +{ + struct request_info *ri = arg; + struct timeval now, diff; + if (what & BEV_EVENT_EOF) { + ++total_n_handled; + total_n_bytes += ri->n_read; + evutil_gettimeofday(&now, NULL); + evutil_timersub(&now, &ri->started, &diff); + evutil_timeradd(&diff, &total_time, &total_time); + + if (total_n_handled && (total_n_handled%1000)==0) + printf("%d requests done\n",total_n_handled); + + if (total_n_launched < N_REQUESTS) { + if (launch_request() < 0) + perror("Can't launch"); + } + } else { + ++total_n_errors; + perror("Unexpected error"); + } + + bufferevent_setcb(b, NULL, NULL, NULL, NULL); + free(ri); + bufferevent_disable(b, EV_READ|EV_WRITE); + bufferevent_free(b); +} + +static void +frob_socket(evutil_socket_t sock) +{ + struct linger l; + int one = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof(one)); + l.l_onoff = 1; + l.l_linger = 0; + if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&l, sizeof(l))<0) + perror("setsockopt"); +} + +static int +launch_request(void) +{ + evutil_socket_t sock; + struct sockaddr_in sin; + struct bufferevent *b; + + struct request_info *ri; + + memset(&sin, 0, sizeof(sin)); + + ++total_n_launched; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(0x7f000001); + sin.sin_port = htons(8080); + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + if (evutil_make_socket_nonblocking(sock) < 0) + return -1; + frob_socket(sock); + if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) { + int e = errno; + if (! EVUTIL_ERR_CONNECT_RETRIABLE(e)) { + return -1; + } + } + + ri = malloc(sizeof(*ri)); + ri->n_read = 0; + evutil_gettimeofday(&ri->started, NULL); + + b = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE); + + bufferevent_setcb(b, readcb, NULL, errorcb, ri); + bufferevent_enable(b, EV_READ|EV_WRITE); + + evbuffer_add_printf(bufferevent_get_output(b), + "GET %s HTTP/1.0\r\n\r\n", resource); + + return 0; +} + + +int +main(int argc, char **argv) +{ + int i; + struct timeval start, end, total; + long long usec; + double throughput; + resource = "/ref"; + + setvbuf(stdout, NULL, _IONBF, 0); + + base = event_base_new(); + + for (i=0; i < PARALLELISM; ++i) { + if (launch_request() < 0) + perror("launch"); + } + + evutil_gettimeofday(&start, NULL); + + event_base_dispatch(base); + + evutil_gettimeofday(&end, NULL); + evutil_timersub(&end, &start, &total); + usec = total_time.tv_sec * 1000000 + total_time.tv_usec; + + if (!total_n_handled) { + puts("Nothing worked. You probably did something dumb."); + return 0; + } + + + throughput = total_n_handled / + (total.tv_sec+ ((double)total.tv_usec)/1000000.0); + +#ifdef WIN32 +#define I64_FMT "%I64d" +#define I64_TYP __int64 +#else +#define I64_FMT "%lld" +#define I64_TYP long long int +#endif + + printf("\n%d requests in %d.%06d sec. (%.2f throughput)\n" + "Each took about %.02f msec latency\n" + I64_FMT "bytes read. %d errors.\n", + total_n_handled, + (int)total.tv_sec, (int)total.tv_usec, + throughput, + (double)(usec/1000) / total_n_handled, + (I64_TYP)total_n_bytes, n_errors); + + return 0; +} diff --git a/libevent/test/regress.c b/libevent/test/regress.c new file mode 100644 index 0000000..2d48583 --- /dev/null +++ b/libevent/test/regress.c @@ -0,0 +1,2406 @@ +/* + * Copyright (c) 2003-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#ifdef WIN32 +#include +#include +#endif + +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#ifndef WIN32 +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/event_compat.h" +#include "event2/tag.h" +#include "event2/buffer.h" +#include "event2/buffer_compat.h" +#include "event2/util.h" +#include "event-internal.h" +#include "evthread-internal.h" +#include "util-internal.h" +#include "log-internal.h" + +#include "regress.h" + +#ifndef WIN32 +#include "regress.gen.h" +#endif + +evutil_socket_t pair[2]; +int test_ok; +int called; +struct event_base *global_base; + +static char wbuf[4096]; +static char rbuf[4096]; +static int woff; +static int roff; +static int usepersist; +static struct timeval tset; +static struct timeval tcalled; + + +#define TEST1 "this is a test" +#define SECONDS 1 + +#ifndef SHUT_WR +#define SHUT_WR 1 +#endif + +#ifdef WIN32 +#define write(fd,buf,len) send((fd),(buf),(int)(len),0) +#define read(fd,buf,len) recv((fd),(buf),(int)(len),0) +#endif + +struct basic_cb_args +{ + struct event_base *eb; + struct event *ev; + unsigned int callcount; +}; + +static void +simple_read_cb(evutil_socket_t fd, short event, void *arg) +{ + char buf[256]; + int len; + + len = read(fd, buf, sizeof(buf)); + + if (len) { + if (!called) { + if (event_add(arg, NULL) == -1) + exit(1); + } + } else if (called == 1) + test_ok = 1; + + called++; +} + +static void +basic_read_cb(evutil_socket_t fd, short event, void *data) +{ + char buf[256]; + int len; + struct basic_cb_args *arg = data; + + len = read(fd, buf, sizeof(buf)); + + if (len < 0) { + tt_fail_perror("read (callback)"); + } else { + switch (arg->callcount++) { + case 0: /* first call: expect to read data; cycle */ + if (len > 0) + return; + + tt_fail_msg("EOF before data read"); + break; + + case 1: /* second call: expect EOF; stop */ + if (len > 0) + tt_fail_msg("not all data read on first cycle"); + break; + + default: /* third call: should not happen */ + tt_fail_msg("too many cycles"); + } + } + + event_del(arg->ev); + event_base_loopexit(arg->eb, NULL); +} + +static void +dummy_read_cb(evutil_socket_t fd, short event, void *arg) +{ +} + +static void +simple_write_cb(evutil_socket_t fd, short event, void *arg) +{ + int len; + + len = write(fd, TEST1, strlen(TEST1) + 1); + if (len == -1) + test_ok = 0; + else + test_ok = 1; +} + +static void +multiple_write_cb(evutil_socket_t fd, short event, void *arg) +{ + struct event *ev = arg; + int len; + + len = 128; + if (woff + len >= (int)sizeof(wbuf)) + len = sizeof(wbuf) - woff; + + len = write(fd, wbuf + woff, len); + if (len == -1) { + fprintf(stderr, "%s: write\n", __func__); + if (usepersist) + event_del(ev); + return; + } + + woff += len; + + if (woff >= (int)sizeof(wbuf)) { + shutdown(fd, SHUT_WR); + if (usepersist) + event_del(ev); + return; + } + + if (!usepersist) { + if (event_add(ev, NULL) == -1) + exit(1); + } +} + +static void +multiple_read_cb(evutil_socket_t fd, short event, void *arg) +{ + struct event *ev = arg; + int len; + + len = read(fd, rbuf + roff, sizeof(rbuf) - roff); + if (len == -1) + fprintf(stderr, "%s: read\n", __func__); + if (len <= 0) { + if (usepersist) + event_del(ev); + return; + } + + roff += len; + if (!usepersist) { + if (event_add(ev, NULL) == -1) + exit(1); + } +} + +static void +timeout_cb(evutil_socket_t fd, short event, void *arg) +{ + struct timeval tv; + int diff; + + evutil_gettimeofday(&tcalled, NULL); + if (evutil_timercmp(&tcalled, &tset, >)) + evutil_timersub(&tcalled, &tset, &tv); + else + evutil_timersub(&tset, &tcalled, &tv); + + diff = tv.tv_sec*1000 + tv.tv_usec/1000 - SECONDS * 1000; + if (diff < 0) + diff = -diff; + + if (diff < 100) + test_ok = 1; +} + +struct both { + struct event ev; + int nread; +}; + +static void +combined_read_cb(evutil_socket_t fd, short event, void *arg) +{ + struct both *both = arg; + char buf[128]; + int len; + + len = read(fd, buf, sizeof(buf)); + if (len == -1) + fprintf(stderr, "%s: read\n", __func__); + if (len <= 0) + return; + + both->nread += len; + if (event_add(&both->ev, NULL) == -1) + exit(1); +} + +static void +combined_write_cb(evutil_socket_t fd, short event, void *arg) +{ + struct both *both = arg; + char buf[128]; + int len; + + len = sizeof(buf); + if (len > both->nread) + len = both->nread; + + memset(buf, 'q', len); + + len = write(fd, buf, len); + if (len == -1) + fprintf(stderr, "%s: write\n", __func__); + if (len <= 0) { + shutdown(fd, SHUT_WR); + return; + } + + both->nread -= len; + if (event_add(&both->ev, NULL) == -1) + exit(1); +} + +/* These macros used to replicate the work of the legacy test wrapper code */ +#define setup_test(x) do { \ + if (!in_legacy_test_wrapper) { \ + TT_FAIL(("Legacy test %s not wrapped properly", x)); \ + return; \ + } \ + } while (0) +#define cleanup_test() setup_test("cleanup") + +static void +test_simpleread(void) +{ + struct event ev; + + /* Very simple read test */ + setup_test("Simple read: "); + + if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + } + + shutdown(pair[0], SHUT_WR); + + event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); + if (event_add(&ev, NULL) == -1) + exit(1); + event_dispatch(); + + cleanup_test(); +} + +static void +test_simplewrite(void) +{ + struct event ev; + + /* Very simple write test */ + setup_test("Simple write: "); + + event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev); + if (event_add(&ev, NULL) == -1) + exit(1); + event_dispatch(); + + cleanup_test(); +} + +static void +simpleread_multiple_cb(evutil_socket_t fd, short event, void *arg) +{ + if (++called == 2) + test_ok = 1; +} + +static void +test_simpleread_multiple(void) +{ + struct event one, two; + + /* Very simple read test */ + setup_test("Simple read to multiple evens: "); + + if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + } + + shutdown(pair[0], SHUT_WR); + + event_set(&one, pair[1], EV_READ, simpleread_multiple_cb, NULL); + if (event_add(&one, NULL) == -1) + exit(1); + event_set(&two, pair[1], EV_READ, simpleread_multiple_cb, NULL); + if (event_add(&two, NULL) == -1) + exit(1); + event_dispatch(); + + cleanup_test(); +} + +static int have_closed = 0; +static int premature_event = 0; +static void +simpleclose_close_fd_cb(evutil_socket_t s, short what, void *ptr) +{ + evutil_socket_t **fds = ptr; + TT_BLATHER(("Closing")); + evutil_closesocket(*fds[0]); + evutil_closesocket(*fds[1]); + *fds[0] = -1; + *fds[1] = -1; + have_closed = 1; +} + +static void +record_event_cb(evutil_socket_t s, short what, void *ptr) +{ + short *whatp = ptr; + if (!have_closed) + premature_event = 1; + *whatp = what; + TT_BLATHER(("Recorded %d on socket %d", (int)what, (int)s)); +} + +static void +test_simpleclose(void *ptr) +{ + /* Test that a close of FD is detected as a read and as a write. */ + struct event_base *base = event_base_new(); + evutil_socket_t pair1[2]={-1,-1}, pair2[2] = {-1, -1}; + evutil_socket_t *to_close[2]; + struct event *rev=NULL, *wev=NULL, *closeev=NULL; + struct timeval tv; + short got_read_on_close = 0, got_write_on_close = 0; + char buf[1024]; + memset(buf, 99, sizeof(buf)); +#ifdef WIN32 +#define LOCAL_SOCKETPAIR_AF AF_INET +#else +#define LOCAL_SOCKETPAIR_AF AF_UNIX +#endif + if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair1)<0) + TT_DIE(("socketpair: %s", strerror(errno))); + if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair2)<0) + TT_DIE(("socketpair: %s", strerror(errno))); + if (evutil_make_socket_nonblocking(pair1[1]) < 0) + TT_DIE(("make_socket_nonblocking")); + if (evutil_make_socket_nonblocking(pair2[1]) < 0) + TT_DIE(("make_socket_nonblocking")); + + /** Stuff pair2[1] full of data, until write fails */ + while (1) { + int r = write(pair2[1], buf, sizeof(buf)); + if (r<0) { + int err = evutil_socket_geterror(pair2[1]); + if (! EVUTIL_ERR_RW_RETRIABLE(err)) + TT_DIE(("write failed strangely: %s", + evutil_socket_error_to_string(err))); + break; + } + } + to_close[0] = &pair1[0]; + to_close[1] = &pair2[0]; + + closeev = event_new(base, -1, EV_TIMEOUT, simpleclose_close_fd_cb, + to_close); + rev = event_new(base, pair1[1], EV_READ, record_event_cb, + &got_read_on_close); + TT_BLATHER(("Waiting for read on %d", (int)pair1[1])); + wev = event_new(base, pair2[1], EV_WRITE, record_event_cb, + &got_write_on_close); + TT_BLATHER(("Waiting for write on %d", (int)pair2[1])); + tv.tv_sec = 0; + tv.tv_usec = 100*1000; /* Close pair1[0] after a little while, and make + * sure we get a read event. */ + event_add(closeev, &tv); + event_add(rev, NULL); + event_add(wev, NULL); + /* Don't let the test go on too long. */ + tv.tv_sec = 0; + tv.tv_usec = 200*1000; + event_base_loopexit(base, &tv); + event_base_loop(base, 0); + + tt_int_op(got_read_on_close, ==, EV_READ); + tt_int_op(got_write_on_close, ==, EV_WRITE); + tt_int_op(premature_event, ==, 0); + +end: + if (pair1[0] >= 0) + evutil_closesocket(pair1[0]); + if (pair1[1] >= 0) + evutil_closesocket(pair1[1]); + if (pair2[0] >= 0) + evutil_closesocket(pair2[0]); + if (pair2[1] >= 0) + evutil_closesocket(pair2[1]); + if (rev) + event_free(rev); + if (wev) + event_free(wev); + if (closeev) + event_free(closeev); + if (base) + event_base_free(base); +} + + +static void +test_multiple(void) +{ + struct event ev, ev2; + int i; + + /* Multiple read and write test */ + setup_test("Multiple read/write: "); + memset(rbuf, 0, sizeof(rbuf)); + for (i = 0; i < (int)sizeof(wbuf); i++) + wbuf[i] = i; + + roff = woff = 0; + usepersist = 0; + + event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev); + if (event_add(&ev, NULL) == -1) + exit(1); + event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2); + if (event_add(&ev2, NULL) == -1) + exit(1); + event_dispatch(); + + if (roff == woff) + test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; + + cleanup_test(); +} + +static void +test_persistent(void) +{ + struct event ev, ev2; + int i; + + /* Multiple read and write test with persist */ + setup_test("Persist read/write: "); + memset(rbuf, 0, sizeof(rbuf)); + for (i = 0; i < (int)sizeof(wbuf); i++) + wbuf[i] = i; + + roff = woff = 0; + usepersist = 1; + + event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev); + if (event_add(&ev, NULL) == -1) + exit(1); + event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2); + if (event_add(&ev2, NULL) == -1) + exit(1); + event_dispatch(); + + if (roff == woff) + test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; + + cleanup_test(); +} + +static void +test_combined(void) +{ + struct both r1, r2, w1, w2; + + setup_test("Combined read/write: "); + memset(&r1, 0, sizeof(r1)); + memset(&r2, 0, sizeof(r2)); + memset(&w1, 0, sizeof(w1)); + memset(&w2, 0, sizeof(w2)); + + w1.nread = 4096; + w2.nread = 8192; + + event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1); + event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1); + event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2); + event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2); + tt_assert(event_add(&r1.ev, NULL) != -1); + tt_assert(!event_add(&w1.ev, NULL)); + tt_assert(!event_add(&r2.ev, NULL)); + tt_assert(!event_add(&w2.ev, NULL)); + event_dispatch(); + + if (r1.nread == 8192 && r2.nread == 4096) + test_ok = 1; + +end: + cleanup_test(); +} + +static void +test_simpletimeout(void) +{ + struct timeval tv; + struct event ev; + + setup_test("Simple timeout: "); + + tv.tv_usec = 0; + tv.tv_sec = SECONDS; + evtimer_set(&ev, timeout_cb, NULL); + evtimer_add(&ev, &tv); + + evutil_gettimeofday(&tset, NULL); + event_dispatch(); + + cleanup_test(); +} + +static void +periodic_timeout_cb(evutil_socket_t fd, short event, void *arg) +{ + int *count = arg; + + (*count)++; + if (*count == 6) { + /* call loopexit only once - on slow machines(?), it is + * apparently possible for this to get called twice. */ + test_ok = 1; + event_base_loopexit(global_base, NULL); + } +} + +static void +test_persistent_timeout(void) +{ + struct timeval tv; + struct event ev; + int count = 0; + + evutil_timerclear(&tv); + tv.tv_usec = 10000; + + event_assign(&ev, global_base, -1, EV_TIMEOUT|EV_PERSIST, + periodic_timeout_cb, &count); + event_add(&ev, &tv); + + event_dispatch(); + + event_del(&ev); +} + +struct persist_active_timeout_called { + int n; + short events[16]; + struct timeval tvs[16]; +}; + +static void +activate_cb(evutil_socket_t fd, short event, void *arg) +{ + struct event *ev = arg; + event_active(ev, EV_READ, 1); +} + +static void +persist_active_timeout_cb(evutil_socket_t fd, short event, void *arg) +{ + struct persist_active_timeout_called *c = arg; + if (c->n < 15) { + c->events[c->n] = event; + evutil_gettimeofday(&c->tvs[c->n], NULL); + ++c->n; + } +} + +static void +test_persistent_active_timeout(void *ptr) +{ + struct timeval tv, tv2, tv_exit, start; + struct event ev; + struct persist_active_timeout_called res; + + struct basic_test_data *data = ptr; + struct event_base *base = data->base; + + memset(&res, 0, sizeof(res)); + + tv.tv_sec = 0; + tv.tv_usec = 200 * 1000; + event_assign(&ev, base, -1, EV_TIMEOUT|EV_PERSIST, + persist_active_timeout_cb, &res); + event_add(&ev, &tv); + + tv2.tv_sec = 0; + tv2.tv_usec = 100 * 1000; + event_base_once(base, -1, EV_TIMEOUT, activate_cb, &ev, &tv2); + + tv_exit.tv_sec = 0; + tv_exit.tv_usec = 600 * 1000; + event_base_loopexit(base, &tv_exit); + + event_base_assert_ok(base); + evutil_gettimeofday(&start, NULL); + + event_base_dispatch(base); + event_base_assert_ok(base); + + tt_int_op(res.n, ==, 3); + tt_int_op(res.events[0], ==, EV_READ); + tt_int_op(res.events[1], ==, EV_TIMEOUT); + tt_int_op(res.events[2], ==, EV_TIMEOUT); + test_timeval_diff_eq(&start, &res.tvs[0], 100); + test_timeval_diff_eq(&start, &res.tvs[1], 300); + test_timeval_diff_eq(&start, &res.tvs[2], 500); +end: + event_del(&ev); +} + +struct common_timeout_info { + struct event ev; + struct timeval called_at; + int which; + int count; +}; + +static void +common_timeout_cb(evutil_socket_t fd, short event, void *arg) +{ + struct common_timeout_info *ti = arg; + ++ti->count; + evutil_gettimeofday(&ti->called_at, NULL); + if (ti->count >= 6) + event_del(&ti->ev); +} + +static void +test_common_timeout(void *ptr) +{ + struct basic_test_data *data = ptr; + + struct event_base *base = data->base; + int i; + struct common_timeout_info info[100]; + + struct timeval now; + struct timeval tmp_100_ms = { 0, 100*1000 }; + struct timeval tmp_200_ms = { 0, 200*1000 }; + + const struct timeval *ms_100, *ms_200; + + ms_100 = event_base_init_common_timeout(base, &tmp_100_ms); + ms_200 = event_base_init_common_timeout(base, &tmp_200_ms); + tt_assert(ms_100); + tt_assert(ms_200); + tt_ptr_op(event_base_init_common_timeout(base, &tmp_200_ms), + ==, ms_200); + tt_int_op(ms_100->tv_sec, ==, 0); + tt_int_op(ms_200->tv_sec, ==, 0); + tt_int_op(ms_100->tv_usec, ==, 100000|0x50000000); + tt_int_op(ms_200->tv_usec, ==, 200000|0x50100000); + + memset(info, 0, sizeof(info)); + + for (i=0; i<100; ++i) { + info[i].which = i; + event_assign(&info[i].ev, base, -1, EV_TIMEOUT|EV_PERSIST, + common_timeout_cb, &info[i]); + if (i % 2) { + event_add(&info[i].ev, ms_100); + } else { + event_add(&info[i].ev, ms_200); + } + } + + event_base_assert_ok(base); + event_base_dispatch(base); + + evutil_gettimeofday(&now, NULL); + event_base_assert_ok(base); + + for (i=0; i<10; ++i) { + struct timeval tmp; + int ms_diff; + tt_int_op(info[i].count, ==, 6); + evutil_timersub(&now, &info[i].called_at, &tmp); + ms_diff = tmp.tv_usec/1000 + tmp.tv_sec*1000; + if (i % 2) { + tt_int_op(ms_diff, >, 500); + tt_int_op(ms_diff, <, 700); + } else { + tt_int_op(ms_diff, >, -100); + tt_int_op(ms_diff, <, 100); + } + } + + /* Make sure we can free the base with some events in. */ + for (i=0; i<100; ++i) { + if (i % 2) { + event_add(&info[i].ev, ms_100); + } else { + event_add(&info[i].ev, ms_200); + } + } + +end: + event_base_free(data->base); /* need to do this here before info is + * out-of-scope */ + data->base = NULL; +} + +#ifndef WIN32 +static void signal_cb(evutil_socket_t fd, short event, void *arg); + +#define current_base event_global_current_base_ +extern struct event_base *current_base; + +static void +child_signal_cb(evutil_socket_t fd, short event, void *arg) +{ + struct timeval tv; + int *pint = arg; + + *pint = 1; + + tv.tv_usec = 500000; + tv.tv_sec = 0; + event_loopexit(&tv); +} + +static void +test_fork(void) +{ + int status, got_sigchld = 0; + struct event ev, sig_ev; + pid_t pid; + + setup_test("After fork: "); + + tt_assert(current_base); + evthread_make_base_notifiable(current_base); + + if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + } + + event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); + if (event_add(&ev, NULL) == -1) + exit(1); + + evsignal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld); + evsignal_add(&sig_ev, NULL); + + event_base_assert_ok(current_base); + TT_BLATHER(("Before fork")); + if ((pid = fork()) == 0) { + /* in the child */ + TT_BLATHER(("In child, before reinit")); + event_base_assert_ok(current_base); + if (event_reinit(current_base) == -1) { + fprintf(stdout, "FAILED (reinit)\n"); + exit(1); + } + TT_BLATHER(("After reinit")); + event_base_assert_ok(current_base); + TT_BLATHER(("After assert-ok")); + + evsignal_del(&sig_ev); + + called = 0; + + event_dispatch(); + + event_base_free(current_base); + + /* we do not send an EOF; simple_read_cb requires an EOF + * to set test_ok. we just verify that the callback was + * called. */ + exit(test_ok != 0 || called != 2 ? -2 : 76); + } + + /* wait for the child to read the data */ + sleep(1); + + if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + } + + TT_BLATHER(("Before waitpid")); + if (waitpid(pid, &status, 0) == -1) { + fprintf(stdout, "FAILED (fork)\n"); + exit(1); + } + TT_BLATHER(("After waitpid")); + + if (WEXITSTATUS(status) != 76) { + fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status)); + exit(1); + } + + /* test that the current event loop still works */ + if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { + fprintf(stderr, "%s: write\n", __func__); + } + + shutdown(pair[0], SHUT_WR); + + event_dispatch(); + + if (!got_sigchld) { + fprintf(stdout, "FAILED (sigchld)\n"); + exit(1); + } + + evsignal_del(&sig_ev); + + end: + cleanup_test(); +} + +static void +signal_cb_sa(int sig) +{ + test_ok = 2; +} + +static void +signal_cb(evutil_socket_t fd, short event, void *arg) +{ + struct event *ev = arg; + + evsignal_del(ev); + test_ok = 1; +} + +static void +test_simplesignal(void) +{ + struct event ev; + struct itimerval itv; + + setup_test("Simple signal: "); + evsignal_set(&ev, SIGALRM, signal_cb, &ev); + evsignal_add(&ev, NULL); + /* find bugs in which operations are re-ordered */ + evsignal_del(&ev); + evsignal_add(&ev, NULL); + + memset(&itv, 0, sizeof(itv)); + itv.it_value.tv_sec = 1; + if (setitimer(ITIMER_REAL, &itv, NULL) == -1) + goto skip_simplesignal; + + event_dispatch(); + skip_simplesignal: + if (evsignal_del(&ev) == -1) + test_ok = 0; + + cleanup_test(); +} + +static void +test_multiplesignal(void) +{ + struct event ev_one, ev_two; + struct itimerval itv; + + setup_test("Multiple signal: "); + + evsignal_set(&ev_one, SIGALRM, signal_cb, &ev_one); + evsignal_add(&ev_one, NULL); + + evsignal_set(&ev_two, SIGALRM, signal_cb, &ev_two); + evsignal_add(&ev_two, NULL); + + memset(&itv, 0, sizeof(itv)); + itv.it_value.tv_sec = 1; + if (setitimer(ITIMER_REAL, &itv, NULL) == -1) + goto skip_simplesignal; + + event_dispatch(); + + skip_simplesignal: + if (evsignal_del(&ev_one) == -1) + test_ok = 0; + if (evsignal_del(&ev_two) == -1) + test_ok = 0; + + cleanup_test(); +} + +static void +test_immediatesignal(void) +{ + struct event ev; + + test_ok = 0; + evsignal_set(&ev, SIGUSR1, signal_cb, &ev); + evsignal_add(&ev, NULL); + raise(SIGUSR1); + event_loop(EVLOOP_NONBLOCK); + evsignal_del(&ev); + cleanup_test(); +} + +static void +test_signal_dealloc(void) +{ + /* make sure that evsignal_event is event_del'ed and pipe closed */ + struct event ev; + struct event_base *base = event_init(); + evsignal_set(&ev, SIGUSR1, signal_cb, &ev); + evsignal_add(&ev, NULL); + evsignal_del(&ev); + event_base_free(base); + /* If we got here without asserting, we're fine. */ + test_ok = 1; + cleanup_test(); +} + +static void +test_signal_pipeloss(void) +{ + /* make sure that the base1 pipe is closed correctly. */ + struct event_base *base1, *base2; + int pipe1; + test_ok = 0; + base1 = event_init(); + pipe1 = base1->sig.ev_signal_pair[0]; + base2 = event_init(); + event_base_free(base2); + event_base_free(base1); + if (close(pipe1) != -1 || errno!=EBADF) { + /* fd must be closed, so second close gives -1, EBADF */ + printf("signal pipe not closed. "); + test_ok = 0; + } else { + test_ok = 1; + } + cleanup_test(); +} + +/* + * make two bases to catch signals, use both of them. this only works + * for event mechanisms that use our signal pipe trick. kqueue handles + * signals internally, and all interested kqueues get all the signals. + */ +static void +test_signal_switchbase(void) +{ + struct event ev1, ev2; + struct event_base *base1, *base2; + int is_kqueue; + test_ok = 0; + base1 = event_init(); + base2 = event_init(); + is_kqueue = !strcmp(event_get_method(),"kqueue"); + evsignal_set(&ev1, SIGUSR1, signal_cb, &ev1); + evsignal_set(&ev2, SIGUSR1, signal_cb, &ev2); + if (event_base_set(base1, &ev1) || + event_base_set(base2, &ev2) || + event_add(&ev1, NULL) || + event_add(&ev2, NULL)) { + fprintf(stderr, "%s: cannot set base, add\n", __func__); + exit(1); + } + + tt_ptr_op(event_get_base(&ev1), ==, base1); + tt_ptr_op(event_get_base(&ev2), ==, base2); + + test_ok = 0; + /* can handle signal before loop is called */ + raise(SIGUSR1); + event_base_loop(base2, EVLOOP_NONBLOCK); + if (is_kqueue) { + if (!test_ok) + goto end; + test_ok = 0; + } + event_base_loop(base1, EVLOOP_NONBLOCK); + if (test_ok && !is_kqueue) { + test_ok = 0; + + /* set base1 to handle signals */ + event_base_loop(base1, EVLOOP_NONBLOCK); + raise(SIGUSR1); + event_base_loop(base1, EVLOOP_NONBLOCK); + event_base_loop(base2, EVLOOP_NONBLOCK); + } +end: + event_base_free(base1); + event_base_free(base2); + cleanup_test(); +} + +/* + * assert that a signal event removed from the event queue really is + * removed - with no possibility of it's parent handler being fired. + */ +static void +test_signal_assert(void) +{ + struct event ev; + struct event_base *base = event_init(); + test_ok = 0; + /* use SIGCONT so we don't kill ourselves when we signal to nowhere */ + evsignal_set(&ev, SIGCONT, signal_cb, &ev); + evsignal_add(&ev, NULL); + /* + * if evsignal_del() fails to reset the handler, it's current handler + * will still point to evsig_handler(). + */ + evsignal_del(&ev); + + raise(SIGCONT); +#if 0 + /* only way to verify we were in evsig_handler() */ + /* XXXX Now there's no longer a good way. */ + if (base->sig.evsig_caught) + test_ok = 0; + else + test_ok = 1; +#else + test_ok = 1; +#endif + + event_base_free(base); + cleanup_test(); + return; +} + +/* + * assert that we restore our previous signal handler properly. + */ +static void +test_signal_restore(void) +{ + struct event ev; + struct event_base *base = event_init(); +#ifdef _EVENT_HAVE_SIGACTION + struct sigaction sa; +#endif + + test_ok = 0; +#ifdef _EVENT_HAVE_SIGACTION + sa.sa_handler = signal_cb_sa; + sa.sa_flags = 0x0; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGUSR1, &sa, NULL) == -1) + goto out; +#else + if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR) + goto out; +#endif + evsignal_set(&ev, SIGUSR1, signal_cb, &ev); + evsignal_add(&ev, NULL); + evsignal_del(&ev); + + raise(SIGUSR1); + /* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */ + if (test_ok != 2) + test_ok = 0; +out: + event_base_free(base); + cleanup_test(); + return; +} + +static void +signal_cb_swp(int sig, short event, void *arg) +{ + called++; + if (called < 5) + raise(sig); + else + event_loopexit(NULL); +} +static void +timeout_cb_swp(evutil_socket_t fd, short event, void *arg) +{ + if (called == -1) { + struct timeval tv = {5, 0}; + + called = 0; + evtimer_add((struct event *)arg, &tv); + raise(SIGUSR1); + return; + } + test_ok = 0; + event_loopexit(NULL); +} + +static void +test_signal_while_processing(void) +{ + struct event_base *base = event_init(); + struct event ev, ev_timer; + struct timeval tv = {0, 0}; + + setup_test("Receiving a signal while processing other signal: "); + + called = -1; + test_ok = 1; + signal_set(&ev, SIGUSR1, signal_cb_swp, NULL); + signal_add(&ev, NULL); + evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer); + evtimer_add(&ev_timer, &tv); + event_dispatch(); + + event_base_free(base); + cleanup_test(); + return; +} +#endif + +static void +test_free_active_base(void *ptr) +{ + struct basic_test_data *data = ptr; + struct event_base *base1; + struct event ev1; + + base1 = event_init(); + if (base1) { + event_assign(&ev1, base1, data->pair[1], EV_READ, + dummy_read_cb, NULL); + event_add(&ev1, NULL); + event_base_free(base1); /* should not crash */ + } else { + tt_fail_msg("failed to create event_base for test"); + } + + base1 = event_init(); + tt_assert(base1); + event_assign(&ev1, base1, 0, 0, dummy_read_cb, NULL); + event_active(&ev1, EV_READ, 1); + event_base_free(base1); +end: + ; +} + +static void +test_manipulate_active_events(void *ptr) +{ + struct basic_test_data *data = ptr; + struct event_base *base = data->base; + struct event ev1; + + event_assign(&ev1, base, -1, EV_TIMEOUT, dummy_read_cb, NULL); + + /* Make sure an active event is pending. */ + event_active(&ev1, EV_READ, 1); + tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), + ==, EV_READ); + + /* Make sure that activating an event twice works. */ + event_active(&ev1, EV_WRITE, 1); + tt_int_op(event_pending(&ev1, EV_READ|EV_TIMEOUT|EV_WRITE, NULL), + ==, EV_READ|EV_WRITE); + +end: + event_del(&ev1); +} + +static void +test_bad_assign(void *ptr) +{ + struct event ev; + int r; + /* READ|SIGNAL is not allowed */ + r = event_assign(&ev, NULL, -1, EV_SIGNAL|EV_READ, dummy_read_cb, NULL); + tt_int_op(r,==,-1); + +end: + ; +} + +static int reentrant_cb_run = 0; + +static void +bad_reentrant_run_loop_cb(evutil_socket_t fd, short what, void *ptr) +{ + struct event_base *base = ptr; + int r; + reentrant_cb_run = 1; + /* This reentrant call to event_base_loop should be detected and + * should fail */ + r = event_base_loop(base, 0); + tt_int_op(r, ==, -1); +end: + ; +} + +static void +test_bad_reentrant(void *ptr) +{ + struct basic_test_data *data = ptr; + struct event_base *base = data->base; + struct event ev; + int r; + event_assign(&ev, base, -1, + 0, bad_reentrant_run_loop_cb, base); + + event_active(&ev, EV_WRITE, 1); + r = event_base_loop(base, 0); + tt_int_op(r, ==, 1); + tt_int_op(reentrant_cb_run, ==, 1); +end: + ; +} + +static void +test_event_base_new(void *ptr) +{ + struct basic_test_data *data = ptr; + struct event_base *base = 0; + struct event ev1; + struct basic_cb_args args; + + int towrite = (int)strlen(TEST1)+1; + int len = write(data->pair[0], TEST1, towrite); + + if (len < 0) + tt_abort_perror("initial write"); + else if (len != towrite) + tt_abort_printf(("initial write fell short (%d of %d bytes)", + len, towrite)); + + if (shutdown(data->pair[0], SHUT_WR)) + tt_abort_perror("initial write shutdown"); + + base = event_base_new(); + if (!base) + tt_abort_msg("failed to create event base"); + + args.eb = base; + args.ev = &ev1; + args.callcount = 0; + event_assign(&ev1, base, data->pair[1], + EV_READ|EV_PERSIST, basic_read_cb, &args); + + if (event_add(&ev1, NULL)) + tt_abort_perror("initial event_add"); + + if (event_base_loop(base, 0)) + tt_abort_msg("unsuccessful exit from event loop"); + +end: + if (base) + event_base_free(base); +} + +static void +test_loopexit(void) +{ + struct timeval tv, tv_start, tv_end; + struct event ev; + + setup_test("Loop exit: "); + + tv.tv_usec = 0; + tv.tv_sec = 60*60*24; + evtimer_set(&ev, timeout_cb, NULL); + evtimer_add(&ev, &tv); + + tv.tv_usec = 0; + tv.tv_sec = 1; + event_loopexit(&tv); + + evutil_gettimeofday(&tv_start, NULL); + event_dispatch(); + evutil_gettimeofday(&tv_end, NULL); + evutil_timersub(&tv_end, &tv_start, &tv_end); + + evtimer_del(&ev); + + tt_assert(event_base_got_exit(global_base)); + tt_assert(!event_base_got_break(global_base)); + + if (tv.tv_sec < 2) + test_ok = 1; + +end: + cleanup_test(); +} + +static void +test_loopexit_multiple(void) +{ + struct timeval tv; + struct event_base *base; + + setup_test("Loop Multiple exit: "); + + base = event_base_new(); + + tv.tv_usec = 0; + tv.tv_sec = 1; + event_base_loopexit(base, &tv); + + tv.tv_usec = 0; + tv.tv_sec = 2; + event_base_loopexit(base, &tv); + + event_base_dispatch(base); + + tt_assert(event_base_got_exit(base)); + tt_assert(!event_base_got_break(base)); + + event_base_free(base); + + test_ok = 1; + +end: + cleanup_test(); +} + +static void +break_cb(evutil_socket_t fd, short events, void *arg) +{ + test_ok = 1; + event_loopbreak(); +} + +static void +fail_cb(evutil_socket_t fd, short events, void *arg) +{ + test_ok = 0; +} + +static void +test_loopbreak(void) +{ + struct event ev1, ev2; + struct timeval tv; + + setup_test("Loop break: "); + + tv.tv_sec = 0; + tv.tv_usec = 0; + evtimer_set(&ev1, break_cb, NULL); + evtimer_add(&ev1, &tv); + evtimer_set(&ev2, fail_cb, NULL); + evtimer_add(&ev2, &tv); + + event_dispatch(); + + tt_assert(!event_base_got_exit(global_base)); + tt_assert(event_base_got_break(global_base)); + + evtimer_del(&ev1); + evtimer_del(&ev2); + +end: + cleanup_test(); +} + +static struct event *readd_test_event_last_added = NULL; +static void +re_add_read_cb(evutil_socket_t fd, short event, void *arg) +{ + char buf[256]; + struct event *ev_other = arg; + readd_test_event_last_added = ev_other; + + if (read(fd, buf, sizeof(buf)) < 0) { + tt_fail_perror("read"); + } + + event_add(ev_other, NULL); + ++test_ok; +} + +static void +test_nonpersist_readd(void) +{ + struct event ev1, ev2; + + setup_test("Re-add nonpersistent events: "); + event_set(&ev1, pair[0], EV_READ, re_add_read_cb, &ev2); + event_set(&ev2, pair[1], EV_READ, re_add_read_cb, &ev1); + + if (write(pair[0], "Hello", 5) < 0) { + tt_fail_perror("write(pair[0])"); + } + + if (write(pair[1], "Hello", 5) < 0) { + tt_fail_perror("write(pair[1])\n"); + } + + if (event_add(&ev1, NULL) == -1 || + event_add(&ev2, NULL) == -1) { + test_ok = 0; + } + if (test_ok != 0) + exit(1); + event_loop(EVLOOP_ONCE); + if (test_ok != 2) + exit(1); + /* At this point, we executed both callbacks. Whichever one got + * called first added the second, but the second then immediately got + * deleted before its callback was called. At this point, though, it + * re-added the first. + */ + if (!readd_test_event_last_added) { + test_ok = 0; + } else if (readd_test_event_last_added == &ev1) { + if (!event_pending(&ev1, EV_READ, NULL) || + event_pending(&ev2, EV_READ, NULL)) + test_ok = 0; + } else { + if (event_pending(&ev1, EV_READ, NULL) || + !event_pending(&ev2, EV_READ, NULL)) + test_ok = 0; + } + + event_del(&ev1); + event_del(&ev2); + + cleanup_test(); +} + +struct test_pri_event { + struct event ev; + int count; +}; + +static void +test_priorities_cb(evutil_socket_t fd, short what, void *arg) +{ + struct test_pri_event *pri = arg; + struct timeval tv; + + if (pri->count == 3) { + event_loopexit(NULL); + return; + } + + pri->count++; + + evutil_timerclear(&tv); + event_add(&pri->ev, &tv); +} + +static void +test_priorities_impl(int npriorities) +{ + struct test_pri_event one, two; + struct timeval tv; + + TT_BLATHER(("Testing Priorities %d: ", npriorities)); + + event_base_priority_init(global_base, npriorities); + + memset(&one, 0, sizeof(one)); + memset(&two, 0, sizeof(two)); + + timeout_set(&one.ev, test_priorities_cb, &one); + if (event_priority_set(&one.ev, 0) == -1) { + fprintf(stderr, "%s: failed to set priority", __func__); + exit(1); + } + + timeout_set(&two.ev, test_priorities_cb, &two); + if (event_priority_set(&two.ev, npriorities - 1) == -1) { + fprintf(stderr, "%s: failed to set priority", __func__); + exit(1); + } + + evutil_timerclear(&tv); + + if (event_add(&one.ev, &tv) == -1) + exit(1); + if (event_add(&two.ev, &tv) == -1) + exit(1); + + event_dispatch(); + + event_del(&one.ev); + event_del(&two.ev); + + if (npriorities == 1) { + if (one.count == 3 && two.count == 3) + test_ok = 1; + } else if (npriorities == 2) { + /* Two is called once because event_loopexit is priority 1 */ + if (one.count == 3 && two.count == 1) + test_ok = 1; + } else { + if (one.count == 3 && two.count == 0) + test_ok = 1; + } +} + +static void +test_priorities(void) +{ + test_priorities_impl(1); + if (test_ok) + test_priorities_impl(2); + if (test_ok) + test_priorities_impl(3); +} + + +static void +test_multiple_cb(evutil_socket_t fd, short event, void *arg) +{ + if (event & EV_READ) + test_ok |= 1; + else if (event & EV_WRITE) + test_ok |= 2; +} + +static void +test_multiple_events_for_same_fd(void) +{ + struct event e1, e2; + + setup_test("Multiple events for same fd: "); + + event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL); + event_add(&e1, NULL); + event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL); + event_add(&e2, NULL); + event_loop(EVLOOP_ONCE); + event_del(&e2); + + if (write(pair[1], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + } + + event_loop(EVLOOP_ONCE); + event_del(&e1); + + if (test_ok != 3) + test_ok = 0; + + cleanup_test(); +} + +int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf); +int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf); +int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t number); +int evtag_decode_tag(ev_uint32_t *pnumber, struct evbuffer *evbuf); + +static void +read_once_cb(evutil_socket_t fd, short event, void *arg) +{ + char buf[256]; + int len; + + len = read(fd, buf, sizeof(buf)); + + if (called) { + test_ok = 0; + } else if (len) { + /* Assumes global pair[0] can be used for writing */ + if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + test_ok = 0; + } else { + test_ok = 1; + } + } + + called++; +} + +static void +test_want_only_once(void) +{ + struct event ev; + struct timeval tv; + + /* Very simple read test */ + setup_test("Want read only once: "); + + if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + } + + /* Setup the loop termination */ + evutil_timerclear(&tv); + tv.tv_sec = 1; + event_loopexit(&tv); + + event_set(&ev, pair[1], EV_READ, read_once_cb, &ev); + if (event_add(&ev, NULL) == -1) + exit(1); + event_dispatch(); + + cleanup_test(); +} + +#define TEST_MAX_INT 6 + +static void +evtag_int_test(void *ptr) +{ + struct evbuffer *tmp = evbuffer_new(); + ev_uint32_t integers[TEST_MAX_INT] = { + 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 + }; + ev_uint32_t integer; + ev_uint64_t big_int; + int i; + + evtag_init(); + + for (i = 0; i < TEST_MAX_INT; i++) { + int oldlen, newlen; + oldlen = (int)EVBUFFER_LENGTH(tmp); + evtag_encode_int(tmp, integers[i]); + newlen = (int)EVBUFFER_LENGTH(tmp); + TT_BLATHER(("encoded 0x%08x with %d bytes", + (unsigned)integers[i], newlen - oldlen)); + big_int = integers[i]; + big_int *= 1000000000; /* 1 billion */ + evtag_encode_int64(tmp, big_int); + } + + for (i = 0; i < TEST_MAX_INT; i++) { + tt_int_op(evtag_decode_int(&integer, tmp), !=, -1); + tt_uint_op(integer, ==, integers[i]); + tt_int_op(evtag_decode_int64(&big_int, tmp), !=, -1); + tt_assert((big_int / 1000000000) == integers[i]); + } + + tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); +end: + evbuffer_free(tmp); +} + +static void +evtag_fuzz(void *ptr) +{ + u_char buffer[4096]; + struct evbuffer *tmp = evbuffer_new(); + struct timeval tv; + int i, j; + + int not_failed = 0; + + evtag_init(); + + for (j = 0; j < 100; j++) { + for (i = 0; i < (int)sizeof(buffer); i++) + buffer[i] = rand(); + evbuffer_drain(tmp, -1); + evbuffer_add(tmp, buffer, sizeof(buffer)); + + if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) + not_failed++; + } + + /* The majority of decodes should fail */ + tt_int_op(not_failed, <, 10); + + /* Now insert some corruption into the tag length field */ + evbuffer_drain(tmp, -1); + evutil_timerclear(&tv); + tv.tv_sec = 1; + evtag_marshal_timeval(tmp, 0, &tv); + evbuffer_add(tmp, buffer, sizeof(buffer)); + + ((char *)EVBUFFER_DATA(tmp))[1] = '\xff'; + if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) { + tt_abort_msg("evtag_unmarshal_timeval should have failed"); + } + +end: + evbuffer_free(tmp); +} + +static void +evtag_tag_encoding(void *ptr) +{ + struct evbuffer *tmp = evbuffer_new(); + ev_uint32_t integers[TEST_MAX_INT] = { + 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 + }; + ev_uint32_t integer; + int i; + + evtag_init(); + + for (i = 0; i < TEST_MAX_INT; i++) { + int oldlen, newlen; + oldlen = (int)EVBUFFER_LENGTH(tmp); + evtag_encode_tag(tmp, integers[i]); + newlen = (int)EVBUFFER_LENGTH(tmp); + TT_BLATHER(("encoded 0x%08x with %d bytes", + (unsigned)integers[i], newlen - oldlen)); + } + + for (i = 0; i < TEST_MAX_INT; i++) { + tt_int_op(evtag_decode_tag(&integer, tmp), !=, -1); + tt_uint_op(integer, ==, integers[i]); + } + + tt_uint_op(EVBUFFER_LENGTH(tmp), ==, 0); + +end: + evbuffer_free(tmp); +} + +static void +evtag_test_peek(void *ptr) +{ + struct evbuffer *tmp = evbuffer_new(); + ev_uint32_t u32; + + evtag_marshal_int(tmp, 30, 0); + evtag_marshal_string(tmp, 40, "Hello world"); + + tt_int_op(evtag_peek(tmp, &u32), ==, 1); + tt_int_op(u32, ==, 30); + tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); + tt_int_op(u32, ==, 1+1+1); + tt_int_op(evtag_consume(tmp), ==, 0); + + tt_int_op(evtag_peek(tmp, &u32), ==, 1); + tt_int_op(u32, ==, 40); + tt_int_op(evtag_peek_length(tmp, &u32), ==, 0); + tt_int_op(u32, ==, 1+1+11); + tt_int_op(evtag_payload_length(tmp, &u32), ==, 0); + tt_int_op(u32, ==, 11); + +end: + evbuffer_free(tmp); +} + + +static void +test_methods(void *ptr) +{ + const char **methods = event_get_supported_methods(); + struct event_config *cfg = NULL; + struct event_base *base = NULL; + const char *backend; + int n_methods = 0; + + tt_assert(methods); + + backend = methods[0]; + while (*methods != NULL) { + TT_BLATHER(("Support method: %s", *methods)); + ++methods; + ++n_methods; + } + + cfg = event_config_new(); + assert(cfg != NULL); + + tt_int_op(event_config_avoid_method(cfg, backend), ==, 0); + event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); + + base = event_base_new_with_config(cfg); + if (n_methods > 1) { + tt_assert(base); + tt_str_op(backend, !=, event_base_get_method(base)); + } else { + tt_assert(base == NULL); + } + +end: + if (base) + event_base_free(base); + if (cfg) + event_config_free(cfg); +} + +static void +test_version(void *arg) +{ + const char *vstr; + ev_uint32_t vint; + int major, minor, patch, n; + + vstr = event_get_version(); + vint = event_get_version_number(); + + tt_assert(vstr); + tt_assert(vint); + + tt_str_op(vstr, ==, LIBEVENT_VERSION); + tt_int_op(vint, ==, LIBEVENT_VERSION_NUMBER); + + n = sscanf(vstr, "%d.%d.%d", &major, &minor, &patch); + tt_assert(3 == n); + tt_int_op((vint&0xffffff00), ==, ((major<<24)|(minor<<16)|(patch<<8))); +end: + ; +} + +static void +test_base_features(void *arg) +{ + struct event_base *base = NULL; + struct event_config *cfg = NULL; + + cfg = event_config_new(); + + tt_assert(0 == event_config_require_features(cfg, EV_FEATURE_ET)); + + base = event_base_new_with_config(cfg); + if (base) { + tt_int_op(EV_FEATURE_ET, ==, + event_base_get_features(base) & EV_FEATURE_ET); + } else { + base = event_base_new(); + tt_int_op(0, ==, event_base_get_features(base) & EV_FEATURE_ET); + } + +end: + if (base) + event_base_free(base); + if (cfg) + event_config_free(cfg); +} + +#ifdef _EVENT_HAVE_SETENV +#define SETENV_OK +#elif !defined(_EVENT_HAVE_SETENV) && defined(_EVENT_HAVE_PUTENV) +static void setenv(const char *k, const char *v, int _o) +{ + char b[256]; + evutil_snprintf(b, sizeof(b), "%s=%s",k,v); + putenv(b); +} +#define SETENV_OK +#endif + +#ifdef _EVENT_HAVE_UNSETENV +#define UNSETENV_OK +#elif !defined(_EVENT_HAVE_UNSETENV) && defined(_EVENT_HAVE_PUTENV) +static void unsetenv(const char *k) +{ + char b[256]; + evutil_snprintf(b, sizeof(b), "%s=",k); + putenv(b); +} +#define UNSETENV_OK +#endif + +#if defined(SETENV_OK) && defined(UNSETENV_OK) +static void +methodname_to_envvar(const char *mname, char *buf, size_t buflen) +{ + char *cp; + evutil_snprintf(buf, buflen, "EVENT_NO%s", mname); + for (cp = buf; *cp; ++cp) { + *cp = EVUTIL_TOUPPER(*cp); + } +} +#endif + +static void +test_base_environ(void *arg) +{ + struct event_base *base = NULL; + struct event_config *cfg = NULL; + +#if defined(SETENV_OK) && defined(UNSETENV_OK) + const char **basenames; + int i, n_methods=0; + char varbuf[128]; + const char *defaultname, *ignoreenvname; + + /* See if unsetenv works before we rely on it. */ + setenv("EVENT_NOWAFFLES", "1", 1); + unsetenv("EVENT_NOWAFFLES"); + if (getenv("EVENT_NOWAFFLES") != NULL) { +#ifndef _EVENT_HAVE_UNSETENV + TT_DECLARE("NOTE", ("Can't fake unsetenv; skipping test")); +#else + TT_DECLARE("NOTE", ("unsetenv doesn't work; skipping test")); +#endif + tt_skip(); + } + + basenames = event_get_supported_methods(); + for (i = 0; basenames[i]; ++i) { + methodname_to_envvar(basenames[i], varbuf, sizeof(varbuf)); + unsetenv(varbuf); + ++n_methods; + } + + base = event_base_new(); + tt_assert(base); + + defaultname = event_base_get_method(base); + TT_BLATHER(("default is <%s>", defaultname)); + event_base_free(base); + base = NULL; + + /* Can we disable the method with EVENT_NOfoo ? */ + if (!strcmp(defaultname, "epoll (with changelist)")) { + setenv("EVENT_NOEPOLL", "1", 1); + ignoreenvname = "epoll"; + } else { + methodname_to_envvar(defaultname, varbuf, sizeof(varbuf)); + setenv(varbuf, "1", 1); + ignoreenvname = defaultname; + } + + /* Use an empty cfg rather than NULL so a failure doesn't exit() */ + cfg = event_config_new(); + base = event_base_new_with_config(cfg); + event_config_free(cfg); + cfg = NULL; + if (n_methods == 1) { + tt_assert(!base); + } else { + tt_assert(base); + tt_str_op(defaultname, !=, event_base_get_method(base)); + event_base_free(base); + base = NULL; + } + + /* Can we disable looking at the environment with IGNORE_ENV ? */ + cfg = event_config_new(); + event_config_set_flag(cfg, EVENT_BASE_FLAG_IGNORE_ENV); + base = event_base_new_with_config(cfg); + tt_assert(base); + tt_str_op(ignoreenvname, ==, event_base_get_method(base)); +#else + tt_skip(); +#endif + +end: + if (base) + event_base_free(base); + if (cfg) + event_config_free(cfg); +} + +static void +read_called_once_cb(evutil_socket_t fd, short event, void *arg) +{ + tt_int_op(event, ==, EV_READ); + called += 1; +end: + ; +} + +static void +timeout_called_once_cb(evutil_socket_t fd, short event, void *arg) +{ + tt_int_op(event, ==, EV_TIMEOUT); + called += 100; +end: + ; +} + +static void +test_event_once(void *ptr) +{ + struct basic_test_data *data = ptr; + struct timeval tv; + int r; + + tv.tv_sec = 0; + tv.tv_usec = 50*1000; + called = 0; + r = event_base_once(data->base, data->pair[0], EV_READ, + read_called_once_cb, NULL, NULL); + tt_int_op(r, ==, 0); + r = event_base_once(data->base, -1, EV_TIMEOUT, + timeout_called_once_cb, NULL, &tv); + tt_int_op(r, ==, 0); + r = event_base_once(data->base, -1, 0, NULL, NULL, NULL); + tt_int_op(r, <, 0); + + if (write(data->pair[1], TEST1, strlen(TEST1)+1) < 0) { + tt_fail_perror("write"); + } + + shutdown(data->pair[1], SHUT_WR); + + event_base_dispatch(data->base); + + tt_int_op(called, ==, 101); +end: + ; +} + +static void +test_event_pending(void *ptr) +{ + struct basic_test_data *data = ptr; + struct event *r=NULL, *w=NULL, *t=NULL; + struct timeval tv, now, tv2, diff; + + tv.tv_sec = 0; + tv.tv_usec = 500 * 1000; + r = event_new(data->base, data->pair[0], EV_READ, simple_read_cb, + NULL); + w = event_new(data->base, data->pair[1], EV_WRITE, simple_write_cb, + NULL); + t = evtimer_new(data->base, timeout_cb, NULL); + + evutil_gettimeofday(&now, NULL); + event_add(r, NULL); + event_add(t, &tv); + + tt_assert( event_pending(r, EV_READ, NULL)); + tt_assert(!event_pending(w, EV_WRITE, NULL)); + tt_assert(!event_pending(r, EV_WRITE, NULL)); + tt_assert( event_pending(r, EV_READ|EV_WRITE, NULL)); + tt_assert(!event_pending(r, EV_TIMEOUT, NULL)); + tt_assert( event_pending(t, EV_TIMEOUT, NULL)); + tt_assert( event_pending(t, EV_TIMEOUT, &tv2)); + + tt_assert(evutil_timercmp(&tv2, &now, >)); + evutil_timeradd(&now, &tv, &tv); + evutil_timersub(&tv2, &tv, &diff); + tt_int_op(diff.tv_sec, ==, 0); + tt_int_op(labs(diff.tv_usec), <, 1000); + +end: + if (r) { + event_del(r); + event_free(r); + } + if (w) { + event_del(w); + event_free(w); + } + if (t) { + event_del(t); + event_free(t); + } +} + +#ifndef WIN32 +/* You can't do this test on windows, since dup2 doesn't work on sockets */ + +static void +dfd_cb(evutil_socket_t fd, short e, void *data) +{ + *(int*)data = (int)e; +} + +/* Regression test for our workaround for a fun epoll/linux related bug + * where fd2 = dup(fd1); add(fd2); close(fd2); dup2(fd1,fd2); add(fd2) + * will get you an EEXIST */ +static void +test_dup_fd(void *arg) +{ + struct basic_test_data *data = arg; + struct event_base *base = data->base; + struct event *ev1=NULL, *ev2=NULL; + int fd, dfd=-1; + int ev1_got, ev2_got; + + tt_int_op(write(data->pair[0], "Hello world", + strlen("Hello world")), >, 0); + fd = data->pair[1]; + + dfd = dup(fd); + tt_int_op(dfd, >=, 0); + + ev1 = event_new(base, fd, EV_READ|EV_PERSIST, dfd_cb, &ev1_got); + ev2 = event_new(base, dfd, EV_READ|EV_PERSIST, dfd_cb, &ev2_got); + ev1_got = ev2_got = 0; + event_add(ev1, NULL); + event_add(ev2, NULL); + event_base_loop(base, EVLOOP_ONCE); + tt_int_op(ev1_got, ==, EV_READ); + tt_int_op(ev2_got, ==, EV_READ); + + /* Now close and delete dfd then dispatch. We need to do the + * dispatch here so that when we add it later, we think there + * was an intermediate delete. */ + close(dfd); + event_del(ev2); + ev1_got = ev2_got = 0; + event_base_loop(base, EVLOOP_ONCE); + tt_want_int_op(ev1_got, ==, EV_READ); + tt_int_op(ev2_got, ==, 0); + + /* Re-duplicate the fd. We need to get the same duplicated + * value that we closed to provoke the epoll quirk. Also, we + * need to change the events to write, or else the old lingering + * read event will make the test pass whether the change was + * successful or not. */ + tt_int_op(dup2(fd, dfd), ==, dfd); + event_free(ev2); + ev2 = event_new(base, dfd, EV_WRITE|EV_PERSIST, dfd_cb, &ev2_got); + event_add(ev2, NULL); + ev1_got = ev2_got = 0; + event_base_loop(base, EVLOOP_ONCE); + tt_want_int_op(ev1_got, ==, EV_READ); + tt_int_op(ev2_got, ==, EV_WRITE); + +end: + if (ev1) + event_free(ev1); + if (ev2) + event_free(ev2); + close(dfd); +} +#endif + +#ifdef _EVENT_DISABLE_MM_REPLACEMENT +static void +test_mm_functions(void *arg) +{ + _tinytest_set_test_skipped(); +} +#else +static int +check_dummy_mem_ok(void *_mem) +{ + char *mem = _mem; + mem -= 16; + return !memcmp(mem, "{[]}", 16); +} + +static void * +dummy_malloc(size_t len) +{ + char *mem = malloc(len+16); + memcpy(mem, "{[]}", 16); + return mem+16; +} + +static void * +dummy_realloc(void *_mem, size_t len) +{ + char *mem = _mem; + if (!mem) + return dummy_malloc(len); + tt_want(check_dummy_mem_ok(_mem)); + mem -= 16; + mem = realloc(mem, len+16); + return mem+16; +} + +static void +dummy_free(void *_mem) +{ + char *mem = _mem; + tt_want(check_dummy_mem_ok(_mem)); + mem -= 16; + free(mem); +} + +static void +test_mm_functions(void *arg) +{ + struct event_base *b = NULL; + struct event_config *cfg = NULL; + event_set_mem_functions(dummy_malloc, dummy_realloc, dummy_free); + cfg = event_config_new(); + event_config_avoid_method(cfg, "Nonesuch"); + b = event_base_new_with_config(cfg); + tt_assert(b); + tt_assert(check_dummy_mem_ok(b)); +end: + if (cfg) + event_config_free(cfg); + if (b) + event_base_free(b); +} +#endif + +static void +many_event_cb(evutil_socket_t fd, short event, void *arg) +{ + int *calledp = arg; + *calledp += 1; +} + +static void +test_many_events(void *arg) +{ + /* Try 70 events that should all be ready at once. This will + * exercise the "resize" code on most of the backends, and will make + * sure that we can get past the 64-handle limit of some windows + * functions. */ +#define MANY 70 + + struct basic_test_data *data = arg; + struct event_base *base = data->base; + int one_at_a_time = data->setup_data != NULL; + evutil_socket_t sock[MANY]; + struct event *ev[MANY]; + int called[MANY]; + int i; + int loopflags = EVLOOP_NONBLOCK, evflags=0; + const int is_evport = !strcmp(event_base_get_method(base),"evport"); + if (one_at_a_time) { + loopflags |= EVLOOP_ONCE; + evflags = EV_PERSIST; + } + + memset(sock, 0xff, sizeof(sock)); + memset(ev, 0, sizeof(ev)); + memset(called, 0, sizeof(called)); + if (is_evport && one_at_a_time) { + TT_DECLARE("NOTE", ("evport can't pass this in 2.0; skipping\n")); + tt_skip(); + } + + for (i = 0; i < MANY; ++i) { + /* We need an event that will hit the backend, and that will + * be ready immediately. "Send a datagram" is an easy + * instance of that. */ + sock[i] = socket(AF_INET, SOCK_DGRAM, 0); + tt_assert(sock[i] >= 0); + called[i] = 0; + ev[i] = event_new(base, sock[i], EV_WRITE|evflags, + many_event_cb, &called[i]); + event_add(ev[i], NULL); + if (one_at_a_time) + event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE); + } + + event_base_loop(base, loopflags); + + for (i = 0; i < MANY; ++i) { + if (one_at_a_time) + tt_int_op(called[i], ==, MANY - i + 1); + else + tt_int_op(called[i], ==, 1); + } + +end: + for (i = 0; i < MANY; ++i) { + if (ev[i]) + event_free(ev[i]); + if (sock[i] >= 0) + evutil_closesocket(sock[i]); + } +#undef MANY +} + +static void +test_struct_event_size(void *arg) +{ + tt_int_op(event_get_struct_event_size(), <=, sizeof(struct event)); +end: + ; +} + +struct testcase_t main_testcases[] = { + /* Some converted-over tests */ + { "methods", test_methods, TT_FORK, NULL, NULL }, + { "version", test_version, 0, NULL, NULL }, + BASIC(base_features, TT_FORK|TT_NO_LOGS), + { "base_environ", test_base_environ, TT_FORK, NULL, NULL }, + + BASIC(event_base_new, TT_FORK|TT_NEED_SOCKETPAIR), + BASIC(free_active_base, TT_FORK|TT_NEED_SOCKETPAIR), + + BASIC(manipulate_active_events, TT_FORK|TT_NEED_BASE), + + BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), + BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS), + + /* These are still using the old API */ + LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE), + { "persistent_active_timeout", test_persistent_active_timeout, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + LEGACY(priorities, TT_FORK|TT_NEED_BASE), + { "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE, + &basic_setup, NULL }, + + /* These legacy tests may not all need all of these flags. */ + LEGACY(simpleread, TT_ISOLATED), + LEGACY(simpleread_multiple, TT_ISOLATED), + LEGACY(simplewrite, TT_ISOLATED), + { "simpleclose", test_simpleclose, TT_FORK, &basic_setup, + NULL }, + LEGACY(multiple, TT_ISOLATED), + LEGACY(persistent, TT_ISOLATED), + LEGACY(combined, TT_ISOLATED), + LEGACY(simpletimeout, TT_ISOLATED), + LEGACY(loopbreak, TT_ISOLATED), + LEGACY(loopexit, TT_ISOLATED), + LEGACY(loopexit_multiple, TT_ISOLATED), + LEGACY(nonpersist_readd, TT_ISOLATED), + LEGACY(multiple_events_for_same_fd, TT_ISOLATED), + LEGACY(want_only_once, TT_ISOLATED), + { "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL }, + { "event_pending", test_event_pending, TT_ISOLATED, &basic_setup, + NULL }, +#ifndef WIN32 + { "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL }, +#endif + { "mm_functions", test_mm_functions, TT_FORK, NULL, NULL }, + { "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL }, + { "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 }, + + { "struct_event_size", test_struct_event_size, 0, NULL, NULL }, + +#ifndef WIN32 + LEGACY(fork, TT_ISOLATED), +#endif + END_OF_TESTCASES +}; + +struct testcase_t evtag_testcases[] = { + { "int", evtag_int_test, TT_FORK, NULL, NULL }, + { "fuzz", evtag_fuzz, TT_FORK, NULL, NULL }, + { "encoding", evtag_tag_encoding, TT_FORK, NULL, NULL }, + { "peek", evtag_test_peek, 0, NULL, NULL }, + + END_OF_TESTCASES +}; + +struct testcase_t signal_testcases[] = { +#ifndef WIN32 + LEGACY(simplesignal, TT_ISOLATED), + LEGACY(multiplesignal, TT_ISOLATED), + LEGACY(immediatesignal, TT_ISOLATED), + LEGACY(signal_dealloc, TT_ISOLATED), + LEGACY(signal_pipeloss, TT_ISOLATED), + LEGACY(signal_switchbase, TT_ISOLATED|TT_NO_LOGS), + LEGACY(signal_restore, TT_ISOLATED), + LEGACY(signal_assert, TT_ISOLATED), + LEGACY(signal_while_processing, TT_ISOLATED), +#endif + END_OF_TESTCASES +}; + diff --git a/libevent/test/regress.gen.c b/libevent/test/regress.gen.c new file mode 100644 index 0000000..141f4f4 --- /dev/null +++ b/libevent/test/regress.gen.c @@ -0,0 +1,1225 @@ +/* + * Automatically generated from ./regress.rpc + * by event_rpcgen.py/0.1. DO NOT EDIT THIS FILE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _EVENT___func__ +#define __func__ _EVENT___func__ +#endif + + +#include "regress.gen.h" + +void event_warn(const char *fmt, ...); +void event_warnx(const char *fmt, ...); + + +/* + * Implementation of msg + */ + +static struct msg_access_ __msg_base = { + msg_from_name_assign, + msg_from_name_get, + msg_to_name_assign, + msg_to_name_get, + msg_attack_assign, + msg_attack_get, + msg_run_assign, + msg_run_get, + msg_run_add, +}; + +struct msg * +msg_new(void) +{ + return msg_new_with_arg(NULL); +} + +struct msg * +msg_new_with_arg(void *unused) +{ + struct msg *tmp; + if ((tmp = malloc(sizeof(struct msg))) == NULL) { + event_warn("%s: malloc", __func__); + return (NULL); + } + tmp->base = &__msg_base; + + tmp->from_name_data = NULL; + tmp->from_name_set = 0; + + tmp->to_name_data = NULL; + tmp->to_name_set = 0; + + tmp->attack_data = NULL; + tmp->attack_set = 0; + + tmp->run_data = NULL; + tmp->run_length = 0; + tmp->run_num_allocated = 0; + tmp->run_set = 0; + + return (tmp); +} + + + + +static int +msg_run_expand_to_hold_more(struct msg *msg) +{ + int tobe_allocated = msg->run_num_allocated; + struct run** new_data = NULL; + tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; + new_data = (struct run**) realloc(msg->run_data, + tobe_allocated * sizeof(struct run*)); + if (new_data == NULL) + return -1; + msg->run_data = new_data; + msg->run_num_allocated = tobe_allocated; + return 0;} + +struct run* +msg_run_add(struct msg *msg) +{ + if (++msg->run_length >= msg->run_num_allocated) { + if (msg_run_expand_to_hold_more(msg)<0) + goto error; + } + msg->run_data[msg->run_length - 1] = run_new(); + if (msg->run_data[msg->run_length - 1] == NULL) + goto error; + msg->run_set = 1; + return (msg->run_data[msg->run_length - 1]); +error: + --msg->run_length; + return (NULL); +} + +int +msg_from_name_assign(struct msg *msg, + const char * value) +{ + if (msg->from_name_data != NULL) + free(msg->from_name_data); + if ((msg->from_name_data = strdup(value)) == NULL) + return (-1); + msg->from_name_set = 1; + return (0); +} + +int +msg_to_name_assign(struct msg *msg, + const char * value) +{ + if (msg->to_name_data != NULL) + free(msg->to_name_data); + if ((msg->to_name_data = strdup(value)) == NULL) + return (-1); + msg->to_name_set = 1; + return (0); +} + +int +msg_attack_assign(struct msg *msg, + const struct kill* value) +{ + struct evbuffer *tmp = NULL; + if (msg->attack_set) { + kill_clear(msg->attack_data); + msg->attack_set = 0; + } else { + msg->attack_data = kill_new(); + if (msg->attack_data == NULL) { + event_warn("%s: kill_new()", __func__); + goto error; + } + } + if ((tmp = evbuffer_new()) == NULL) { + event_warn("%s: evbuffer_new()", __func__); + goto error; + } + kill_marshal(tmp, value); + if (kill_unmarshal(msg->attack_data, tmp) == -1) { + event_warnx("%s: kill_unmarshal", __func__); + goto error; + } + msg->attack_set = 1; + evbuffer_free(tmp); + return (0); + error: + if (tmp != NULL) + evbuffer_free(tmp); + if (msg->attack_data != NULL) { + kill_free(msg->attack_data); + msg->attack_data = NULL; + } + return (-1); +} + +int +msg_run_assign(struct msg *msg, int off, + const struct run* value) +{ + if (!msg->run_set || off < 0 || off >= msg->run_length) + return (-1); + + { + int had_error = 0; + struct evbuffer *tmp = NULL; + run_clear(msg->run_data[off]); + if ((tmp = evbuffer_new()) == NULL) { + event_warn("%s: evbuffer_new()", __func__); + had_error = 1; + goto done; + } + run_marshal(tmp, value); + if (run_unmarshal(msg->run_data[off], tmp) == -1) { + event_warnx("%s: run_unmarshal", __func__); + had_error = 1; + goto done; + } + done:if (tmp != NULL) + evbuffer_free(tmp); + if (had_error) { + run_clear(msg->run_data[off]); + return (-1); + } + } + return (0); +} + +int +msg_from_name_get(struct msg *msg, char * *value) +{ + if (msg->from_name_set != 1) + return (-1); + *value = msg->from_name_data; + return (0); +} + +int +msg_to_name_get(struct msg *msg, char * *value) +{ + if (msg->to_name_set != 1) + return (-1); + *value = msg->to_name_data; + return (0); +} + +int +msg_attack_get(struct msg *msg, struct kill* *value) +{ + if (msg->attack_set != 1) { + msg->attack_data = kill_new(); + if (msg->attack_data == NULL) + return (-1); + msg->attack_set = 1; + } + *value = msg->attack_data; + return (0); +} + +int +msg_run_get(struct msg *msg, int offset, + struct run* *value) +{ + if (!msg->run_set || offset < 0 || offset >= msg->run_length) + return (-1); + *value = msg->run_data[offset]; + return (0); +} + +void +msg_clear(struct msg *tmp) +{ + if (tmp->from_name_set == 1) { + free(tmp->from_name_data); + tmp->from_name_data = NULL; + tmp->from_name_set = 0; + } + if (tmp->to_name_set == 1) { + free(tmp->to_name_data); + tmp->to_name_data = NULL; + tmp->to_name_set = 0; + } + if (tmp->attack_set == 1) { + kill_free(tmp->attack_data); + tmp->attack_data = NULL; + tmp->attack_set = 0; + } + if (tmp->run_set == 1) { + int i; + for (i = 0; i < tmp->run_length; ++i) { + run_free(tmp->run_data[i]); + } + free(tmp->run_data); + tmp->run_data = NULL; + tmp->run_set = 0; + tmp->run_length = 0; + tmp->run_num_allocated = 0; + } +} + +void +msg_free(struct msg *tmp) +{ + if (tmp->from_name_data != NULL) + free (tmp->from_name_data); + if (tmp->to_name_data != NULL) + free (tmp->to_name_data); + if (tmp->attack_data != NULL) + kill_free(tmp->attack_data); + if (tmp->run_set == 1) { + int i; + for (i = 0; i < tmp->run_length; ++i) { + run_free(tmp->run_data[i]); + } + free(tmp->run_data); + tmp->run_data = NULL; + tmp->run_set = 0; + tmp->run_length = 0; + tmp->run_num_allocated = 0; + } + free(tmp->run_data); + free(tmp); +} + +void +msg_marshal(struct evbuffer *evbuf, const struct msg *tmp){ + evtag_marshal_string(evbuf, MSG_FROM_NAME, tmp->from_name_data); + evtag_marshal_string(evbuf, MSG_TO_NAME, tmp->to_name_data); + if (tmp->attack_set) { + evtag_marshal_kill(evbuf, MSG_ATTACK, tmp->attack_data); + } + if (tmp->run_set) { + { + int i; + for (i = 0; i < tmp->run_length; ++i) { + evtag_marshal_run(evbuf, MSG_RUN, tmp->run_data[i]); + } + } + } +} + +int +msg_unmarshal(struct msg *tmp, struct evbuffer *evbuf) +{ + ev_uint32_t tag; + while (evbuffer_get_length(evbuf) > 0) { + if (evtag_peek(evbuf, &tag) == -1) + return (-1); + switch (tag) { + + case MSG_FROM_NAME: + + if (tmp->from_name_set) + return (-1); + if (evtag_unmarshal_string(evbuf, MSG_FROM_NAME, &tmp->from_name_data) == -1) { + event_warnx("%s: failed to unmarshal from_name", __func__); + return (-1); + } + tmp->from_name_set = 1; + break; + + case MSG_TO_NAME: + + if (tmp->to_name_set) + return (-1); + if (evtag_unmarshal_string(evbuf, MSG_TO_NAME, &tmp->to_name_data) == -1) { + event_warnx("%s: failed to unmarshal to_name", __func__); + return (-1); + } + tmp->to_name_set = 1; + break; + + case MSG_ATTACK: + + if (tmp->attack_set) + return (-1); + tmp->attack_data = kill_new(); + if (tmp->attack_data == NULL) + return (-1); + if (evtag_unmarshal_kill(evbuf, MSG_ATTACK, tmp->attack_data) == -1) { + event_warnx("%s: failed to unmarshal attack", __func__); + return (-1); + } + tmp->attack_set = 1; + break; + + case MSG_RUN: + + if (tmp->run_length >= tmp->run_num_allocated && + msg_run_expand_to_hold_more(tmp) < 0) { + puts("HEY NOW"); + return (-1); + } + tmp->run_data[tmp->run_length] = run_new(); + if (tmp->run_data[tmp->run_length] == NULL) + return (-1); + if (evtag_unmarshal_run(evbuf, MSG_RUN, tmp->run_data[tmp->run_length]) == -1) { + event_warnx("%s: failed to unmarshal run", __func__); + return (-1); + } + ++tmp->run_length; + tmp->run_set = 1; + break; + + default: + return -1; + } + } + + if (msg_complete(tmp) == -1) + return (-1); + return (0); +} + +int +msg_complete(struct msg *msg) +{ + if (!msg->from_name_set) + return (-1); + if (!msg->to_name_set) + return (-1); + if (msg->attack_set && kill_complete(msg->attack_data) == -1) + return (-1); + { + int i; + for (i = 0; i < msg->run_length; ++i) { + if (msg->run_set && run_complete(msg->run_data[i]) == -1) + return (-1); + } + } + return (0); +} + +int +evtag_unmarshal_msg(struct evbuffer *evbuf, ev_uint32_t need_tag, struct msg *msg) +{ + ev_uint32_t tag; + int res = -1; + + struct evbuffer *tmp = evbuffer_new(); + + if (evtag_unmarshal(evbuf, &tag, tmp) == -1 || tag != need_tag) + goto error; + + if (msg_unmarshal(msg, tmp) == -1) + goto error; + + res = 0; + + error: + evbuffer_free(tmp); + return (res); +} + +void +evtag_marshal_msg(struct evbuffer *evbuf, ev_uint32_t tag, const struct msg *msg) +{ + struct evbuffer *_buf = evbuffer_new(); + assert(_buf != NULL); + msg_marshal(_buf, msg); + evtag_marshal_buffer(evbuf, tag, _buf); + evbuffer_free(_buf); +} + +/* + * Implementation of kill + */ + +static struct kill_access_ __kill_base = { + kill_weapon_assign, + kill_weapon_get, + kill_action_assign, + kill_action_get, + kill_how_often_assign, + kill_how_often_get, + kill_how_often_add, +}; + +struct kill * +kill_new(void) +{ + return kill_new_with_arg(NULL); +} + +struct kill * +kill_new_with_arg(void *unused) +{ + struct kill *tmp; + if ((tmp = malloc(sizeof(struct kill))) == NULL) { + event_warn("%s: malloc", __func__); + return (NULL); + } + tmp->base = &__kill_base; + + tmp->weapon_data = NULL; + tmp->weapon_set = 0; + + tmp->action_data = NULL; + tmp->action_set = 0; + + tmp->how_often_data = NULL; + tmp->how_often_length = 0; + tmp->how_often_num_allocated = 0; + tmp->how_often_set = 0; + + return (tmp); +} + + + +static int +kill_how_often_expand_to_hold_more(struct kill *msg) +{ + int tobe_allocated = msg->how_often_num_allocated; + ev_uint32_t* new_data = NULL; + tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; + new_data = (ev_uint32_t*) realloc(msg->how_often_data, + tobe_allocated * sizeof(ev_uint32_t)); + if (new_data == NULL) + return -1; + msg->how_often_data = new_data; + msg->how_often_num_allocated = tobe_allocated; + return 0;} + +ev_uint32_t * +kill_how_often_add(struct kill *msg, const ev_uint32_t value) +{ + if (++msg->how_often_length >= msg->how_often_num_allocated) { + if (kill_how_often_expand_to_hold_more(msg)<0) + goto error; + } + msg->how_often_data[msg->how_often_length - 1] = value; + msg->how_often_set = 1; + return &(msg->how_often_data[msg->how_often_length - 1]); +error: + --msg->how_often_length; + return (NULL); +} + +int +kill_weapon_assign(struct kill *msg, + const char * value) +{ + if (msg->weapon_data != NULL) + free(msg->weapon_data); + if ((msg->weapon_data = strdup(value)) == NULL) + return (-1); + msg->weapon_set = 1; + return (0); +} + +int +kill_action_assign(struct kill *msg, + const char * value) +{ + if (msg->action_data != NULL) + free(msg->action_data); + if ((msg->action_data = strdup(value)) == NULL) + return (-1); + msg->action_set = 1; + return (0); +} + +int +kill_how_often_assign(struct kill *msg, int off, + const ev_uint32_t value) +{ + if (!msg->how_often_set || off < 0 || off >= msg->how_often_length) + return (-1); + + { + msg->how_often_data[off] = value; + } + return (0); +} + +int +kill_weapon_get(struct kill *msg, char * *value) +{ + if (msg->weapon_set != 1) + return (-1); + *value = msg->weapon_data; + return (0); +} + +int +kill_action_get(struct kill *msg, char * *value) +{ + if (msg->action_set != 1) + return (-1); + *value = msg->action_data; + return (0); +} + +int +kill_how_often_get(struct kill *msg, int offset, + ev_uint32_t *value) +{ + if (!msg->how_often_set || offset < 0 || offset >= msg->how_often_length) + return (-1); + *value = msg->how_often_data[offset]; + return (0); +} + +void +kill_clear(struct kill *tmp) +{ + if (tmp->weapon_set == 1) { + free(tmp->weapon_data); + tmp->weapon_data = NULL; + tmp->weapon_set = 0; + } + if (tmp->action_set == 1) { + free(tmp->action_data); + tmp->action_data = NULL; + tmp->action_set = 0; + } + if (tmp->how_often_set == 1) { + free(tmp->how_often_data); + tmp->how_often_data = NULL; + tmp->how_often_set = 0; + tmp->how_often_length = 0; + tmp->how_often_num_allocated = 0; + } +} + +void +kill_free(struct kill *tmp) +{ + if (tmp->weapon_data != NULL) + free (tmp->weapon_data); + if (tmp->action_data != NULL) + free (tmp->action_data); + if (tmp->how_often_set == 1) { + free(tmp->how_often_data); + tmp->how_often_data = NULL; + tmp->how_often_set = 0; + tmp->how_often_length = 0; + tmp->how_often_num_allocated = 0; + } + free(tmp->how_often_data); + free(tmp); +} + +void +kill_marshal(struct evbuffer *evbuf, const struct kill *tmp){ + evtag_marshal_string(evbuf, KILL_WEAPON, tmp->weapon_data); + evtag_marshal_string(evbuf, KILL_ACTION, tmp->action_data); + if (tmp->how_often_set) { + { + int i; + for (i = 0; i < tmp->how_often_length; ++i) { + evtag_marshal_int(evbuf, KILL_HOW_OFTEN, tmp->how_often_data[i]); + } + } + } +} + +int +kill_unmarshal(struct kill *tmp, struct evbuffer *evbuf) +{ + ev_uint32_t tag; + while (evbuffer_get_length(evbuf) > 0) { + if (evtag_peek(evbuf, &tag) == -1) + return (-1); + switch (tag) { + + case KILL_WEAPON: + + if (tmp->weapon_set) + return (-1); + if (evtag_unmarshal_string(evbuf, KILL_WEAPON, &tmp->weapon_data) == -1) { + event_warnx("%s: failed to unmarshal weapon", __func__); + return (-1); + } + tmp->weapon_set = 1; + break; + + case KILL_ACTION: + + if (tmp->action_set) + return (-1); + if (evtag_unmarshal_string(evbuf, KILL_ACTION, &tmp->action_data) == -1) { + event_warnx("%s: failed to unmarshal action", __func__); + return (-1); + } + tmp->action_set = 1; + break; + + case KILL_HOW_OFTEN: + + if (tmp->how_often_length >= tmp->how_often_num_allocated && + kill_how_often_expand_to_hold_more(tmp) < 0) { + puts("HEY NOW"); + return (-1); + } + if (evtag_unmarshal_int(evbuf, KILL_HOW_OFTEN, &tmp->how_often_data[tmp->how_often_length]) == -1) { + event_warnx("%s: failed to unmarshal how_often", __func__); + return (-1); + } + ++tmp->how_often_length; + tmp->how_often_set = 1; + break; + + default: + return -1; + } + } + + if (kill_complete(tmp) == -1) + return (-1); + return (0); +} + +int +kill_complete(struct kill *msg) +{ + if (!msg->weapon_set) + return (-1); + if (!msg->action_set) + return (-1); + return (0); +} + +int +evtag_unmarshal_kill(struct evbuffer *evbuf, ev_uint32_t need_tag, struct kill *msg) +{ + ev_uint32_t tag; + int res = -1; + + struct evbuffer *tmp = evbuffer_new(); + + if (evtag_unmarshal(evbuf, &tag, tmp) == -1 || tag != need_tag) + goto error; + + if (kill_unmarshal(msg, tmp) == -1) + goto error; + + res = 0; + + error: + evbuffer_free(tmp); + return (res); +} + +void +evtag_marshal_kill(struct evbuffer *evbuf, ev_uint32_t tag, const struct kill *msg) +{ + struct evbuffer *_buf = evbuffer_new(); + assert(_buf != NULL); + kill_marshal(_buf, msg); + evtag_marshal_buffer(evbuf, tag, _buf); + evbuffer_free(_buf); +} + +/* + * Implementation of run + */ + +static struct run_access_ __run_base = { + run_how_assign, + run_how_get, + run_some_bytes_assign, + run_some_bytes_get, + run_fixed_bytes_assign, + run_fixed_bytes_get, + run_notes_assign, + run_notes_get, + run_notes_add, + run_large_number_assign, + run_large_number_get, + run_other_numbers_assign, + run_other_numbers_get, + run_other_numbers_add, +}; + +struct run * +run_new(void) +{ + return run_new_with_arg(NULL); +} + +struct run * +run_new_with_arg(void *unused) +{ + struct run *tmp; + if ((tmp = malloc(sizeof(struct run))) == NULL) { + event_warn("%s: malloc", __func__); + return (NULL); + } + tmp->base = &__run_base; + + tmp->how_data = NULL; + tmp->how_set = 0; + + tmp->some_bytes_data = NULL; + tmp->some_bytes_length = 0; + tmp->some_bytes_set = 0; + + memset(tmp->fixed_bytes_data, 0, sizeof(tmp->fixed_bytes_data)); + tmp->fixed_bytes_set = 0; + + tmp->notes_data = NULL; + tmp->notes_length = 0; + tmp->notes_num_allocated = 0; + tmp->notes_set = 0; + + tmp->large_number_data = 0; + tmp->large_number_set = 0; + + tmp->other_numbers_data = NULL; + tmp->other_numbers_length = 0; + tmp->other_numbers_num_allocated = 0; + tmp->other_numbers_set = 0; + + return (tmp); +} + + + + +static int +run_notes_expand_to_hold_more(struct run *msg) +{ + int tobe_allocated = msg->notes_num_allocated; + char ** new_data = NULL; + tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; + new_data = (char **) realloc(msg->notes_data, + tobe_allocated * sizeof(char *)); + if (new_data == NULL) + return -1; + msg->notes_data = new_data; + msg->notes_num_allocated = tobe_allocated; + return 0;} + +char * * +run_notes_add(struct run *msg, const char * value) +{ + if (++msg->notes_length >= msg->notes_num_allocated) { + if (run_notes_expand_to_hold_more(msg)<0) + goto error; + } + if (value != NULL) { + msg->notes_data[msg->notes_length - 1] = strdup(value); + if (msg->notes_data[msg->notes_length - 1] == NULL) { + goto error; + } + } else { + msg->notes_data[msg->notes_length - 1] = NULL; + } + msg->notes_set = 1; + return &(msg->notes_data[msg->notes_length - 1]); +error: + --msg->notes_length; + return (NULL); +} + + +static int +run_other_numbers_expand_to_hold_more(struct run *msg) +{ + int tobe_allocated = msg->other_numbers_num_allocated; + ev_uint32_t* new_data = NULL; + tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; + new_data = (ev_uint32_t*) realloc(msg->other_numbers_data, + tobe_allocated * sizeof(ev_uint32_t)); + if (new_data == NULL) + return -1; + msg->other_numbers_data = new_data; + msg->other_numbers_num_allocated = tobe_allocated; + return 0;} + +ev_uint32_t * +run_other_numbers_add(struct run *msg, const ev_uint32_t value) +{ + if (++msg->other_numbers_length >= msg->other_numbers_num_allocated) { + if (run_other_numbers_expand_to_hold_more(msg)<0) + goto error; + } + msg->other_numbers_data[msg->other_numbers_length - 1] = value; + msg->other_numbers_set = 1; + return &(msg->other_numbers_data[msg->other_numbers_length - 1]); +error: + --msg->other_numbers_length; + return (NULL); +} + +int +run_how_assign(struct run *msg, + const char * value) +{ + if (msg->how_data != NULL) + free(msg->how_data); + if ((msg->how_data = strdup(value)) == NULL) + return (-1); + msg->how_set = 1; + return (0); +} + +int +run_some_bytes_assign(struct run *msg, const ev_uint8_t * value, ev_uint32_t len) +{ + if (msg->some_bytes_data != NULL) + free (msg->some_bytes_data); + msg->some_bytes_data = malloc(len); + if (msg->some_bytes_data == NULL) + return (-1); + msg->some_bytes_set = 1; + msg->some_bytes_length = len; + memcpy(msg->some_bytes_data, value, len); + return (0); +} + +int +run_fixed_bytes_assign(struct run *msg, const ev_uint8_t *value) +{ + msg->fixed_bytes_set = 1; + memcpy(msg->fixed_bytes_data, value, 24); + return (0); +} + +int +run_notes_assign(struct run *msg, int off, + const char * value) +{ + if (!msg->notes_set || off < 0 || off >= msg->notes_length) + return (-1); + + { + if (msg->notes_data[off] != NULL) + free(msg->notes_data[off]); + msg->notes_data[off] = strdup(value); + if (msg->notes_data[off] == NULL) { + event_warnx("%s: strdup", __func__); + return (-1); + } + } + return (0); +} + +int +run_large_number_assign(struct run *msg, const ev_uint64_t value) +{ + msg->large_number_set = 1; + msg->large_number_data = value; + return (0); +} + +int +run_other_numbers_assign(struct run *msg, int off, + const ev_uint32_t value) +{ + if (!msg->other_numbers_set || off < 0 || off >= msg->other_numbers_length) + return (-1); + + { + msg->other_numbers_data[off] = value; + } + return (0); +} + +int +run_how_get(struct run *msg, char * *value) +{ + if (msg->how_set != 1) + return (-1); + *value = msg->how_data; + return (0); +} + +int +run_some_bytes_get(struct run *msg, ev_uint8_t * *value, ev_uint32_t *plen) +{ + if (msg->some_bytes_set != 1) + return (-1); + *value = msg->some_bytes_data; + *plen = msg->some_bytes_length; + return (0); +} + +int +run_fixed_bytes_get(struct run *msg, ev_uint8_t **value) +{ + if (msg->fixed_bytes_set != 1) + return (-1); + *value = msg->fixed_bytes_data; + return (0); +} + +int +run_notes_get(struct run *msg, int offset, + char * *value) +{ + if (!msg->notes_set || offset < 0 || offset >= msg->notes_length) + return (-1); + *value = msg->notes_data[offset]; + return (0); +} + +int +run_large_number_get(struct run *msg, ev_uint64_t *value) +{ + if (msg->large_number_set != 1) + return (-1); + *value = msg->large_number_data; + return (0); +} + +int +run_other_numbers_get(struct run *msg, int offset, + ev_uint32_t *value) +{ + if (!msg->other_numbers_set || offset < 0 || offset >= msg->other_numbers_length) + return (-1); + *value = msg->other_numbers_data[offset]; + return (0); +} + +void +run_clear(struct run *tmp) +{ + if (tmp->how_set == 1) { + free(tmp->how_data); + tmp->how_data = NULL; + tmp->how_set = 0; + } + if (tmp->some_bytes_set == 1) { + free (tmp->some_bytes_data); + tmp->some_bytes_data = NULL; + tmp->some_bytes_length = 0; + tmp->some_bytes_set = 0; + } + tmp->fixed_bytes_set = 0; + memset(tmp->fixed_bytes_data, 0, sizeof(tmp->fixed_bytes_data)); + if (tmp->notes_set == 1) { + int i; + for (i = 0; i < tmp->notes_length; ++i) { + if (tmp->notes_data[i] != NULL) free(tmp->notes_data[i]); + } + free(tmp->notes_data); + tmp->notes_data = NULL; + tmp->notes_set = 0; + tmp->notes_length = 0; + tmp->notes_num_allocated = 0; + } + tmp->large_number_set = 0; + if (tmp->other_numbers_set == 1) { + free(tmp->other_numbers_data); + tmp->other_numbers_data = NULL; + tmp->other_numbers_set = 0; + tmp->other_numbers_length = 0; + tmp->other_numbers_num_allocated = 0; + } +} + +void +run_free(struct run *tmp) +{ + if (tmp->how_data != NULL) + free (tmp->how_data); + if (tmp->some_bytes_data != NULL) + free(tmp->some_bytes_data); + if (tmp->notes_set == 1) { + int i; + for (i = 0; i < tmp->notes_length; ++i) { + if (tmp->notes_data[i] != NULL) free(tmp->notes_data[i]); + } + free(tmp->notes_data); + tmp->notes_data = NULL; + tmp->notes_set = 0; + tmp->notes_length = 0; + tmp->notes_num_allocated = 0; + } + free(tmp->notes_data); + if (tmp->other_numbers_set == 1) { + free(tmp->other_numbers_data); + tmp->other_numbers_data = NULL; + tmp->other_numbers_set = 0; + tmp->other_numbers_length = 0; + tmp->other_numbers_num_allocated = 0; + } + free(tmp->other_numbers_data); + free(tmp); +} + +void +run_marshal(struct evbuffer *evbuf, const struct run *tmp){ + evtag_marshal_string(evbuf, RUN_HOW, tmp->how_data); + if (tmp->some_bytes_set) { + evtag_marshal(evbuf, RUN_SOME_BYTES, tmp->some_bytes_data, tmp->some_bytes_length); + } + evtag_marshal(evbuf, RUN_FIXED_BYTES, tmp->fixed_bytes_data, (24)); + if (tmp->notes_set) { + { + int i; + for (i = 0; i < tmp->notes_length; ++i) { + evtag_marshal_string(evbuf, RUN_NOTES, tmp->notes_data[i]); + } + } + } + if (tmp->large_number_set) { + evtag_marshal_int64(evbuf, RUN_LARGE_NUMBER, tmp->large_number_data); + } + if (tmp->other_numbers_set) { + { + int i; + for (i = 0; i < tmp->other_numbers_length; ++i) { + evtag_marshal_int(evbuf, RUN_OTHER_NUMBERS, tmp->other_numbers_data[i]); + } + } + } +} + +int +run_unmarshal(struct run *tmp, struct evbuffer *evbuf) +{ + ev_uint32_t tag; + while (evbuffer_get_length(evbuf) > 0) { + if (evtag_peek(evbuf, &tag) == -1) + return (-1); + switch (tag) { + + case RUN_HOW: + + if (tmp->how_set) + return (-1); + if (evtag_unmarshal_string(evbuf, RUN_HOW, &tmp->how_data) == -1) { + event_warnx("%s: failed to unmarshal how", __func__); + return (-1); + } + tmp->how_set = 1; + break; + + case RUN_SOME_BYTES: + + if (tmp->some_bytes_set) + return (-1); + if (evtag_payload_length(evbuf, &tmp->some_bytes_length) == -1) + return (-1); + if (tmp->some_bytes_length > evbuffer_get_length(evbuf)) + return (-1); + if ((tmp->some_bytes_data = malloc(tmp->some_bytes_length)) == NULL) + return (-1); + if (evtag_unmarshal_fixed(evbuf, RUN_SOME_BYTES, tmp->some_bytes_data, tmp->some_bytes_length) == -1) { + event_warnx("%s: failed to unmarshal some_bytes", __func__); + return (-1); + } + tmp->some_bytes_set = 1; + break; + + case RUN_FIXED_BYTES: + + if (tmp->fixed_bytes_set) + return (-1); + if (evtag_unmarshal_fixed(evbuf, RUN_FIXED_BYTES, tmp->fixed_bytes_data, (24)) == -1) { + event_warnx("%s: failed to unmarshal fixed_bytes", __func__); + return (-1); + } + tmp->fixed_bytes_set = 1; + break; + + case RUN_NOTES: + + if (tmp->notes_length >= tmp->notes_num_allocated && + run_notes_expand_to_hold_more(tmp) < 0) { + puts("HEY NOW"); + return (-1); + } + if (evtag_unmarshal_string(evbuf, RUN_NOTES, &tmp->notes_data[tmp->notes_length]) == -1) { + event_warnx("%s: failed to unmarshal notes", __func__); + return (-1); + } + ++tmp->notes_length; + tmp->notes_set = 1; + break; + + case RUN_LARGE_NUMBER: + + if (tmp->large_number_set) + return (-1); + if (evtag_unmarshal_int64(evbuf, RUN_LARGE_NUMBER, &tmp->large_number_data) == -1) { + event_warnx("%s: failed to unmarshal large_number", __func__); + return (-1); + } + tmp->large_number_set = 1; + break; + + case RUN_OTHER_NUMBERS: + + if (tmp->other_numbers_length >= tmp->other_numbers_num_allocated && + run_other_numbers_expand_to_hold_more(tmp) < 0) { + puts("HEY NOW"); + return (-1); + } + if (evtag_unmarshal_int(evbuf, RUN_OTHER_NUMBERS, &tmp->other_numbers_data[tmp->other_numbers_length]) == -1) { + event_warnx("%s: failed to unmarshal other_numbers", __func__); + return (-1); + } + ++tmp->other_numbers_length; + tmp->other_numbers_set = 1; + break; + + default: + return -1; + } + } + + if (run_complete(tmp) == -1) + return (-1); + return (0); +} + +int +run_complete(struct run *msg) +{ + if (!msg->how_set) + return (-1); + if (!msg->fixed_bytes_set) + return (-1); + return (0); +} + +int +evtag_unmarshal_run(struct evbuffer *evbuf, ev_uint32_t need_tag, struct run *msg) +{ + ev_uint32_t tag; + int res = -1; + + struct evbuffer *tmp = evbuffer_new(); + + if (evtag_unmarshal(evbuf, &tag, tmp) == -1 || tag != need_tag) + goto error; + + if (run_unmarshal(msg, tmp) == -1) + goto error; + + res = 0; + + error: + evbuffer_free(tmp); + return (res); +} + +void +evtag_marshal_run(struct evbuffer *evbuf, ev_uint32_t tag, const struct run *msg) +{ + struct evbuffer *_buf = evbuffer_new(); + assert(_buf != NULL); + run_marshal(_buf, msg); + evtag_marshal_buffer(evbuf, tag, _buf); + evbuffer_free(_buf); +} + diff --git a/libevent/test/regress.gen.h b/libevent/test/regress.gen.h new file mode 100644 index 0000000..1281b94 --- /dev/null +++ b/libevent/test/regress.gen.h @@ -0,0 +1,207 @@ +/* + * Automatically generated from ./regress.rpc + */ + +#ifndef ___REGRESS_RPC_ +#define ___REGRESS_RPC_ + +#include /* for ev_uint*_t */ +#include + +struct msg; +struct kill; +struct run; + +/* Tag definition for msg */ +enum msg_ { + MSG_FROM_NAME=1, + MSG_TO_NAME=2, + MSG_ATTACK=3, + MSG_RUN=4, + MSG_MAX_TAGS +}; + +/* Structure declaration for msg */ +struct msg_access_ { + int (*from_name_assign)(struct msg *, const char *); + int (*from_name_get)(struct msg *, char * *); + int (*to_name_assign)(struct msg *, const char *); + int (*to_name_get)(struct msg *, char * *); + int (*attack_assign)(struct msg *, const struct kill*); + int (*attack_get)(struct msg *, struct kill* *); + int (*run_assign)(struct msg *, int, const struct run*); + int (*run_get)(struct msg *, int, struct run* *); + struct run* (*run_add)(struct msg *msg); +}; + +struct msg { + struct msg_access_ *base; + + char *from_name_data; + char *to_name_data; + struct kill* attack_data; + struct run* *run_data; + int run_length; + int run_num_allocated; + + ev_uint8_t from_name_set; + ev_uint8_t to_name_set; + ev_uint8_t attack_set; + ev_uint8_t run_set; +}; + +struct msg *msg_new(void); +struct msg *msg_new_with_arg(void *); +void msg_free(struct msg *); +void msg_clear(struct msg *); +void msg_marshal(struct evbuffer *, const struct msg *); +int msg_unmarshal(struct msg *, struct evbuffer *); +int msg_complete(struct msg *); +void evtag_marshal_msg(struct evbuffer *, ev_uint32_t, + const struct msg *); +int evtag_unmarshal_msg(struct evbuffer *, ev_uint32_t, + struct msg *); +int msg_from_name_assign(struct msg *, const char *); +int msg_from_name_get(struct msg *, char * *); +int msg_to_name_assign(struct msg *, const char *); +int msg_to_name_get(struct msg *, char * *); +int msg_attack_assign(struct msg *, const struct kill*); +int msg_attack_get(struct msg *, struct kill* *); +int msg_run_assign(struct msg *, int, const struct run*); +int msg_run_get(struct msg *, int, struct run* *); +struct run* msg_run_add(struct msg *msg); +/* --- msg done --- */ + +/* Tag definition for kill */ +enum kill_ { + KILL_WEAPON=65825, + KILL_ACTION=2, + KILL_HOW_OFTEN=3, + KILL_MAX_TAGS +}; + +/* Structure declaration for kill */ +struct kill_access_ { + int (*weapon_assign)(struct kill *, const char *); + int (*weapon_get)(struct kill *, char * *); + int (*action_assign)(struct kill *, const char *); + int (*action_get)(struct kill *, char * *); + int (*how_often_assign)(struct kill *, int, const ev_uint32_t); + int (*how_often_get)(struct kill *, int, ev_uint32_t *); + ev_uint32_t * (*how_often_add)(struct kill *msg, const ev_uint32_t value); +}; + +struct kill { + struct kill_access_ *base; + + char *weapon_data; + char *action_data; + ev_uint32_t *how_often_data; + int how_often_length; + int how_often_num_allocated; + + ev_uint8_t weapon_set; + ev_uint8_t action_set; + ev_uint8_t how_often_set; +}; + +struct kill *kill_new(void); +struct kill *kill_new_with_arg(void *); +void kill_free(struct kill *); +void kill_clear(struct kill *); +void kill_marshal(struct evbuffer *, const struct kill *); +int kill_unmarshal(struct kill *, struct evbuffer *); +int kill_complete(struct kill *); +void evtag_marshal_kill(struct evbuffer *, ev_uint32_t, + const struct kill *); +int evtag_unmarshal_kill(struct evbuffer *, ev_uint32_t, + struct kill *); +int kill_weapon_assign(struct kill *, const char *); +int kill_weapon_get(struct kill *, char * *); +int kill_action_assign(struct kill *, const char *); +int kill_action_get(struct kill *, char * *); +int kill_how_often_assign(struct kill *, int, const ev_uint32_t); +int kill_how_often_get(struct kill *, int, ev_uint32_t *); +ev_uint32_t * kill_how_often_add(struct kill *msg, const ev_uint32_t value); +/* --- kill done --- */ + +/* Tag definition for run */ +enum run_ { + RUN_HOW=1, + RUN_SOME_BYTES=2, + RUN_FIXED_BYTES=3, + RUN_NOTES=4, + RUN_LARGE_NUMBER=5, + RUN_OTHER_NUMBERS=6, + RUN_MAX_TAGS +}; + +/* Structure declaration for run */ +struct run_access_ { + int (*how_assign)(struct run *, const char *); + int (*how_get)(struct run *, char * *); + int (*some_bytes_assign)(struct run *, const ev_uint8_t *, ev_uint32_t); + int (*some_bytes_get)(struct run *, ev_uint8_t * *, ev_uint32_t *); + int (*fixed_bytes_assign)(struct run *, const ev_uint8_t *); + int (*fixed_bytes_get)(struct run *, ev_uint8_t **); + int (*notes_assign)(struct run *, int, const char *); + int (*notes_get)(struct run *, int, char * *); + char * * (*notes_add)(struct run *msg, const char * value); + int (*large_number_assign)(struct run *, const ev_uint64_t); + int (*large_number_get)(struct run *, ev_uint64_t *); + int (*other_numbers_assign)(struct run *, int, const ev_uint32_t); + int (*other_numbers_get)(struct run *, int, ev_uint32_t *); + ev_uint32_t * (*other_numbers_add)(struct run *msg, const ev_uint32_t value); +}; + +struct run { + struct run_access_ *base; + + char *how_data; + ev_uint8_t *some_bytes_data; + ev_uint32_t some_bytes_length; + ev_uint8_t fixed_bytes_data[24]; + char * *notes_data; + int notes_length; + int notes_num_allocated; + ev_uint64_t large_number_data; + ev_uint32_t *other_numbers_data; + int other_numbers_length; + int other_numbers_num_allocated; + + ev_uint8_t how_set; + ev_uint8_t some_bytes_set; + ev_uint8_t fixed_bytes_set; + ev_uint8_t notes_set; + ev_uint8_t large_number_set; + ev_uint8_t other_numbers_set; +}; + +struct run *run_new(void); +struct run *run_new_with_arg(void *); +void run_free(struct run *); +void run_clear(struct run *); +void run_marshal(struct evbuffer *, const struct run *); +int run_unmarshal(struct run *, struct evbuffer *); +int run_complete(struct run *); +void evtag_marshal_run(struct evbuffer *, ev_uint32_t, + const struct run *); +int evtag_unmarshal_run(struct evbuffer *, ev_uint32_t, + struct run *); +int run_how_assign(struct run *, const char *); +int run_how_get(struct run *, char * *); +int run_some_bytes_assign(struct run *, const ev_uint8_t *, ev_uint32_t); +int run_some_bytes_get(struct run *, ev_uint8_t * *, ev_uint32_t *); +int run_fixed_bytes_assign(struct run *, const ev_uint8_t *); +int run_fixed_bytes_get(struct run *, ev_uint8_t **); +int run_notes_assign(struct run *, int, const char *); +int run_notes_get(struct run *, int, char * *); +char * * run_notes_add(struct run *msg, const char * value); +int run_large_number_assign(struct run *, const ev_uint64_t); +int run_large_number_get(struct run *, ev_uint64_t *); +int run_other_numbers_assign(struct run *, int, const ev_uint32_t); +int run_other_numbers_get(struct run *, int, ev_uint32_t *); +ev_uint32_t * run_other_numbers_add(struct run *msg, const ev_uint32_t value); +/* --- run done --- */ + +#endif /* ___REGRESS_RPC_ */ diff --git a/libevent/test/regress.h b/libevent/test/regress.h new file mode 100644 index 0000000..32adccd --- /dev/null +++ b/libevent/test/regress.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#ifndef _REGRESS_H_ +#define _REGRESS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "tinytest.h" +#include "tinytest_macros.h" + +extern struct testcase_t main_testcases[]; +extern struct testcase_t evtag_testcases[]; +extern struct testcase_t evbuffer_testcases[]; +extern struct testcase_t bufferevent_testcases[]; +extern struct testcase_t bufferevent_iocp_testcases[]; +extern struct testcase_t util_testcases[]; +extern struct testcase_t signal_testcases[]; +extern struct testcase_t http_testcases[]; +extern struct testcase_t dns_testcases[]; +extern struct testcase_t rpc_testcases[]; +extern struct testcase_t edgetriggered_testcases[]; +extern struct testcase_t minheap_testcases[]; +extern struct testcase_t iocp_testcases[]; +extern struct testcase_t ssl_testcases[]; +extern struct testcase_t listener_testcases[]; +extern struct testcase_t listener_iocp_testcases[]; +extern struct testcase_t thread_testcases[]; + +void regress_threads(void *); +void test_bufferevent_zlib(void *); + +/* Helpers to wrap old testcases */ +extern evutil_socket_t pair[2]; +extern int test_ok; +extern int called; +extern struct event_base *global_base; +extern int in_legacy_test_wrapper; + +int regress_make_tmpfile(const void *data, size_t datalen); + +struct basic_test_data { + struct event_base *base; + evutil_socket_t pair[2]; + + void (*legacy_test_fn)(void); + + void *setup_data; +}; +extern const struct testcase_setup_t basic_setup; + + +extern const struct testcase_setup_t legacy_setup; +void run_legacy_test_fn(void *ptr); + +/* A couple of flags that basic/legacy_setup can support. */ +#define TT_NEED_SOCKETPAIR TT_FIRST_USER_FLAG +#define TT_NEED_BASE (TT_FIRST_USER_FLAG<<1) +#define TT_NEED_DNS (TT_FIRST_USER_FLAG<<2) +#define TT_LEGACY (TT_FIRST_USER_FLAG<<3) +#define TT_NEED_THREADS (TT_FIRST_USER_FLAG<<4) +#define TT_NO_LOGS (TT_FIRST_USER_FLAG<<5) +#define TT_ENABLE_IOCP_FLAG (TT_FIRST_USER_FLAG<<6) +#define TT_ENABLE_IOCP (TT_ENABLE_IOCP_FLAG|TT_NEED_THREADS) + +/* All the flags that a legacy test needs. */ +#define TT_ISOLATED TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE + + +#define BASIC(name,flags) \ + { #name, test_## name, flags, &basic_setup, NULL } + +#define LEGACY(name,flags) \ + { #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \ + test_## name } + +struct evutil_addrinfo; +struct evutil_addrinfo *ai_find_by_family(struct evutil_addrinfo *ai, int f); +struct evutil_addrinfo *ai_find_by_protocol(struct evutil_addrinfo *ai, int p); +int _test_ai_eq(const struct evutil_addrinfo *ai, const char *sockaddr_port, + int socktype, int protocol, int line); + +#define test_ai_eq(ai, str, s, p) do { \ + if (_test_ai_eq((ai), (str), (s), (p), __LINE__)<0) \ + goto end; \ + } while (0) + +#define test_timeval_diff_leq(tv1, tv2, diff, tolerance) \ + tt_int_op(abs(timeval_msec_diff((tv1), (tv2)) - diff), <=, tolerance) + +#define test_timeval_diff_eq(tv1, tv2, diff) \ + test_timeval_diff_leq((tv1), (tv2), (diff), 50) + +long timeval_msec_diff(const struct timeval *start, const struct timeval *end); + +#ifdef __cplusplus +} +#endif + +#endif /* _REGRESS_H_ */ diff --git a/libevent/test/regress.rpc b/libevent/test/regress.rpc new file mode 100644 index 0000000..0ee904e --- /dev/null +++ b/libevent/test/regress.rpc @@ -0,0 +1,25 @@ +/* tests data packing and unpacking */ + +struct msg { + string /* sender */ from_name = 1; /* be verbose */ + string to_name = 2; + optional struct[kill] attack = 3; + array struct[run] run = 4; +} + +struct kill { + string weapon = 0x10121; + string action = 2; + array int how_often = 3; +} + +struct run { + string how = 1; + optional bytes some_bytes = 2; + + bytes fixed_bytes[24] = 3; + array string notes = 4; + + optional int64 large_number = 5; + array int other_numbers = 6; +} diff --git a/libevent/test/regress_buffer.c b/libevent/test/regress_buffer.c new file mode 100644 index 0000000..6a2b6fc --- /dev/null +++ b/libevent/test/regress_buffer.c @@ -0,0 +1,1666 @@ +/* + * Copyright (c) 2003-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#ifdef WIN32 +#include +#include +#endif + +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#ifndef WIN32 +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include + +#include "event2/event.h" +#include "event2/buffer.h" +#include "event2/buffer_compat.h" +#include "event2/util.h" + +#include "evbuffer-internal.h" +#include "log-internal.h" + +#include "regress.h" + +/* Validates that an evbuffer is good. Returns false if it isn't, true if it + * is*/ +static int +_evbuffer_validate(struct evbuffer *buf) +{ + struct evbuffer_chain *chain; + size_t sum = 0; + int found_last_with_datap = 0; + + if (buf->first == NULL) { + tt_assert(buf->last == NULL); + tt_assert(buf->total_len == 0); + } + + chain = buf->first; + + tt_assert(buf->last_with_datap); + if (buf->last_with_datap == &buf->first) + found_last_with_datap = 1; + + while (chain != NULL) { + if (&chain->next == buf->last_with_datap) + found_last_with_datap = 1; + sum += chain->off; + if (chain->next == NULL) { + tt_assert(buf->last == chain); + } + tt_assert(chain->buffer_len >= chain->misalign + chain->off); + chain = chain->next; + } + + if (buf->first) + tt_assert(*buf->last_with_datap); + + if (*buf->last_with_datap) { + chain = *buf->last_with_datap; + if (chain->off == 0 || buf->total_len == 0) { + tt_assert(chain->off == 0) + tt_assert(chain == buf->first); + tt_assert(buf->total_len == 0); + } + chain = chain->next; + while (chain != NULL) { + tt_assert(chain->off == 0); + chain = chain->next; + } + } else { + tt_assert(buf->last_with_datap == &buf->first); + } + tt_assert(found_last_with_datap); + + tt_assert(sum == buf->total_len); + return 1; + end: + return 0; +} + +static void +evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp) +{ + struct evbuffer_chain *chain; + size_t a, w, u; + int n = 0; + u = a = w = 0; + + chain = buf->first; + /* skip empty at start */ + while (chain && chain->off==0) { + ++n; + a += chain->buffer_len; + chain = chain->next; + } + /* first nonempty chain: stuff at the end only is wasted. */ + if (chain) { + ++n; + a += chain->buffer_len; + u += chain->off; + if (chain->next && chain->next->off) + w += (size_t)(chain->buffer_len - (chain->misalign + chain->off)); + chain = chain->next; + } + /* subsequent nonempty chains */ + while (chain && chain->off) { + ++n; + a += chain->buffer_len; + w += (size_t)chain->misalign; + u += chain->off; + if (chain->next && chain->next->off) + w += (size_t) (chain->buffer_len - (chain->misalign + chain->off)); + chain = chain->next; + } + /* subsequent empty chains */ + while (chain) { + ++n; + a += chain->buffer_len; + } + *allocatedp = a; + *wastedp = w; + *usedp = u; +} + +#define evbuffer_validate(buf) \ + TT_STMT_BEGIN if (!_evbuffer_validate(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END + +static void +test_evbuffer(void *ptr) +{ + static char buffer[512], *tmp; + struct evbuffer *evb = evbuffer_new(); + struct evbuffer *evb_two = evbuffer_new(); + size_t sz_tmp; + int i; + + evbuffer_validate(evb); + evbuffer_add_printf(evb, "%s/%d", "hello", 1); + evbuffer_validate(evb); + + tt_assert(evbuffer_get_length(evb) == 7); + tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1)); + + evbuffer_add_buffer(evb, evb_two); + evbuffer_validate(evb); + + evbuffer_drain(evb, strlen("hello/")); + evbuffer_validate(evb); + tt_assert(evbuffer_get_length(evb) == 1); + tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1)); + + evbuffer_add_printf(evb_two, "%s", "/hello"); + evbuffer_validate(evb); + evbuffer_add_buffer(evb, evb_two); + evbuffer_validate(evb); + + tt_assert(evbuffer_get_length(evb_two) == 0); + tt_assert(evbuffer_get_length(evb) == 7); + tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0); + + memset(buffer, 0, sizeof(buffer)); + evbuffer_add(evb, buffer, sizeof(buffer)); + evbuffer_validate(evb); + tt_assert(evbuffer_get_length(evb) == 7 + 512); + + tmp = (char *)evbuffer_pullup(evb, 7 + 512); + tt_assert(tmp); + tt_assert(!strncmp(tmp, "1/hello", 7)); + tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer))); + evbuffer_validate(evb); + + evbuffer_prepend(evb, "something", 9); + evbuffer_validate(evb); + evbuffer_prepend(evb, "else", 4); + evbuffer_validate(evb); + + tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7); + tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7)); + evbuffer_validate(evb); + + evbuffer_drain(evb, -1); + evbuffer_validate(evb); + evbuffer_drain(evb_two, -1); + evbuffer_validate(evb); + + for (i = 0; i < 3; ++i) { + evbuffer_add(evb_two, buffer, sizeof(buffer)); + evbuffer_validate(evb_two); + evbuffer_add_buffer(evb, evb_two); + evbuffer_validate(evb); + evbuffer_validate(evb_two); + } + + tt_assert(evbuffer_get_length(evb_two) == 0); + tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer)); + + /* test remove buffer */ + sz_tmp = (size_t)(sizeof(buffer)*2.5); + evbuffer_remove_buffer(evb, evb_two, sz_tmp); + tt_assert(evbuffer_get_length(evb_two) == sz_tmp); + tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2); + evbuffer_validate(evb); + + if (memcmp(evbuffer_pullup( + evb, -1), buffer, sizeof(buffer) / 2) != 0 || + memcmp(evbuffer_pullup( + evb_two, -1), buffer, sizeof(buffer) != 0)) + tt_abort_msg("Pullup did not preserve content"); + + evbuffer_validate(evb); + + + /* testing one-vector reserve and commit */ + { + struct evbuffer_iovec v[1]; + char *buf; + int i, j, r; + + for (i = 0; i < 3; ++i) { + r = evbuffer_reserve_space(evb, 10000, v, 1); + tt_int_op(r, ==, 1); + tt_assert(v[0].iov_len >= 10000); + tt_assert(v[0].iov_base != NULL); + + evbuffer_validate(evb); + buf = v[0].iov_base; + for (j = 0; j < 10000; ++j) { + buf[j] = j; + } + evbuffer_validate(evb); + + tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0); + evbuffer_validate(evb); + + tt_assert(evbuffer_get_length(evb) >= 10000); + + evbuffer_drain(evb, j * 5000); + evbuffer_validate(evb); + } + } + + end: + evbuffer_free(evb); + evbuffer_free(evb_two); +} + +static void +no_cleanup(const void *data, size_t datalen, void *extra) +{ +} + +static void +test_evbuffer_remove_buffer_with_empty(void *ptr) +{ + struct evbuffer *src = evbuffer_new(); + struct evbuffer *dst = evbuffer_new(); + char buf[2]; + + evbuffer_validate(src); + evbuffer_validate(dst); + + /* setup the buffers */ + /* we need more data in src than we will move later */ + evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL); + evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL); + /* we need one buffer in dst and one empty buffer at the end */ + evbuffer_add(dst, buf, sizeof(buf)); + evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL); + + evbuffer_validate(src); + evbuffer_validate(dst); + + /* move three bytes over */ + evbuffer_remove_buffer(src, dst, 3); + + evbuffer_validate(src); + evbuffer_validate(dst); + +end: + evbuffer_free(src); + evbuffer_free(dst); +} + +static void +test_evbuffer_reserve2(void *ptr) +{ + /* Test the two-vector cases of reserve/commit. */ + struct evbuffer *buf = evbuffer_new(); + int n, i; + struct evbuffer_iovec v[2]; + size_t remaining; + char *cp, *cp2; + + /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/ + n = evbuffer_reserve_space(buf, 1024, v, 2); + tt_int_op(n, ==, 1); + tt_int_op(evbuffer_get_length(buf), ==, 0); + tt_assert(v[0].iov_base != NULL); + tt_int_op(v[0].iov_len, >=, 1024); + memset(v[0].iov_base, 'X', 512); + cp = v[0].iov_base; + remaining = v[0].iov_len - 512; + v[0].iov_len = 512; + evbuffer_validate(buf); + tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); + tt_int_op(evbuffer_get_length(buf), ==, 512); + evbuffer_validate(buf); + + /* Ask for another same-chunk request, in an existing chunk. Use 8 + * bytes of it. */ + n = evbuffer_reserve_space(buf, 32, v, 2); + tt_int_op(n, ==, 1); + tt_assert(cp + 512 == v[0].iov_base); + tt_int_op(remaining, ==, v[0].iov_len); + memset(v[0].iov_base, 'Y', 8); + v[0].iov_len = 8; + tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); + tt_int_op(evbuffer_get_length(buf), ==, 520); + remaining -= 8; + evbuffer_validate(buf); + + /* Now ask for a request that will be split. Use only one byte of it, + though. */ + n = evbuffer_reserve_space(buf, remaining+64, v, 2); + tt_int_op(n, ==, 2); + tt_assert(cp + 520 == v[0].iov_base); + tt_int_op(remaining, ==, v[0].iov_len); + tt_assert(v[1].iov_base); + tt_assert(v[1].iov_len >= 64); + cp2 = v[1].iov_base; + memset(v[0].iov_base, 'Z', 1); + v[0].iov_len = 1; + tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); + tt_int_op(evbuffer_get_length(buf), ==, 521); + remaining -= 1; + evbuffer_validate(buf); + + /* Now ask for a request that will be split. Use some of the first + * part and some of the second. */ + n = evbuffer_reserve_space(buf, remaining+64, v, 2); + evbuffer_validate(buf); + tt_int_op(n, ==, 2); + tt_assert(cp + 521 == v[0].iov_base); + tt_int_op(remaining, ==, v[0].iov_len); + tt_assert(v[1].iov_base == cp2); + tt_assert(v[1].iov_len >= 64); + memset(v[0].iov_base, 'W', 400); + v[0].iov_len = 400; + memset(v[1].iov_base, 'x', 60); + v[1].iov_len = 60; + tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2)); + tt_int_op(evbuffer_get_length(buf), ==, 981); + evbuffer_validate(buf); + + /* Now peek to make sure stuff got made how we like. */ + memset(v,0,sizeof(v)); + n = evbuffer_peek(buf, -1, NULL, v, 2); + tt_int_op(n, ==, 2); + tt_int_op(v[0].iov_len, ==, 921); + tt_int_op(v[1].iov_len, ==, 60); + + cp = v[0].iov_base; + for (i=0; i<512; ++i) + tt_int_op(cp[i], ==, 'X'); + for (i=512; i<520; ++i) + tt_int_op(cp[i], ==, 'Y'); + for (i=520; i<521; ++i) + tt_int_op(cp[i], ==, 'Z'); + for (i=521; i<921; ++i) + tt_int_op(cp[i], ==, 'W'); + + cp = v[1].iov_base; + for (i=0; i<60; ++i) + tt_int_op(cp[i], ==, 'x'); + +end: + evbuffer_free(buf); +} + +static void +test_evbuffer_reserve_many(void *ptr) +{ + /* This is a glass-box test to handle expanding a buffer with more + * chunks and reallocating chunks as needed */ + struct evbuffer *buf = evbuffer_new(); + struct evbuffer_iovec v[8]; + int n; + size_t sz; + int add_data = ptr && !strcmp(ptr, "add"); + int fill_first = ptr && !strcmp(ptr, "fill"); + char *cp1, *cp2; + + /* When reserving the the first chunk, we just allocate it */ + n = evbuffer_reserve_space(buf, 128, v, 2); + evbuffer_validate(buf); + tt_int_op(n, ==, 1); + tt_assert(v[0].iov_len >= 128); + sz = v[0].iov_len; + cp1 = v[0].iov_base; + if (add_data) { + *(char*)v[0].iov_base = 'X'; + v[0].iov_len = 1; + n = evbuffer_commit_space(buf, v, 1); + tt_int_op(n, ==, 0); + } else if (fill_first) { + memset(v[0].iov_base, 'X', v[0].iov_len); + n = evbuffer_commit_space(buf, v, 1); + tt_int_op(n, ==, 0); + n = evbuffer_reserve_space(buf, 128, v, 2); + tt_int_op(n, ==, 1); + sz = v[0].iov_len; + tt_assert(v[0].iov_base != cp1); + cp1 = v[0].iov_base; + } + + /* Make another chunk get added. */ + n = evbuffer_reserve_space(buf, sz+128, v, 2); + evbuffer_validate(buf); + tt_int_op(n, ==, 2); + sz = v[0].iov_len + v[1].iov_len; + tt_int_op(sz, >=, v[0].iov_len+128); + if (add_data) { + tt_assert(v[0].iov_base == cp1 + 1); + } else { + tt_assert(v[0].iov_base == cp1); + } + cp1 = v[0].iov_base; + cp2 = v[1].iov_base; + + /* And a third chunk. */ + n = evbuffer_reserve_space(buf, sz+128, v, 3); + evbuffer_validate(buf); + tt_int_op(n, ==, 3); + tt_assert(cp1 == v[0].iov_base); + tt_assert(cp2 == v[1].iov_base); + sz = v[0].iov_len + v[1].iov_len + v[2].iov_len; + + /* Now force a reallocation by asking for more space in only 2 + * buffers. */ + n = evbuffer_reserve_space(buf, sz+128, v, 2); + evbuffer_validate(buf); + if (add_data) { + tt_int_op(n, ==, 2); + tt_assert(cp1 == v[0].iov_base); + } else { + tt_int_op(n, ==, 1); + } + +end: + evbuffer_free(buf); +} + +static void +test_evbuffer_expand(void *ptr) +{ + char data[4096]; + struct evbuffer *buf; + size_t a,w,u; + void *buffer; + + memset(data, 'X', sizeof(data)); + + /* Make sure that expand() works on an empty buffer */ + buf = evbuffer_new(); + tt_int_op(evbuffer_expand(buf, 20000), ==, 0); + evbuffer_validate(buf); + a=w=u=0; + evbuffer_get_waste(buf, &a,&w,&u); + tt_assert(w == 0); + tt_assert(u == 0); + tt_assert(a >= 20000); + tt_assert(buf->first); + tt_assert(buf->first == buf->last); + tt_assert(buf->first->off == 0); + tt_assert(buf->first->buffer_len >= 20000); + + /* Make sure that expand() works as a no-op when there's enough + * contiguous space already. */ + buffer = buf->first->buffer; + evbuffer_add(buf, data, 1024); + tt_int_op(evbuffer_expand(buf, 1024), ==, 0); + tt_assert(buf->first->buffer == buffer); + evbuffer_validate(buf); + evbuffer_free(buf); + + /* Make sure that expand() can work by moving misaligned data + * when it makes sense to do so. */ + buf = evbuffer_new(); + evbuffer_add(buf, data, 400); + { + int n = (int)(buf->first->buffer_len - buf->first->off - 1); + tt_assert(n < (int)sizeof(data)); + evbuffer_add(buf, data, n); + } + tt_assert(buf->first == buf->last); + tt_assert(buf->first->off == buf->first->buffer_len - 1); + evbuffer_drain(buf, buf->first->off - 1); + tt_assert(1 == evbuffer_get_length(buf)); + tt_assert(buf->first->misalign > 0); + tt_assert(buf->first->off == 1); + buffer = buf->first->buffer; + tt_assert(evbuffer_expand(buf, 40) == 0); + tt_assert(buf->first == buf->last); + tt_assert(buf->first->off == 1); + tt_assert(buf->first->buffer == buffer); + tt_assert(buf->first->misalign == 0); + evbuffer_validate(buf); + evbuffer_free(buf); + + /* add, expand, pull-up: This used to crash libevent. */ + buf = evbuffer_new(); + + evbuffer_add(buf, data, sizeof(data)); + evbuffer_add(buf, data, sizeof(data)); + evbuffer_add(buf, data, sizeof(data)); + + evbuffer_validate(buf); + evbuffer_expand(buf, 1024); + evbuffer_validate(buf); + evbuffer_pullup(buf, -1); + evbuffer_validate(buf); + +end: + evbuffer_free(buf); +} + + +static int reference_cb_called; +static void +reference_cb(const void *data, size_t len, void *extra) +{ + tt_str_op(data, ==, "this is what we add as read-only memory."); + tt_int_op(len, ==, strlen(data)); + tt_want(extra == (void *)0xdeadaffe); + ++reference_cb_called; +end: + ; +} + +static void +test_evbuffer_reference(void *ptr) +{ + struct evbuffer *src = evbuffer_new(); + struct evbuffer *dst = evbuffer_new(); + struct evbuffer_iovec v[1]; + const char *data = "this is what we add as read-only memory."; + reference_cb_called = 0; + + tt_assert(evbuffer_add_reference(src, data, strlen(data), + reference_cb, (void *)0xdeadaffe) != -1); + + evbuffer_reserve_space(dst, strlen(data), v, 1); + tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1); + + evbuffer_validate(src); + evbuffer_validate(dst); + + /* make sure that we don't write data at the beginning */ + evbuffer_prepend(src, "aaaaa", 5); + evbuffer_validate(src); + evbuffer_drain(src, 5); + + tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10, + strlen(data) - 10) != -1); + + v[0].iov_len = strlen(data); + + evbuffer_commit_space(dst, v, 1); + evbuffer_validate(src); + evbuffer_validate(dst); + + tt_int_op(reference_cb_called, ==, 1); + + tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)), + data, strlen(data))); + evbuffer_validate(dst); + + end: + evbuffer_free(dst); + evbuffer_free(src); +} + +int _evbuffer_testing_use_sendfile(void); +int _evbuffer_testing_use_mmap(void); +int _evbuffer_testing_use_linear_file_access(void); + +static void +test_evbuffer_add_file(void *ptr) +{ + const char *impl = ptr; + struct evbuffer *src = evbuffer_new(); + const char *data = "this is what we add as file system data."; + size_t datalen; + const char *compare; + int fd = -1; + evutil_socket_t pair[2] = {-1, -1}; + int r=0, n_written=0; + + /* Add a test for a big file. XXXX */ + + tt_assert(impl); + if (!strcmp(impl, "sendfile")) { + if (!_evbuffer_testing_use_sendfile()) + tt_skip(); + TT_BLATHER(("Using sendfile-based implementaion")); + } else if (!strcmp(impl, "mmap")) { + if (!_evbuffer_testing_use_mmap()) + tt_skip(); + TT_BLATHER(("Using mmap-based implementaion")); + } else if (!strcmp(impl, "linear")) { + if (!_evbuffer_testing_use_linear_file_access()) + tt_skip(); + TT_BLATHER(("Using read-based implementaion")); + } else { + TT_DIE(("Didn't recognize the implementation")); + } + + /* Say that it drains to a fd so that we can use sendfile. */ + evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD); + +#if defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__) + /* We need to use a pair of AF_INET sockets, since Solaris + doesn't support sendfile() over AF_UNIX. */ + if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, pair) == -1) + tt_abort_msg("ersatz_socketpair failed"); +#else + if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) + tt_abort_msg("socketpair failed"); +#endif + + datalen = strlen(data); + fd = regress_make_tmpfile(data, datalen); + + tt_assert(fd != -1); + + tt_assert(evbuffer_add_file(src, fd, 0, datalen) != -1); + + evbuffer_validate(src); + + while (evbuffer_get_length(src) && + (r = evbuffer_write(src, pair[0])) > 0) { + evbuffer_validate(src); + n_written += r; + } + tt_int_op(r, !=, -1); + tt_int_op(n_written, ==, datalen); + + evbuffer_validate(src); + tt_int_op(evbuffer_read(src, pair[1], (int)strlen(data)), ==, datalen); + evbuffer_validate(src); + compare = (char *)evbuffer_pullup(src, datalen); + tt_assert(compare != NULL); + if (memcmp(compare, data, datalen)) + tt_abort_msg("Data from add_file differs."); + + evbuffer_validate(src); + end: + if (pair[0] >= 0) + evutil_closesocket(pair[0]); + if (pair[1] >= 0) + evutil_closesocket(pair[1]); + evbuffer_free(src); +} + +#ifndef _EVENT_DISABLE_MM_REPLACEMENT +static void * +failing_malloc(size_t how_much) +{ + errno = ENOMEM; + return NULL; +} +#endif + +static void +test_evbuffer_readln(void *ptr) +{ + struct evbuffer *evb = evbuffer_new(); + struct evbuffer *evb_tmp = evbuffer_new(); + const char *s; + char *cp = NULL; + size_t sz; + +#define tt_line_eq(content) \ + TT_STMT_BEGIN \ + if (!cp || sz != strlen(content) || strcmp(cp, content)) { \ + TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \ + } \ + TT_STMT_END + + /* Test EOL_ANY. */ + s = "complex silly newline\r\n\n\r\n\n\rmore\0\n"; + evbuffer_add(evb, s, strlen(s)+2); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); + tt_line_eq("complex silly newline"); + free(cp); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); + if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6)) + tt_abort_msg("Not as expected"); + tt_uint_op(evbuffer_get_length(evb), ==, 0); + evbuffer_validate(evb); + s = "\nno newline"; + evbuffer_add(evb, s, strlen(s)); + free(cp); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); + tt_line_eq(""); + free(cp); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); + tt_assert(!cp); + evbuffer_validate(evb); + evbuffer_drain(evb, evbuffer_get_length(evb)); + tt_assert(evbuffer_get_length(evb) == 0); + evbuffer_validate(evb); + + /* Test EOL_CRLF */ + s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n"; + evbuffer_add(evb, s, strlen(s)); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); + tt_line_eq("Line with\rin the middle"); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); + tt_line_eq("Line with good crlf"); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); + tt_line_eq(""); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); + tt_line_eq("final"); + s = "x"; + evbuffer_validate(evb); + evbuffer_add(evb, s, 1); + evbuffer_validate(evb); + free(cp); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); + tt_assert(!cp); + evbuffer_validate(evb); + + /* Test CRLF_STRICT */ + s = " and a bad crlf\nand a good one\r\n\r\nMore\r"; + evbuffer_add(evb, s, strlen(s)); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq("x and a bad crlf\nand a good one"); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq(""); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_assert(!cp); + evbuffer_validate(evb); + evbuffer_add(evb, "\n", 1); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq("More"); + free(cp); + tt_assert(evbuffer_get_length(evb) == 0); + evbuffer_validate(evb); + + s = "An internal CR\r is not an eol\r\nNor is a lack of one"; + evbuffer_add(evb, s, strlen(s)); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq("An internal CR\r is not an eol"); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_assert(!cp); + evbuffer_validate(evb); + + evbuffer_add(evb, "\r\n", 2); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq("Nor is a lack of one"); + free(cp); + tt_assert(evbuffer_get_length(evb) == 0); + evbuffer_validate(evb); + + /* Test LF */ + s = "An\rand a nl\n\nText"; + evbuffer_add(evb, s, strlen(s)); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_line_eq("An\rand a nl"); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_line_eq(""); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_assert(!cp); + free(cp); + evbuffer_add(evb, "\n", 1); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_line_eq("Text"); + free(cp); + evbuffer_validate(evb); + + /* Test CRLF_STRICT - across boundaries*/ + s = " and a bad crlf\nand a good one\r"; + evbuffer_add(evb_tmp, s, strlen(s)); + evbuffer_validate(evb); + evbuffer_add_buffer(evb, evb_tmp); + evbuffer_validate(evb); + s = "\n\r"; + evbuffer_add(evb_tmp, s, strlen(s)); + evbuffer_validate(evb); + evbuffer_add_buffer(evb, evb_tmp); + evbuffer_validate(evb); + s = "\nMore\r"; + evbuffer_add(evb_tmp, s, strlen(s)); + evbuffer_validate(evb); + evbuffer_add_buffer(evb, evb_tmp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq(" and a bad crlf\nand a good one"); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq(""); + free(cp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_assert(!cp); + free(cp); + evbuffer_validate(evb); + evbuffer_add(evb, "\n", 1); + evbuffer_validate(evb); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); + tt_line_eq("More"); + free(cp); cp = NULL; + evbuffer_validate(evb); + tt_assert(evbuffer_get_length(evb) == 0); + + /* Test memory problem*/ + s = "one line\ntwo line\nblue line"; + evbuffer_add(evb_tmp, s, strlen(s)); + evbuffer_validate(evb); + evbuffer_add_buffer(evb, evb_tmp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_line_eq("one line"); + free(cp); cp = NULL; + evbuffer_validate(evb); + + /* the next call to readline should fail */ +#ifndef _EVENT_DISABLE_MM_REPLACEMENT + event_set_mem_functions(failing_malloc, realloc, free); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_assert(cp == NULL); + evbuffer_validate(evb); + + /* now we should get the next line back */ + event_set_mem_functions(malloc, realloc, free); +#endif + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_line_eq("two line"); + free(cp); cp = NULL; + evbuffer_validate(evb); + + end: + evbuffer_free(evb); + evbuffer_free(evb_tmp); + if (cp) free(cp); +} + +static void +test_evbuffer_search_eol(void *ptr) +{ + struct evbuffer *buf = evbuffer_new(); + struct evbuffer_ptr ptr1, ptr2; + const char *s; + size_t eol_len; + + s = "string! \r\n\r\nx\n"; + evbuffer_add(buf, s, strlen(s)); + eol_len = -1; + ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF); + tt_int_op(ptr1.pos, ==, 8); + tt_int_op(eol_len, ==, 2); + + eol_len = -1; + ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF); + tt_int_op(ptr2.pos, ==, 8); + tt_int_op(eol_len, ==, 2); + + evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD); + eol_len = -1; + ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF); + tt_int_op(ptr2.pos, ==, 9); + tt_int_op(eol_len, ==, 1); + + eol_len = -1; + ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT); + tt_int_op(ptr2.pos, ==, 10); + tt_int_op(eol_len, ==, 2); + + eol_len = -1; + ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF); + tt_int_op(ptr1.pos, ==, 9); + tt_int_op(eol_len, ==, 1); + + eol_len = -1; + ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); + tt_int_op(ptr2.pos, ==, 9); + tt_int_op(eol_len, ==, 1); + + evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD); + eol_len = -1; + ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); + tt_int_op(ptr2.pos, ==, 11); + tt_int_op(eol_len, ==, 1); + +end: + evbuffer_free(buf); +} + +static void +test_evbuffer_iterative(void *ptr) +{ + struct evbuffer *buf = evbuffer_new(); + const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz"; + unsigned i, j, sum, n; + + sum = 0; + n = 0; + for (i = 0; i < 1000; ++i) { + for (j = 1; j < strlen(abc); ++j) { + char format[32]; + evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j); + evbuffer_add_printf(buf, format, abc); + + /* Only check for rep violations every so often. + Walking over the whole list of chains can get + pretty expensive as it gets long. + */ + if ((n % 337) == 0) + evbuffer_validate(buf); + + sum += j; + n++; + } + } + evbuffer_validate(buf); + + tt_uint_op(sum, ==, evbuffer_get_length(buf)); + + { + size_t a,w,u; + a=w=u=0; + evbuffer_get_waste(buf, &a, &w, &u); + if (0) + printf("Allocated: %u.\nWasted: %u.\nUsed: %u.", + (unsigned)a, (unsigned)w, (unsigned)u); + tt_assert( ((double)w)/a < .125); + } + end: + evbuffer_free(buf); + +} + +static void +test_evbuffer_find(void *ptr) +{ + u_char* p; + const char* test1 = "1234567890\r\n"; + const char* test2 = "1234567890\r"; +#define EVBUFFER_INITIAL_LENGTH 256 + char test3[EVBUFFER_INITIAL_LENGTH]; + unsigned int i; + struct evbuffer * buf = evbuffer_new(); + + /* make sure evbuffer_find doesn't match past the end of the buffer */ + evbuffer_add(buf, (u_char*)test1, strlen(test1)); + evbuffer_validate(buf); + evbuffer_drain(buf, strlen(test1)); + evbuffer_validate(buf); + evbuffer_add(buf, (u_char*)test2, strlen(test2)); + evbuffer_validate(buf); + p = evbuffer_find(buf, (u_char*)"\r\n", 2); + tt_want(p == NULL); + + /* + * drain the buffer and do another find; in r309 this would + * read past the allocated buffer causing a valgrind error. + */ + evbuffer_drain(buf, strlen(test2)); + evbuffer_validate(buf); + for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i) + test3[i] = 'a'; + test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x'; + evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH); + evbuffer_validate(buf); + p = evbuffer_find(buf, (u_char *)"xy", 2); + tt_want(p == NULL); + + /* simple test for match at end of allocated buffer */ + p = evbuffer_find(buf, (u_char *)"ax", 2); + tt_assert(p != NULL); + tt_want(strncmp((char*)p, "ax", 2) == 0); + +end: + if (buf) + evbuffer_free(buf); +} + +static void +test_evbuffer_ptr_set(void *ptr) +{ + struct evbuffer *buf = evbuffer_new(); + struct evbuffer_ptr pos; + struct evbuffer_iovec v[1]; + + /* create some chains */ + evbuffer_reserve_space(buf, 5000, v, 1); + v[0].iov_len = 5000; + memset(v[0].iov_base, 1, v[0].iov_len); + evbuffer_commit_space(buf, v, 1); + evbuffer_validate(buf); + + evbuffer_reserve_space(buf, 4000, v, 1); + v[0].iov_len = 4000; + memset(v[0].iov_base, 2, v[0].iov_len); + evbuffer_commit_space(buf, v, 1); + + evbuffer_reserve_space(buf, 3000, v, 1); + v[0].iov_len = 3000; + memset(v[0].iov_base, 3, v[0].iov_len); + evbuffer_commit_space(buf, v, 1); + evbuffer_validate(buf); + + tt_int_op(evbuffer_get_length(buf), ==, 12000); + + tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1); + tt_assert(pos.pos == -1); + tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); + tt_assert(pos.pos == 0); + tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1); + + tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); + tt_assert(pos.pos == 0); + tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0); + tt_assert(pos.pos == 10000); + tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0); + tt_assert(pos.pos == 11000); + tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1); + tt_assert(pos.pos == -1); + +end: + if (buf) + evbuffer_free(buf); +} + +static void +test_evbuffer_search(void *ptr) +{ + struct evbuffer *buf = evbuffer_new(); + struct evbuffer *tmp = evbuffer_new(); + struct evbuffer_ptr pos, end; + + /* set up our chains */ + evbuffer_add_printf(tmp, "hello"); /* 5 chars */ + evbuffer_add_buffer(buf, tmp); + evbuffer_add_printf(tmp, "foo"); /* 3 chars */ + evbuffer_add_buffer(buf, tmp); + evbuffer_add_printf(tmp, "cat"); /* 3 chars */ + evbuffer_add_buffer(buf, tmp); + evbuffer_add_printf(tmp, "attack"); + evbuffer_add_buffer(buf, tmp); + + pos = evbuffer_search(buf, "attack", 6, NULL); + tt_int_op(pos.pos, ==, 11); + pos = evbuffer_search(buf, "attacker", 8, NULL); + tt_int_op(pos.pos, ==, -1); + + /* test continuing search */ + pos = evbuffer_search(buf, "oc", 2, NULL); + tt_int_op(pos.pos, ==, 7); + pos = evbuffer_search(buf, "cat", 3, &pos); + tt_int_op(pos.pos, ==, 8); + pos = evbuffer_search(buf, "tacking", 7, &pos); + tt_int_op(pos.pos, ==, -1); + + evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET); + pos = evbuffer_search(buf, "foo", 3, &pos); + tt_int_op(pos.pos, ==, 5); + + evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD); + pos = evbuffer_search(buf, "tat", 3, &pos); + tt_int_op(pos.pos, ==, 10); + + /* test bounded search. */ + /* Set "end" to the first t in "attack". */ + evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET); + pos = evbuffer_search_range(buf, "foo", 3, NULL, &end); + tt_int_op(pos.pos, ==, 5); + pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end); + tt_int_op(pos.pos, ==, 5); + pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end); + tt_int_op(pos.pos, ==, -1); + pos = evbuffer_search_range(buf, "ack", 3, NULL, &end); + tt_int_op(pos.pos, ==, -1); + + +end: + if (buf) + evbuffer_free(buf); + if (tmp) + evbuffer_free(tmp); +} + +static void +log_change_callback(struct evbuffer *buffer, + const struct evbuffer_cb_info *cbinfo, + void *arg) +{ + + size_t old_len = cbinfo->orig_size; + size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted; + struct evbuffer *out = arg; + evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len, + (unsigned long)new_len); +} +static void +self_draining_callback(struct evbuffer *evbuffer, size_t old_len, + size_t new_len, void *arg) +{ + if (new_len > old_len) + evbuffer_drain(evbuffer, new_len); +} + +static void +test_evbuffer_callbacks(void *ptr) +{ + struct evbuffer *buf = evbuffer_new(); + struct evbuffer *buf_out1 = evbuffer_new(); + struct evbuffer *buf_out2 = evbuffer_new(); + struct evbuffer_cb_entry *cb1, *cb2; + + cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); + cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); + + /* Let's run through adding and deleting some stuff from the buffer + * and turning the callbacks on and off and removing them. The callback + * adds a summary of length changes to buf_out1/buf_out2 when called. */ + /* size: 0-> 36. */ + evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2); + evbuffer_validate(buf); + evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED); + evbuffer_drain(buf, 10); /*36->26*/ + evbuffer_validate(buf); + evbuffer_prepend(buf, "Hello", 5);/*26->31*/ + evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED); + evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/ + evbuffer_remove_cb_entry(buf, cb1); + evbuffer_validate(buf); + evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/; + tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL)); + evbuffer_add(buf, "X", 1); /* 0->1 */ + tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2)); + evbuffer_validate(buf); + + tt_str_op(evbuffer_pullup(buf_out1, -1), ==, + "0->36; 36->26; 26->31; 31->38; "); + tt_str_op(evbuffer_pullup(buf_out2, -1), ==, + "0->36; 31->38; 38->0; 0->1; "); + evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1)); + evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2)); + /* Let's test the obsolete buffer_setcb function too. */ + cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); + tt_assert(cb1 != NULL); + cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); + tt_assert(cb2 != NULL); + evbuffer_setcb(buf, self_draining_callback, NULL); + evbuffer_add_printf(buf, "This should get drained right away."); + tt_uint_op(evbuffer_get_length(buf), ==, 0); + tt_uint_op(evbuffer_get_length(buf_out1), ==, 0); + tt_uint_op(evbuffer_get_length(buf_out2), ==, 0); + evbuffer_setcb(buf, NULL, NULL); + evbuffer_add_printf(buf, "This will not."); + tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not."); + evbuffer_validate(buf); + evbuffer_drain(buf, evbuffer_get_length(buf)); + evbuffer_validate(buf); +#if 0 + /* Now let's try a suspended callback. */ + cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); + cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); + evbuffer_cb_suspend(buf,cb2); + evbuffer_prepend(buf,"Hello world",11); /*0->11*/ + evbuffer_validate(buf); + evbuffer_cb_suspend(buf,cb1); + evbuffer_add(buf,"more",4); /* 11->15 */ + evbuffer_cb_unsuspend(buf,cb2); + evbuffer_drain(buf, 4); /* 15->11 */ + evbuffer_cb_unsuspend(buf,cb1); + evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */ + + tt_str_op(evbuffer_pullup(buf_out1, -1), ==, + "0->11; 11->11; 11->0; "); + tt_str_op(evbuffer_pullup(buf_out2, -1), ==, + "0->15; 15->11; 11->0; "); +#endif + + end: + if (buf) + evbuffer_free(buf); + if (buf_out1) + evbuffer_free(buf_out1); + if (buf_out2) + evbuffer_free(buf_out2); +} + +static int ref_done_cb_called_count = 0; +static void *ref_done_cb_called_with = NULL; +static const void *ref_done_cb_called_with_data = NULL; +static size_t ref_done_cb_called_with_len = 0; +static void ref_done_cb(const void *data, size_t len, void *info) +{ + ++ref_done_cb_called_count; + ref_done_cb_called_with = info; + ref_done_cb_called_with_data = data; + ref_done_cb_called_with_len = len; +} + +static void +test_evbuffer_add_reference(void *ptr) +{ + const char chunk1[] = "If you have found the answer to such a problem"; + const char chunk2[] = "you ought to write it up for publication"; + /* -- Knuth's "Notes on the Exercises" from TAOCP */ + char tmp[16]; + size_t len1 = strlen(chunk1), len2=strlen(chunk2); + + struct evbuffer *buf1 = NULL, *buf2 = NULL; + + buf1 = evbuffer_new(); + tt_assert(buf1); + + evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111); + evbuffer_add(buf1, ", ", 2); + evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222); + tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2); + + /* Make sure we can drain a little from a reference. */ + tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6); + tt_int_op(memcmp(tmp, "If you", 6), ==, 0); + tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5); + tt_int_op(memcmp(tmp, " have", 5), ==, 0); + + /* Make sure that prepending does not meddle with immutable data */ + tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0); + tt_int_op(memcmp(chunk1, "If you", 6), ==, 0); + evbuffer_validate(buf1); + + /* Make sure that when the chunk is over, the callback is invoked. */ + evbuffer_drain(buf1, 7); /* Remove prepended stuff. */ + evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */ + tt_int_op(ref_done_cb_called_count, ==, 0); + evbuffer_remove(buf1, tmp, 1); + tt_int_op(tmp[0], ==, 'm'); + tt_assert(ref_done_cb_called_with == (void*)111); + tt_assert(ref_done_cb_called_with_data == chunk1); + tt_assert(ref_done_cb_called_with_len == len1); + tt_int_op(ref_done_cb_called_count, ==, 1); + evbuffer_validate(buf1); + + /* Drain some of the remaining chunk, then add it to another buffer */ + evbuffer_drain(buf1, 6); /* Remove the ", you ". */ + buf2 = evbuffer_new(); + tt_assert(buf2); + tt_int_op(ref_done_cb_called_count, ==, 1); + evbuffer_add(buf2, "I ", 2); + + evbuffer_add_buffer(buf2, buf1); + tt_int_op(ref_done_cb_called_count, ==, 1); + evbuffer_remove(buf2, tmp, 16); + tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0); + evbuffer_drain(buf2, evbuffer_get_length(buf2)); + tt_int_op(ref_done_cb_called_count, ==, 2); + tt_assert(ref_done_cb_called_with == (void*)222); + evbuffer_validate(buf2); + + /* Now add more stuff to buf1 and make sure that it gets removed on + * free. */ + evbuffer_add(buf1, "You shake and shake the ", 24); + evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb, + (void*)3333); + evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42); + evbuffer_free(buf1); + buf1 = NULL; + tt_int_op(ref_done_cb_called_count, ==, 3); + tt_assert(ref_done_cb_called_with == (void*)3333); + +end: + if (buf1) + evbuffer_free(buf1); + if (buf2) + evbuffer_free(buf2); +} + +/* Some cases that we didn't get in test_evbuffer() above, for more coverage. */ +static void +test_evbuffer_prepend(void *ptr) +{ + struct evbuffer *buf1 = NULL, *buf2 = NULL; + char tmp[128]; + int n; + + buf1 = evbuffer_new(); + tt_assert(buf1); + + /* Case 0: The evbuffer is entirely empty. */ + evbuffer_prepend(buf1, "This string has 29 characters", 29); + evbuffer_validate(buf1); + + /* Case 1: Prepend goes entirely in new chunk. */ + evbuffer_prepend(buf1, "Short.", 6); + evbuffer_validate(buf1); + + /* Case 2: prepend goes entirely in first chunk. */ + evbuffer_drain(buf1, 6+11); + evbuffer_prepend(buf1, "it", 2); + evbuffer_validate(buf1); + tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign, + "it has", 6)); + + /* Case 3: prepend is split over multiple chunks. */ + evbuffer_prepend(buf1, "It is no longer true to say ", 28); + evbuffer_validate(buf1); + n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1); + tmp[n]='\0'; + tt_str_op(tmp,==,"It is no longer true to say it has 29 characters"); + + buf2 = evbuffer_new(); + tt_assert(buf2); + + /* Case 4: prepend a buffer to an empty buffer. */ + n = 999; + evbuffer_add_printf(buf1, "Here is string %d. ", n++); + evbuffer_prepend_buffer(buf2, buf1); + evbuffer_validate(buf2); + + /* Case 5: prepend a buffer to a nonempty buffer. */ + evbuffer_add_printf(buf1, "Here is string %d. ", n++); + evbuffer_prepend_buffer(buf2, buf1); + evbuffer_validate(buf2); + evbuffer_validate(buf1); + n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1); + tmp[n]='\0'; + tt_str_op(tmp,==,"Here is string 1000. Here is string 999. "); + +end: + if (buf1) + evbuffer_free(buf1); + if (buf2) + evbuffer_free(buf2); + +} + +static void +test_evbuffer_peek(void *info) +{ + struct evbuffer *buf = NULL, *tmp_buf = NULL; + int i; + struct evbuffer_iovec v[20]; + struct evbuffer_ptr ptr; + +#define tt_iov_eq(v, s) \ + tt_int_op((v)->iov_len, ==, strlen(s)); \ + tt_assert(!memcmp((v)->iov_base, (s), strlen(s))) + + /* Let's make a very fragmented buffer. */ + buf = evbuffer_new(); + tmp_buf = evbuffer_new(); + for (i = 0; i < 16; ++i) { + evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i); + evbuffer_add_buffer(buf, tmp_buf); + } + + /* How many chunks do we need for everything? */ + i = evbuffer_peek(buf, -1, NULL, NULL, 0); + tt_int_op(i, ==, 16); + + /* Simple peek: get everything. */ + i = evbuffer_peek(buf, -1, NULL, v, 20); + tt_int_op(i, ==, 16); /* we used only 16 chunks. */ + tt_iov_eq(&v[0], "Contents of chunk [0]\n"); + tt_iov_eq(&v[3], "Contents of chunk [3]\n"); + tt_iov_eq(&v[12], "Contents of chunk [12]\n"); + tt_iov_eq(&v[15], "Contents of chunk [15]\n"); + + /* Just get one chunk worth. */ + memset(v, 0, sizeof(v)); + i = evbuffer_peek(buf, -1, NULL, v, 1); + tt_int_op(i, ==, 1); + tt_iov_eq(&v[0], "Contents of chunk [0]\n"); + tt_assert(v[1].iov_base == NULL); + + /* Suppose we want at least the first 40 bytes. */ + memset(v, 0, sizeof(v)); + i = evbuffer_peek(buf, 40, NULL, v, 16); + tt_int_op(i, ==, 2); + tt_iov_eq(&v[0], "Contents of chunk [0]\n"); + tt_iov_eq(&v[1], "Contents of chunk [1]\n"); + tt_assert(v[2].iov_base == NULL); + + /* How many chunks do we need for 100 bytes? */ + memset(v, 0, sizeof(v)); + i = evbuffer_peek(buf, 100, NULL, NULL, 0); + tt_int_op(i, ==, 5); + tt_assert(v[0].iov_base == NULL); + + /* Now we ask for more bytes than we provide chunks for */ + memset(v, 0, sizeof(v)); + i = evbuffer_peek(buf, 60, NULL, v, 1); + tt_int_op(i, ==, 3); + tt_iov_eq(&v[0], "Contents of chunk [0]\n"); + tt_assert(v[1].iov_base == NULL); + + /* Now we ask for more bytes than the buffer has. */ + memset(v, 0, sizeof(v)); + i = evbuffer_peek(buf, 65536, NULL, v, 20); + tt_int_op(i, ==, 16); /* we used only 16 chunks. */ + tt_iov_eq(&v[0], "Contents of chunk [0]\n"); + tt_iov_eq(&v[3], "Contents of chunk [3]\n"); + tt_iov_eq(&v[12], "Contents of chunk [12]\n"); + tt_iov_eq(&v[15], "Contents of chunk [15]\n"); + tt_assert(v[16].iov_base == NULL); + + /* What happens if we try an empty buffer? */ + memset(v, 0, sizeof(v)); + i = evbuffer_peek(tmp_buf, -1, NULL, v, 20); + tt_int_op(i, ==, 0); + tt_assert(v[0].iov_base == NULL); + memset(v, 0, sizeof(v)); + i = evbuffer_peek(tmp_buf, 50, NULL, v, 20); + tt_int_op(i, ==, 0); + tt_assert(v[0].iov_base == NULL); + + /* Okay, now time to have fun with pointers. */ + memset(v, 0, sizeof(v)); + evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET); + i = evbuffer_peek(buf, 50, &ptr, v, 20); + tt_int_op(i, ==, 3); + tt_iov_eq(&v[0], " of chunk [1]\n"); + tt_iov_eq(&v[1], "Contents of chunk [2]\n"); + tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/ + + /* advance to the start of another chain. */ + memset(v, 0, sizeof(v)); + evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD); + i = evbuffer_peek(buf, 44, &ptr, v, 20); + tt_int_op(i, ==, 2); + tt_iov_eq(&v[0], "Contents of chunk [2]\n"); + tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/ + +end: + if (buf) + evbuffer_free(buf); + if (tmp_buf) + evbuffer_free(tmp_buf); +} + +/* Check whether evbuffer freezing works right. This is called twice, + once with the argument "start" and once with the argument "end". + When we test "start", we freeze the start of an evbuffer and make sure + that modifying the start of the buffer doesn't work. When we test + "end", we freeze the end of an evbuffer and make sure that modifying + the end of the buffer doesn't work. + */ +static void +test_evbuffer_freeze(void *ptr) +{ + struct evbuffer *buf = NULL, *tmp_buf=NULL; + const char string[] = /* Year's End, Richard Wilbur */ + "I've known the wind by water banks to shake\n" + "The late leaves down, which frozen where they fell\n" + "And held in ice as dancers in a spell\n" + "Fluttered all winter long into a lake..."; + const int start = !strcmp(ptr, "start"); + char *cp; + char charbuf[128]; + int r; + size_t orig_length; + struct evbuffer_iovec v[1]; + + if (!start) + tt_str_op(ptr, ==, "end"); + + buf = evbuffer_new(); + tmp_buf = evbuffer_new(); + tt_assert(tmp_buf); + + evbuffer_add(buf, string, strlen(string)); + evbuffer_freeze(buf, start); /* Freeze the start or the end.*/ + +#define FREEZE_EQ(a, startcase, endcase) \ + do { \ + if (start) { \ + tt_int_op((a), ==, (startcase)); \ + } else { \ + tt_int_op((a), ==, (endcase)); \ + } \ + } while (0) + + + orig_length = evbuffer_get_length(buf); + + /* These functions all manipulate the end of buf. */ + r = evbuffer_add(buf, "abc", 0); + FREEZE_EQ(r, 0, -1); + r = evbuffer_reserve_space(buf, 10, v, 1); + FREEZE_EQ(r, 1, -1); + if (r == 0) { + memset(v[0].iov_base, 'X', 10); + v[0].iov_len = 10; + } + r = evbuffer_commit_space(buf, v, 1); + FREEZE_EQ(r, 0, -1); + r = evbuffer_add_reference(buf, string, 5, NULL, NULL); + FREEZE_EQ(r, 0, -1); + r = evbuffer_add_printf(buf, "Hello %s", "world"); + FREEZE_EQ(r, 11, -1); + /* TODO: test add_buffer, add_file, read */ + + if (!start) + tt_int_op(orig_length, ==, evbuffer_get_length(buf)); + + orig_length = evbuffer_get_length(buf); + + /* These functions all manipulate the start of buf. */ + r = evbuffer_remove(buf, charbuf, 1); + FREEZE_EQ(r, -1, 1); + r = evbuffer_drain(buf, 3); + FREEZE_EQ(r, -1, 0); + r = evbuffer_prepend(buf, "dummy", 5); + FREEZE_EQ(r, -1, 0); + cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF); + FREEZE_EQ(cp==NULL, 1, 0); + if (cp) + free(cp); + /* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */ + + if (start) + tt_int_op(orig_length, ==, evbuffer_get_length(buf)); + +end: + if (buf) + evbuffer_free(buf); + + if (tmp_buf) + evbuffer_free(tmp_buf); +} + +static void * +setup_passthrough(const struct testcase_t *testcase) +{ + return testcase->setup_data; +} +static int +cleanup_passthrough(const struct testcase_t *testcase, void *ptr) +{ + (void) ptr; + return 1; +} + +static const struct testcase_setup_t nil_setup = { + setup_passthrough, + cleanup_passthrough +}; + +struct testcase_t evbuffer_testcases[] = { + { "evbuffer", test_evbuffer, 0, NULL, NULL }, + { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL }, + { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL }, + { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL }, + { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" }, + { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" }, + { "expand", test_evbuffer_expand, 0, NULL, NULL }, + { "reference", test_evbuffer_reference, 0, NULL, NULL }, + { "iterative", test_evbuffer_iterative, 0, NULL, NULL }, + { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL }, + { "search_eol", test_evbuffer_search_eol, 0, NULL, NULL }, + { "find", test_evbuffer_find, 0, NULL, NULL }, + { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL }, + { "search", test_evbuffer_search, 0, NULL, NULL }, + { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL }, + { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL }, + { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL }, + { "peek", test_evbuffer_peek, 0, NULL, NULL }, + { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" }, + { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" }, + /* TODO: need a temp file implementation for Windows */ + { "add_file_sendfile", test_evbuffer_add_file, TT_FORK, &nil_setup, + (void*)"sendfile" }, + { "add_file_mmap", test_evbuffer_add_file, TT_FORK, &nil_setup, + (void*)"mmap" }, + { "add_file_linear", test_evbuffer_add_file, TT_FORK, &nil_setup, + (void*)"linear" }, + + END_OF_TESTCASES +}; diff --git a/libevent/test/regress_bufferevent.c b/libevent/test/regress_bufferevent.c new file mode 100644 index 0000000..2a7097c --- /dev/null +++ b/libevent/test/regress_bufferevent.c @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2003-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +/* The old tests here need assertions to work. */ +#undef NDEBUG + +#ifdef WIN32 +#include +#include +#endif + +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#ifndef WIN32 +#include +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#ifdef _EVENT_HAVE_ARPA_INET_H +#include +#endif + +#include "event2/event-config.h" +#include "event2/event.h" +#include "event2/event_struct.h" +#include "event2/event_compat.h" +#include "event2/tag.h" +#include "event2/buffer.h" +#include "event2/bufferevent.h" +#include "event2/bufferevent_compat.h" +#include "event2/bufferevent_struct.h" +#include "event2/listener.h" +#include "event2/util.h" + +#include "bufferevent-internal.h" +#ifdef WIN32 +#include "iocp-internal.h" +#endif + +#include "regress.h" +#include "regress_testutils.h" + +/* + * simple bufferevent test + */ + +static void +readcb(struct bufferevent *bev, void *arg) +{ + if (evbuffer_get_length(bev->input) == 8333) { + struct evbuffer *evbuf = evbuffer_new(); + assert(evbuf != NULL); + + /* gratuitous test of bufferevent_read_buffer */ + bufferevent_read_buffer(bev, evbuf); + + bufferevent_disable(bev, EV_READ); + + if (evbuffer_get_length(evbuf) == 8333) { + test_ok++; + } + + evbuffer_free(evbuf); + } +} + +static void +writecb(struct bufferevent *bev, void *arg) +{ + if (evbuffer_get_length(bev->output) == 0) { + test_ok++; + } +} + +static void +errorcb(struct bufferevent *bev, short what, void *arg) +{ + test_ok = -2; +} + +static void +test_bufferevent_impl(int use_pair) +{ + struct bufferevent *bev1 = NULL, *bev2 = NULL; + char buffer[8333]; + int i; + + if (use_pair) { + struct bufferevent *pair[2]; + tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); + bev1 = pair[0]; + bev2 = pair[1]; + bufferevent_setcb(bev1, readcb, writecb, errorcb, NULL); + bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL); + tt_int_op(bufferevent_getfd(bev1), ==, -1); + tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); + tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, bev2); + tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, bev1); + } else { + bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL); + bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL); + tt_int_op(bufferevent_getfd(bev1), ==, pair[0]); + tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL); + tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL); + tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); + } + + bufferevent_disable(bev1, EV_READ); + bufferevent_enable(bev2, EV_READ); + + tt_int_op(bufferevent_get_enabled(bev1), ==, EV_WRITE); + tt_int_op(bufferevent_get_enabled(bev2), ==, EV_WRITE|EV_READ); + + for (i = 0; i < (int)sizeof(buffer); i++) + buffer[i] = i; + + bufferevent_write(bev1, buffer, sizeof(buffer)); + + event_dispatch(); + + bufferevent_free(bev1); + tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL); + bufferevent_free(bev2); + + if (test_ok != 2) + test_ok = 0; +end: + ; +} + +static void +test_bufferevent(void) +{ + test_bufferevent_impl(0); +} + +static void +test_bufferevent_pair(void) +{ + test_bufferevent_impl(1); +} + +/* + * test watermarks and bufferevent + */ + +static void +wm_readcb(struct bufferevent *bev, void *arg) +{ + struct evbuffer *evbuf = evbuffer_new(); + int len = (int)evbuffer_get_length(bev->input); + static int nread; + + assert(len >= 10 && len <= 20); + + assert(evbuf != NULL); + + /* gratuitous test of bufferevent_read_buffer */ + bufferevent_read_buffer(bev, evbuf); + + nread += len; + if (nread == 65000) { + bufferevent_disable(bev, EV_READ); + test_ok++; + } + + evbuffer_free(evbuf); +} + +static void +wm_writecb(struct bufferevent *bev, void *arg) +{ + assert(evbuffer_get_length(bev->output) <= 100); + if (evbuffer_get_length(bev->output) == 0) { + evbuffer_drain(bev->output, evbuffer_get_length(bev->output)); + test_ok++; + } +} + +static void +wm_errorcb(struct bufferevent *bev, short what, void *arg) +{ + test_ok = -2; +} + +static void +test_bufferevent_watermarks_impl(int use_pair) +{ + struct bufferevent *bev1 = NULL, *bev2 = NULL; + char buffer[65000]; + int i; + test_ok = 0; + + if (use_pair) { + struct bufferevent *pair[2]; + tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); + bev1 = pair[0]; + bev2 = pair[1]; + bufferevent_setcb(bev1, NULL, wm_writecb, errorcb, NULL); + bufferevent_setcb(bev2, wm_readcb, NULL, errorcb, NULL); + } else { + bev1 = bufferevent_new(pair[0], NULL, wm_writecb, wm_errorcb, NULL); + bev2 = bufferevent_new(pair[1], wm_readcb, NULL, wm_errorcb, NULL); + } + bufferevent_disable(bev1, EV_READ); + bufferevent_enable(bev2, EV_READ); + + for (i = 0; i < (int)sizeof(buffer); i++) + buffer[i] = (char)i; + + /* limit the reading on the receiving bufferevent */ + bufferevent_setwatermark(bev2, EV_READ, 10, 20); + + /* Tell the sending bufferevent not to notify us till it's down to + 100 bytes. */ + bufferevent_setwatermark(bev1, EV_WRITE, 100, 2000); + + bufferevent_write(bev1, buffer, sizeof(buffer)); + + event_dispatch(); + + tt_int_op(test_ok, ==, 2); + + /* The write callback drained all the data from outbuf, so we + * should have removed the write event... */ + tt_assert(!event_pending(&bev2->ev_write, EV_WRITE, NULL)); + +end: + bufferevent_free(bev1); + bufferevent_free(bev2); +} + +static void +test_bufferevent_watermarks(void) +{ + test_bufferevent_watermarks_impl(0); +} + +static void +test_bufferevent_pair_watermarks(void) +{ + test_bufferevent_watermarks_impl(1); +} + +/* + * Test bufferevent filters + */ + +/* strip an 'x' from each byte */ + +static enum bufferevent_filter_result +bufferevent_input_filter(struct evbuffer *src, struct evbuffer *dst, + ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) +{ + const unsigned char *buffer; + unsigned i; + + buffer = evbuffer_pullup(src, evbuffer_get_length(src)); + for (i = 0; i < evbuffer_get_length(src); i += 2) { + assert(buffer[i] == 'x'); + evbuffer_add(dst, buffer + i + 1, 1); + + if (i + 2 > evbuffer_get_length(src)) + break; + } + + evbuffer_drain(src, i); + return (BEV_OK); +} + +/* add an 'x' before each byte */ + +static enum bufferevent_filter_result +bufferevent_output_filter(struct evbuffer *src, struct evbuffer *dst, + ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) +{ + const unsigned char *buffer; + unsigned i; + + buffer = evbuffer_pullup(src, evbuffer_get_length(src)); + for (i = 0; i < evbuffer_get_length(src); ++i) { + evbuffer_add(dst, "x", 1); + evbuffer_add(dst, buffer + i, 1); + } + + evbuffer_drain(src, evbuffer_get_length(src)); + return (BEV_OK); +} + +static void +test_bufferevent_filters_impl(int use_pair) +{ + struct bufferevent *bev1 = NULL, *bev2 = NULL; + struct bufferevent *bev1_base = NULL, *bev2_base = NULL; + char buffer[8333]; + int i; + + test_ok = 0; + + if (use_pair) { + struct bufferevent *pair[2]; + tt_assert(0 == bufferevent_pair_new(NULL, 0, pair)); + bev1 = pair[0]; + bev2 = pair[1]; + } else { + bev1 = bufferevent_socket_new(NULL, pair[0], 0); + bev2 = bufferevent_socket_new(NULL, pair[1], 0); + } + bev1_base = bev1; + bev2_base = bev2; + + for (i = 0; i < (int)sizeof(buffer); i++) + buffer[i] = i; + + bev1 = bufferevent_filter_new(bev1, NULL, bufferevent_output_filter, + BEV_OPT_CLOSE_ON_FREE, NULL, NULL); + + bev2 = bufferevent_filter_new(bev2, bufferevent_input_filter, + NULL, BEV_OPT_CLOSE_ON_FREE, NULL, NULL); + bufferevent_setcb(bev1, NULL, writecb, errorcb, NULL); + bufferevent_setcb(bev2, readcb, NULL, errorcb, NULL); + + tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev1_base); + tt_ptr_op(bufferevent_get_underlying(bev2), ==, bev2_base); + tt_int_op(bufferevent_getfd(bev1), ==, -1); + tt_int_op(bufferevent_getfd(bev2), ==, -1); + + bufferevent_disable(bev1, EV_READ); + bufferevent_enable(bev2, EV_READ); + /* insert some filters */ + bufferevent_write(bev1, buffer, sizeof(buffer)); + + event_dispatch(); + + if (test_ok != 2) + test_ok = 0; + +end: + bufferevent_free(bev1); + bufferevent_free(bev2); + +} + +static void +test_bufferevent_filters(void) +{ + test_bufferevent_filters_impl(0); +} + +static void +test_bufferevent_pair_filters(void) +{ + test_bufferevent_filters_impl(1); +} + + +static void +sender_writecb(struct bufferevent *bev, void *ctx) +{ + if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { + bufferevent_disable(bev,EV_READ|EV_WRITE); + bufferevent_free(bev); + } +} + +static void +sender_errorcb(struct bufferevent *bev, short what, void *ctx) +{ + TT_FAIL(("Got sender error %d",(int)what)); +} + +static int bufferevent_connect_test_flags = 0; +static int n_strings_read = 0; +static int n_reads_invoked = 0; + +#define TEST_STR "Now is the time for all good events to signal for " \ + "the good of their protocol" +static void +listen_cb(struct evconnlistener *listener, evutil_socket_t fd, + struct sockaddr *sa, int socklen, void *arg) +{ + struct event_base *base = arg; + struct bufferevent *bev; + const char s[] = TEST_STR; + TT_BLATHER(("Got a request on socket %d", (int)fd )); + bev = bufferevent_socket_new(base, fd, bufferevent_connect_test_flags); + tt_assert(bev); + bufferevent_setcb(bev, NULL, sender_writecb, sender_errorcb, NULL); + bufferevent_write(bev, s, sizeof(s)); +end: + ; +} + +static void +reader_eventcb(struct bufferevent *bev, short what, void *ctx) +{ + struct event_base *base = ctx; + if (what & BEV_EVENT_ERROR) { + perror("foobar"); + TT_FAIL(("got connector error %d", (int)what)); + return; + } + if (what & BEV_EVENT_CONNECTED) { + bufferevent_enable(bev, EV_READ); + } + if (what & BEV_EVENT_EOF) { + char buf[512]; + size_t n; + n = bufferevent_read(bev, buf, sizeof(buf)-1); + buf[n] = '\0'; + tt_str_op(buf, ==, TEST_STR); + if (++n_strings_read == 2) + event_base_loopexit(base, NULL); + } +end: + ; +} + +static void +reader_readcb(struct bufferevent *bev, void *ctx) +{ + n_reads_invoked++; +} + +static void +test_bufferevent_connect(void *arg) +{ + struct basic_test_data *data = arg; + struct evconnlistener *lev=NULL; + struct bufferevent *bev1=NULL, *bev2=NULL; + struct sockaddr_in localhost; + struct sockaddr_storage ss; + struct sockaddr *sa; + ev_socklen_t slen; + + int be_flags=BEV_OPT_CLOSE_ON_FREE; + + if (strstr((char*)data->setup_data, "defer")) { + be_flags |= BEV_OPT_DEFER_CALLBACKS; + } + if (strstr((char*)data->setup_data, "unlocked")) { + be_flags |= BEV_OPT_UNLOCK_CALLBACKS; + } + if (strstr((char*)data->setup_data, "lock")) { + be_flags |= BEV_OPT_THREADSAFE; + } + bufferevent_connect_test_flags = be_flags; +#ifdef WIN32 + if (!strcmp((char*)data->setup_data, "unset_connectex")) { + struct win32_extension_fns *ext = + (struct win32_extension_fns *) + event_get_win32_extension_fns(); + ext->ConnectEx = NULL; + } +#endif + + memset(&localhost, 0, sizeof(localhost)); + + localhost.sin_port = 0; /* pick-a-port */ + localhost.sin_addr.s_addr = htonl(0x7f000001L); + localhost.sin_family = AF_INET; + sa = (struct sockaddr *)&localhost; + lev = evconnlistener_new_bind(data->base, listen_cb, data->base, + LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, + 16, sa, sizeof(localhost)); + tt_assert(lev); + + sa = (struct sockaddr *)&ss; + slen = sizeof(ss); + if (regress_get_listener_addr(lev, sa, &slen) < 0) { + tt_abort_perror("getsockname"); + } + + tt_assert(!evconnlistener_enable(lev)); + bev1 = bufferevent_socket_new(data->base, -1, be_flags); + bev2 = bufferevent_socket_new(data->base, -1, be_flags); + tt_assert(bev1); + tt_assert(bev2); + bufferevent_setcb(bev1, reader_readcb,NULL, reader_eventcb, data->base); + bufferevent_setcb(bev2, reader_readcb,NULL, reader_eventcb, data->base); + + bufferevent_enable(bev1, EV_READ); + bufferevent_enable(bev2, EV_READ); + + tt_want(!bufferevent_socket_connect(bev1, sa, sizeof(localhost))); + tt_want(!bufferevent_socket_connect(bev2, sa, sizeof(localhost))); + + event_base_dispatch(data->base); + + tt_int_op(n_strings_read, ==, 2); + tt_int_op(n_reads_invoked, >=, 2); +end: + if (lev) + evconnlistener_free(lev); + + if (bev1) + bufferevent_free(bev1); + + if (bev2) + bufferevent_free(bev2); +} + +static void +want_fail_eventcb(struct bufferevent *bev, short what, void *ctx) +{ + struct event_base *base = ctx; + const char *err; + evutil_socket_t s; + + if (what & BEV_EVENT_ERROR) { + s = bufferevent_getfd(bev); + err = evutil_socket_error_to_string(evutil_socket_geterror(s)); + TT_BLATHER(("connection failure on %d: %s", s, err)); + test_ok = 1; + } else { + TT_FAIL(("didn't fail? what %hd", what)); + } + + event_base_loopexit(base, NULL); +} + +static void +close_socket_cb(evutil_socket_t fd, short what, void *arg) +{ + evutil_socket_t *fdp = arg; + if (*fdp >= 0) { + evutil_closesocket(*fdp); + *fdp = -1; + } +} + +static void +test_bufferevent_connect_fail(void *arg) +{ + struct basic_test_data *data = arg; + struct bufferevent *bev=NULL; + struct sockaddr_in localhost; + struct sockaddr *sa = (struct sockaddr*)&localhost; + evutil_socket_t fake_listener = -1; + ev_socklen_t slen = sizeof(localhost); + struct event close_listener_event; + int close_listener_event_added = 0; + struct timeval one_second = { 1, 0 }; + int r; + + test_ok = 0; + + memset(&localhost, 0, sizeof(localhost)); + localhost.sin_port = 0; /* have the kernel pick a port */ + localhost.sin_addr.s_addr = htonl(0x7f000001L); + localhost.sin_family = AF_INET; + + /* bind, but don't listen or accept. should trigger + "Connection refused" reliably on most platforms. */ + fake_listener = socket(localhost.sin_family, SOCK_STREAM, 0); + tt_assert(fake_listener >= 0); + tt_assert(bind(fake_listener, sa, slen) == 0); + tt_assert(getsockname(fake_listener, sa, &slen) == 0); + bev = bufferevent_socket_new(data->base, -1, + BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); + tt_assert(bev); + bufferevent_setcb(bev, NULL, NULL, want_fail_eventcb, data->base); + + r = bufferevent_socket_connect(bev, sa, slen); + /* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells + * detects the error immediately, which is not really wrong of it. */ + tt_want(r == 0 || r == -1); + + /* Close the listener socket after a second. This should trigger + "connection refused" on some other platforms, including OSX. */ + evtimer_assign(&close_listener_event, data->base, close_socket_cb, + &fake_listener); + event_add(&close_listener_event, &one_second); + close_listener_event_added = 1; + + event_base_dispatch(data->base); + + tt_int_op(test_ok, ==, 1); + +end: + if (fake_listener >= 0) + evutil_closesocket(fake_listener); + + if (bev) + bufferevent_free(bev); + + if (close_listener_event_added) + event_del(&close_listener_event); +} + +struct timeout_cb_result { + struct timeval read_timeout_at; + struct timeval write_timeout_at; + struct timeval last_wrote_at; + int n_read_timeouts; + int n_write_timeouts; + int total_calls; +}; + +static void +bev_timeout_write_cb(struct bufferevent *bev, void *arg) +{ + struct timeout_cb_result *res = arg; + evutil_gettimeofday(&res->last_wrote_at, NULL); +} + +static void +bev_timeout_event_cb(struct bufferevent *bev, short what, void *arg) +{ + struct timeout_cb_result *res = arg; + ++res->total_calls; + + if ((what & (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) + == (BEV_EVENT_READING|BEV_EVENT_TIMEOUT)) { + evutil_gettimeofday(&res->read_timeout_at, NULL); + ++res->n_read_timeouts; + } + if ((what & (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) + == (BEV_EVENT_WRITING|BEV_EVENT_TIMEOUT)) { + evutil_gettimeofday(&res->write_timeout_at, NULL); + ++res->n_write_timeouts; + } +} + +static void +test_bufferevent_timeouts(void *arg) +{ + /* "arg" is a string containing "pair" and/or "filter". */ + struct bufferevent *bev1 = NULL, *bev2 = NULL; + struct basic_test_data *data = arg; + int use_pair = 0, use_filter = 0; + struct timeval tv_w, tv_r, started_at; + struct timeout_cb_result res1, res2; + char buf[1024]; + + memset(&res1, 0, sizeof(res1)); + memset(&res2, 0, sizeof(res2)); + + if (strstr((char*)data->setup_data, "pair")) + use_pair = 1; + if (strstr((char*)data->setup_data, "filter")) + use_filter = 1; + + if (use_pair) { + struct bufferevent *p[2]; + tt_int_op(0, ==, bufferevent_pair_new(data->base, 0, p)); + bev1 = p[0]; + bev2 = p[1]; + } else { + bev1 = bufferevent_socket_new(data->base, data->pair[0], 0); + bev2 = bufferevent_socket_new(data->base, data->pair[1], 0); + } + + tt_assert(bev1); + tt_assert(bev2); + + if (use_filter) { + struct bufferevent *bevf1, *bevf2; + bevf1 = bufferevent_filter_new(bev1, NULL, NULL, + BEV_OPT_CLOSE_ON_FREE, NULL, NULL); + bevf2 = bufferevent_filter_new(bev2, NULL, NULL, + BEV_OPT_CLOSE_ON_FREE, NULL, NULL); + tt_assert(bevf1); + tt_assert(bevf2); + bev1 = bevf1; + bev2 = bevf2; + } + + /* Do this nice and early. */ + bufferevent_disable(bev2, EV_READ); + + /* bev1 will try to write and read. Both will time out. */ + evutil_gettimeofday(&started_at, NULL); + tv_w.tv_sec = tv_r.tv_sec = 0; + tv_w.tv_usec = 100*1000; + tv_r.tv_usec = 150*1000; + bufferevent_setcb(bev1, NULL, bev_timeout_write_cb, + bev_timeout_event_cb, &res1); + bufferevent_setwatermark(bev1, EV_WRITE, 1024*1024+10, 0); + bufferevent_set_timeouts(bev1, &tv_r, &tv_w); + if (use_pair) { + /* For a pair, the fact that the other side isn't reading + * makes the writer stall */ + bufferevent_write(bev1, "ABCDEFG", 7); + } else { + /* For a real socket, the kernel's TCP buffers can eat a + * fair number of bytes; make sure that at some point we + * have some bytes that will stall. */ + struct evbuffer *output = bufferevent_get_output(bev1); + int i; + memset(buf, 0xbb, sizeof(buf)); + for (i=0;i<1024;++i) { + evbuffer_add_reference(output, buf, sizeof(buf), + NULL, NULL); + } + } + bufferevent_enable(bev1, EV_READ|EV_WRITE); + + /* bev2 has nothing to say, and isn't listening. */ + bufferevent_setcb(bev2, NULL, bev_timeout_write_cb, + bev_timeout_event_cb, &res2); + tv_w.tv_sec = tv_r.tv_sec = 0; + tv_w.tv_usec = 200*1000; + tv_r.tv_usec = 100*1000; + bufferevent_set_timeouts(bev2, &tv_r, &tv_w); + bufferevent_enable(bev2, EV_WRITE); + + tv_r.tv_sec = 1; + tv_r.tv_usec = 0; + + event_base_loopexit(data->base, &tv_r); + event_base_dispatch(data->base); + + /* XXXX Test that actually reading or writing a little resets the + * timeouts. */ + + /* Each buf1 timeout happens, and happens only once. */ + tt_want(res1.n_read_timeouts); + tt_want(res1.n_write_timeouts); + tt_want(res1.n_read_timeouts == 1); + tt_want(res1.n_write_timeouts == 1); + + test_timeval_diff_eq(&started_at, &res1.read_timeout_at, 150); + test_timeval_diff_eq(&started_at, &res1.write_timeout_at, 100); + +end: + if (bev1) + bufferevent_free(bev1); + if (bev2) + bufferevent_free(bev2); +} + +struct testcase_t bufferevent_testcases[] = { + + LEGACY(bufferevent, TT_ISOLATED), + LEGACY(bufferevent_pair, TT_ISOLATED), + LEGACY(bufferevent_watermarks, TT_ISOLATED), + LEGACY(bufferevent_pair_watermarks, TT_ISOLATED), + LEGACY(bufferevent_filters, TT_ISOLATED), + LEGACY(bufferevent_pair_filters, TT_ISOLATED), + { "bufferevent_connect", test_bufferevent_connect, TT_FORK|TT_NEED_BASE, + &basic_setup, (void*)"" }, + { "bufferevent_connect_defer", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"defer" }, + { "bufferevent_connect_lock", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, (void*)"lock" }, + { "bufferevent_connect_lock_defer", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, + (void*)"defer lock" }, + { "bufferevent_connect_unlocked_cbs", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS, &basic_setup, + (void*)"lock defer unlocked" }, + { "bufferevent_connect_fail", test_bufferevent_connect_fail, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "bufferevent_timeout", test_bufferevent_timeouts, + TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, (void*)"" }, + { "bufferevent_timeout_pair", test_bufferevent_timeouts, + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"pair" }, + { "bufferevent_timeout_filter", test_bufferevent_timeouts, + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter" }, + { "bufferevent_timeout_filter_pair", test_bufferevent_timeouts, + TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"filter pair" }, +#ifdef _EVENT_HAVE_LIBZ + LEGACY(bufferevent_zlib, TT_ISOLATED), +#else + { "bufferevent_zlib", NULL, TT_SKIP, NULL, NULL }, +#endif + + END_OF_TESTCASES, +}; + +struct testcase_t bufferevent_iocp_testcases[] = { + + LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP), + LEGACY(bufferevent_watermarks, TT_ISOLATED|TT_ENABLE_IOCP), + LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP), + { "bufferevent_connect", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"" }, + { "bufferevent_connect_defer", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"defer" }, + { "bufferevent_connect_lock", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, + (void*)"lock" }, + { "bufferevent_connect_lock_defer", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup, + (void*)"defer lock" }, + { "bufferevent_connect_fail", test_bufferevent_connect_fail, + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL }, + { "bufferevent_connect_nonblocking", test_bufferevent_connect, + TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, + (void*)"unset_connectex" }, + + END_OF_TESTCASES, +}; diff --git a/libevent/test/regress_dns.c b/libevent/test/regress_dns.c new file mode 100644 index 0000000..a566469 --- /dev/null +++ b/libevent/test/regress_dns.c @@ -0,0 +1,1853 @@ +/* + * Copyright (c) 2003-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#ifdef WIN32 +#include +#include +#include +#endif + +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#ifndef WIN32 +#include +#include +#include +#include +#include +#endif +#ifdef _EVENT_HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#include +#include +#include +#include +#include + +#include "event2/dns.h" +#include "event2/dns_compat.h" +#include "event2/dns_struct.h" +#include "event2/event.h" +#include "event2/event_compat.h" +#include "event2/event_struct.h" +#include "event2/util.h" +#include "event2/listener.h" +#include "event2/bufferevent.h" +#include "log-internal.h" +#include "regress.h" +#include "regress_testutils.h" + +#include "../util-internal.h" + +static int dns_ok = 0; +static int dns_got_cancel = 0; +static int dns_err = 0; + + +static void +dns_gethostbyname_cb(int result, char type, int count, int ttl, + void *addresses, void *arg) +{ + dns_ok = dns_err = 0; + + if (result == DNS_ERR_TIMEOUT) { + printf("[Timed out] "); + dns_err = result; + goto out; + } + + if (result != DNS_ERR_NONE) { + printf("[Error code %d] ", result); + goto out; + } + + TT_BLATHER(("type: %d, count: %d, ttl: %d: ", type, count, ttl)); + + switch (type) { + case DNS_IPv6_AAAA: { +#if defined(_EVENT_HAVE_STRUCT_IN6_ADDR) && defined(_EVENT_HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) + struct in6_addr *in6_addrs = addresses; + char buf[INET6_ADDRSTRLEN+1]; + int i; + /* a resolution that's not valid does not help */ + if (ttl < 0) + goto out; + for (i = 0; i < count; ++i) { + const char *b = inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf)); + if (b) + TT_BLATHER(("%s ", b)); + else + TT_BLATHER(("%s ", strerror(errno))); + } +#endif + break; + } + case DNS_IPv4_A: { + struct in_addr *in_addrs = addresses; + int i; + /* a resolution that's not valid does not help */ + if (ttl < 0) + goto out; + for (i = 0; i < count; ++i) + TT_BLATHER(("%s ", inet_ntoa(in_addrs[i]))); + break; + } + case DNS_PTR: + /* may get at most one PTR */ + if (count != 1) + goto out; + + TT_BLATHER(("%s ", *(char **)addresses)); + break; + default: + goto out; + } + + dns_ok = type; + +out: + if (arg == NULL) + event_loopexit(NULL); + else + event_base_loopexit((struct event_base *)arg, NULL); +} + +static void +dns_gethostbyname(void) +{ + dns_ok = 0; + evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL); + event_dispatch(); + + tt_int_op(dns_ok, ==, DNS_IPv4_A); + test_ok = dns_ok; +end: + ; +} + +static void +dns_gethostbyname6(void) +{ + dns_ok = 0; + evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL); + event_dispatch(); + + if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) { + tt_skip(); + } + + tt_int_op(dns_ok, ==, DNS_IPv6_AAAA); + test_ok = 1; +end: + ; +} + +static void +dns_gethostbyaddr(void) +{ + struct in_addr in; + in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ + dns_ok = 0; + evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL); + event_dispatch(); + + tt_int_op(dns_ok, ==, DNS_PTR); + test_ok = dns_ok; +end: + ; +} + +static void +dns_resolve_reverse(void *ptr) +{ + struct in_addr in; + struct event_base *base = event_base_new(); + struct evdns_base *dns = evdns_base_new(base, 1/* init name servers */); + struct evdns_request *req = NULL; + + tt_assert(base); + tt_assert(dns); + in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ + dns_ok = 0; + + req = evdns_base_resolve_reverse( + dns, &in, 0, dns_gethostbyname_cb, base); + tt_assert(req); + + event_base_dispatch(base); + + tt_int_op(dns_ok, ==, DNS_PTR); + +end: + if (dns) + evdns_base_free(dns, 0); + if (base) + event_base_free(base); +} + +static int n_server_responses = 0; + +static void +dns_server_request_cb(struct evdns_server_request *req, void *data) +{ + int i, r; + const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa"; + const char TEST_IN6[] = + "f.e.f.e." "0.0.0.0." "0.0.0.0." "1.1.1.1." + "a.a.a.a." "0.0.0.0." "0.0.0.0." "0.f.f.f.ip6.arpa"; + + for (i = 0; i < req->nquestions; ++i) { + const int qtype = req->questions[i]->type; + const int qclass = req->questions[i]->dns_question_class; + const char *qname = req->questions[i]->name; + + struct in_addr ans; + ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ + if (qtype == EVDNS_TYPE_A && + qclass == EVDNS_CLASS_INET && + !evutil_ascii_strcasecmp(qname, "zz.example.com")) { + r = evdns_server_request_add_a_reply(req, qname, + 1, &ans.s_addr, 12345); + if (r<0) + dns_ok = 0; + } else if (qtype == EVDNS_TYPE_AAAA && + qclass == EVDNS_CLASS_INET && + !evutil_ascii_strcasecmp(qname, "zz.example.com")) { + char addr6[17] = "abcdefghijklmnop"; + r = evdns_server_request_add_aaaa_reply(req, + qname, 1, addr6, 123); + if (r<0) + dns_ok = 0; + } else if (qtype == EVDNS_TYPE_PTR && + qclass == EVDNS_CLASS_INET && + !evutil_ascii_strcasecmp(qname, TEST_ARPA)) { + r = evdns_server_request_add_ptr_reply(req, NULL, + qname, "ZZ.EXAMPLE.COM", 54321); + if (r<0) + dns_ok = 0; + } else if (qtype == EVDNS_TYPE_PTR && + qclass == EVDNS_CLASS_INET && + !evutil_ascii_strcasecmp(qname, TEST_IN6)){ + r = evdns_server_request_add_ptr_reply(req, NULL, + qname, + "ZZ-INET6.EXAMPLE.COM", 54322); + if (r<0) + dns_ok = 0; + } else if (qtype == EVDNS_TYPE_A && + qclass == EVDNS_CLASS_INET && + !evutil_ascii_strcasecmp(qname, "drop.example.com")) { + if (evdns_server_request_drop(req)<0) + dns_ok = 0; + return; + } else { + printf("Unexpected question %d %d \"%s\" ", + qtype, qclass, qname); + dns_ok = 0; + } + } + r = evdns_server_request_respond(req, 0); + if (r<0) { + printf("Couldn't send reply. "); + dns_ok = 0; + } +} + +static void +dns_server_gethostbyname_cb(int result, char type, int count, int ttl, + void *addresses, void *arg) +{ + if (result == DNS_ERR_CANCEL) { + if (arg != (void*)(char*)90909) { + printf("Unexpected cancelation"); + dns_ok = 0; + } + dns_got_cancel = 1; + goto out; + } + if (result != DNS_ERR_NONE) { + printf("Unexpected result %d. ", result); + dns_ok = 0; + goto out; + } + if (count != 1) { + printf("Unexpected answer count %d. ", count); + dns_ok = 0; + goto out; + } + switch (type) { + case DNS_IPv4_A: { + struct in_addr *in_addrs = addresses; + if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) { + printf("Bad IPv4 response \"%s\" %d. ", + inet_ntoa(in_addrs[0]), ttl); + dns_ok = 0; + goto out; + } + break; + } + case DNS_IPv6_AAAA: { +#if defined (_EVENT_HAVE_STRUCT_IN6_ADDR) && defined(_EVENT_HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) + struct in6_addr *in6_addrs = addresses; + char buf[INET6_ADDRSTRLEN+1]; + if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16) + || ttl != 123) { + const char *b = inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf)); + printf("Bad IPv6 response \"%s\" %d. ", b, ttl); + dns_ok = 0; + goto out; + } +#endif + break; + } + case DNS_PTR: { + char **addrs = addresses; + if (arg != (void*)6) { + if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || + ttl != 54321) { + printf("Bad PTR response \"%s\" %d. ", + addrs[0], ttl); + dns_ok = 0; + goto out; + } + } else { + if (strcmp(addrs[0], "ZZ-INET6.EXAMPLE.COM") || + ttl != 54322) { + printf("Bad ipv6 PTR response \"%s\" %d. ", + addrs[0], ttl); + dns_ok = 0; + goto out; + } + } + break; + } + default: + printf("Bad response type %d. ", type); + dns_ok = 0; + } + out: + if (++n_server_responses == 3) { + event_loopexit(NULL); + } +} + +static void +dns_server(void) +{ + evutil_socket_t sock=-1; + struct sockaddr_in my_addr; + struct sockaddr_storage ss; + ev_socklen_t slen; + struct evdns_server_port *port=NULL; + struct in_addr resolve_addr; + struct in6_addr resolve_addr6; + struct evdns_base *base=NULL; + struct evdns_request *req=NULL; + + dns_ok = 1; + + base = evdns_base_new(NULL, 0); + + /* Now configure a nameserver port. */ + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock<0) { + tt_abort_perror("socket"); + } + + evutil_make_socket_nonblocking(sock); + + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_port = 0; /* kernel picks */ + my_addr.sin_addr.s_addr = htonl(0x7f000001UL); + if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { + tt_abort_perror("bind"); + } + slen = sizeof(ss); + if (getsockname(sock, (struct sockaddr*)&ss, &slen) < 0) { + tt_abort_perror("getsockname"); + } + + port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); + + /* Add ourself as the only nameserver, and make sure we really are + * the only nameserver. */ + evdns_base_nameserver_sockaddr_add(base, (struct sockaddr*)&ss, slen, 0); + tt_int_op(evdns_base_count_nameservers(base), ==, 1); + + /* Send some queries. */ + evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH, + dns_server_gethostbyname_cb, NULL); + evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH, + dns_server_gethostbyname_cb, NULL); + resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ + evdns_base_resolve_reverse(base, &resolve_addr, 0, + dns_server_gethostbyname_cb, NULL); + memcpy(resolve_addr6.s6_addr, + "\xff\xf0\x00\x00\x00\x00\xaa\xaa" + "\x11\x11\x00\x00\x00\x00\xef\xef", 16); + evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0, + dns_server_gethostbyname_cb, (void*)6); + + req = evdns_base_resolve_ipv4(base, + "drop.example.com", DNS_QUERY_NO_SEARCH, + dns_server_gethostbyname_cb, (void*)(char*)90909); + + evdns_cancel_request(base, req); + + event_dispatch(); + + tt_assert(dns_got_cancel); + test_ok = dns_ok; + +end: + if (port) + evdns_close_server_port(port); + if (sock >= 0) + evutil_closesocket(sock); + if (base) + evdns_base_free(base, 0); +} + +static int n_replies_left; +static struct event_base *exit_base; + +struct generic_dns_callback_result { + int result; + char type; + int count; + int ttl; + size_t addrs_len; + void *addrs; + char addrs_buf[256]; +}; + +static void +generic_dns_callback(int result, char type, int count, int ttl, void *addresses, + void *arg) +{ + size_t len; + struct generic_dns_callback_result *res = arg; + res->result = result; + res->type = type; + res->count = count; + res->ttl = ttl; + + if (type == DNS_IPv4_A) + len = count * 4; + else if (type == DNS_IPv6_AAAA) + len = count * 16; + else if (type == DNS_PTR) + len = strlen(addresses)+1; + else { + res->addrs_len = len = 0; + res->addrs = NULL; + } + if (len) { + res->addrs_len = len; + if (len > 256) + len = 256; + memcpy(res->addrs_buf, addresses, len); + res->addrs = res->addrs_buf; + } + + if (--n_replies_left == 0) + event_base_loopexit(exit_base, NULL); +} + +static struct regress_dns_server_table search_table[] = { + { "host.a.example.com", "err", "3", 0 }, + { "host.b.example.com", "err", "3", 0 }, + { "host.c.example.com", "A", "11.22.33.44", 0 }, + { "host2.a.example.com", "err", "3", 0 }, + { "host2.b.example.com", "A", "200.100.0.100", 0 }, + { "host2.c.example.com", "err", "3", 0 }, + { "hostn.a.example.com", "errsoa", "0", 0 }, + { "hostn.b.example.com", "errsoa", "3", 0 }, + { "hostn.c.example.com", "err", "0", 0 }, + + { "host", "err", "3", 0 }, + { "host2", "err", "3", 0 }, + { "*", "err", "3", 0 }, + { NULL, NULL, NULL, 0 } +}; + +static void +dns_search_test(void *arg) +{ + struct basic_test_data *data = arg; + struct event_base *base = data->base; + struct evdns_base *dns = NULL; + ev_uint16_t portnum = 0; + char buf[64]; + + struct generic_dns_callback_result r[8]; + + tt_assert(regress_dnsserver(base, &portnum, search_table)); + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); + + dns = evdns_base_new(base, 0); + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); + + evdns_base_search_add(dns, "a.example.com"); + evdns_base_search_add(dns, "b.example.com"); + evdns_base_search_add(dns, "c.example.com"); + + n_replies_left = sizeof(r)/sizeof(r[0]); + exit_base = base; + + evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]); + evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]); + evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]); + evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]); + evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]); + evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]); + evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]); + evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]); + + event_base_dispatch(base); + + tt_int_op(r[0].type, ==, DNS_IPv4_A); + tt_int_op(r[0].count, ==, 1); + tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c)); + tt_int_op(r[1].type, ==, DNS_IPv4_A); + tt_int_op(r[1].count, ==, 1); + tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064)); + tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST); + tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST); + tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST); + tt_int_op(r[5].result, ==, DNS_ERR_NODATA); + tt_int_op(r[5].ttl, ==, 42); + tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST); + tt_int_op(r[6].ttl, ==, 42); + tt_int_op(r[7].result, ==, DNS_ERR_NODATA); + tt_int_op(r[7].ttl, ==, 0); + +end: + if (dns) + evdns_base_free(dns, 0); + + regress_clean_dnsserver(); +} + +static int request_count = 0; +static struct evdns_request *current_req = NULL; + +static void +search_cancel_server_cb(struct evdns_server_request *req, void *data) +{ + const char *question; + + if (req->nquestions != 1) + TT_DIE(("Only handling one question at a time; got %d", + req->nquestions)); + + question = req->questions[0]->name; + + TT_BLATHER(("got question, %s", question)); + + tt_assert(request_count > 0); + tt_assert(!evdns_server_request_respond(req, 3)); + + if (!--request_count) + evdns_cancel_request(NULL, current_req); + +end: + ; +} + +static void +dns_search_cancel_test(void *arg) +{ + struct basic_test_data *data = arg; + struct event_base *base = data->base; + struct evdns_base *dns = NULL; + struct evdns_server_port *port = NULL; + ev_uint16_t portnum = 0; + struct generic_dns_callback_result r1; + char buf[64]; + + port = regress_get_dnsserver(base, &portnum, NULL, + search_cancel_server_cb, NULL); + tt_assert(port); + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); + + dns = evdns_base_new(base, 0); + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); + + evdns_base_search_add(dns, "a.example.com"); + evdns_base_search_add(dns, "b.example.com"); + evdns_base_search_add(dns, "c.example.com"); + evdns_base_search_add(dns, "d.example.com"); + + exit_base = base; + request_count = 3; + n_replies_left = 1; + + current_req = evdns_base_resolve_ipv4(dns, "host", 0, + generic_dns_callback, &r1); + event_base_dispatch(base); + + tt_int_op(r1.result, ==, DNS_ERR_CANCEL); + +end: + if (port) + evdns_close_server_port(port); + if (dns) + evdns_base_free(dns, 0); +} + +static void +fail_server_cb(struct evdns_server_request *req, void *data) +{ + const char *question; + int *count = data; + struct in_addr in; + + /* Drop the first N requests that we get. */ + if (*count > 0) { + --*count; + tt_want(! evdns_server_request_drop(req)); + return; + } + + if (req->nquestions != 1) + TT_DIE(("Only handling one question at a time; got %d", + req->nquestions)); + + question = req->questions[0]->name; + + if (!evutil_ascii_strcasecmp(question, "google.com")) { + /* Detect a probe, and get out of the loop. */ + event_base_loopexit(exit_base, NULL); + } + + evutil_inet_pton(AF_INET, "16.32.64.128", &in); + evdns_server_request_add_a_reply(req, question, 1, &in.s_addr, + 100); + tt_assert(! evdns_server_request_respond(req, 0)) + return; +end: + tt_want(! evdns_server_request_drop(req)); +} + +static void +dns_retry_test(void *arg) +{ + struct basic_test_data *data = arg; + struct event_base *base = data->base; + struct evdns_server_port *port = NULL; + struct evdns_base *dns = NULL; + int drop_count = 2; + ev_uint16_t portnum = 0; + char buf[64]; + + struct generic_dns_callback_result r1; + + port = regress_get_dnsserver(base, &portnum, NULL, + fail_server_cb, &drop_count); + tt_assert(port); + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); + + dns = evdns_base_new(base, 0); + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); + tt_assert(! evdns_base_set_option(dns, "timeout", "0.3")); + tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10")); + tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.5")); + + evdns_base_resolve_ipv4(dns, "host.example.com", 0, + generic_dns_callback, &r1); + + n_replies_left = 1; + exit_base = base; + + event_base_dispatch(base); + + tt_int_op(drop_count, ==, 0); + + tt_int_op(r1.type, ==, DNS_IPv4_A); + tt_int_op(r1.count, ==, 1); + tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); + + /* Now try again, but this time have the server get treated as + * failed, so we can send it a test probe. */ + drop_count = 4; + tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "3")); + tt_assert(! evdns_base_set_option(dns, "attempts:", "4")); + memset(&r1, 0, sizeof(r1)); + + evdns_base_resolve_ipv4(dns, "host.example.com", 0, + generic_dns_callback, &r1); + + n_replies_left = 2; + + /* This will run until it answers the "google.com" probe request. */ + event_base_dispatch(base); + + /* We'll treat the server as failed here. */ + tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT); + + /* It should work this time. */ + tt_int_op(drop_count, ==, 0); + evdns_base_resolve_ipv4(dns, "host.example.com", 0, + generic_dns_callback, &r1); + + event_base_dispatch(base); + tt_int_op(r1.result, ==, DNS_ERR_NONE); + tt_int_op(r1.type, ==, DNS_IPv4_A); + tt_int_op(r1.count, ==, 1); + tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); + +end: + if (dns) + evdns_base_free(dns, 0); + if (port) + evdns_close_server_port(port); +} + +static struct regress_dns_server_table internal_error_table[] = { + /* Error 4 (NOTIMPL) makes us reissue the request to another server + if we can. + + XXXX we should reissue under a much wider set of circumstances! + */ + { "foof.example.com", "err", "4", 0 }, + { NULL, NULL, NULL, 0 } +}; + +static struct regress_dns_server_table reissue_table[] = { + { "foof.example.com", "A", "240.15.240.15", 0 }, + { NULL, NULL, NULL, 0 } +}; + +static void +dns_reissue_test(void *arg) +{ + struct basic_test_data *data = arg; + struct event_base *base = data->base; + struct evdns_server_port *port1 = NULL, *port2 = NULL; + struct evdns_base *dns = NULL; + struct generic_dns_callback_result r1; + ev_uint16_t portnum1 = 0, portnum2=0; + char buf1[64], buf2[64]; + + port1 = regress_get_dnsserver(base, &portnum1, NULL, + regress_dns_server_cb, internal_error_table); + tt_assert(port1); + port2 = regress_get_dnsserver(base, &portnum2, NULL, + regress_dns_server_cb, reissue_table); + tt_assert(port2); + evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1); + evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2); + + dns = evdns_base_new(base, 0); + tt_assert(!evdns_base_nameserver_ip_add(dns, buf1)); + tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3")); + tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); + tt_assert(! evdns_base_set_option(dns, "attempts:", "5")); + + memset(&r1, 0, sizeof(r1)); + evdns_base_resolve_ipv4(dns, "foof.example.com", 0, + generic_dns_callback, &r1); + + /* Add this after, so that we are sure to get a reissue. */ + tt_assert(!evdns_base_nameserver_ip_add(dns, buf2)); + + n_replies_left = 1; + exit_base = base; + + event_base_dispatch(base); + tt_int_op(r1.result, ==, DNS_ERR_NONE); + tt_int_op(r1.type, ==, DNS_IPv4_A); + tt_int_op(r1.count, ==, 1); + tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f)); + + /* Make sure we dropped at least once. */ + tt_int_op(internal_error_table[0].seen, >, 0); + +end: + if (dns) + evdns_base_free(dns, 0); + if (port1) + evdns_close_server_port(port1); + if (port2) + evdns_close_server_port(port2); +} + +#if 0 +static void +dumb_bytes_fn(char *p, size_t n) +{ + unsigned i; + /* This gets us 6 bits of entropy per transaction ID, which means we + * will have probably have collisions and need to pick again. */ + for (i=0;ibase; + struct evdns_base *dns = NULL; + ev_uint16_t portnum = 0; + char buf[64]; + + struct generic_dns_callback_result r[20]; + int i; + + tt_assert(regress_dnsserver(base, &portnum, reissue_table)); + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); + + dns = evdns_base_new(base, 0); + tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); + tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3")); + tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0")); + + for (i=0;i<20;++i) + evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); + + n_replies_left = 20; + exit_base = base; + + event_base_dispatch(base); + + for (i=0;i<20;++i) { + tt_int_op(r[i].type, ==, DNS_IPv4_A); + tt_int_op(r[i].count, ==, 1); + tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f)); + } + +end: + if (dns) + evdns_base_free(dns, 0); + regress_clean_dnsserver(); +} + +/* === Test for bufferevent_socket_connect_hostname */ + +static int total_connected_or_failed = 0; +static int total_n_accepted = 0; +static struct event_base *be_connect_hostname_base = NULL; + +/* Implements a DNS server for the connect_hostname test and the + * getaddrinfo_async test */ +static void +be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data) +{ + int i; + int *n_got_p=data; + int added_any=0; + ++*n_got_p; + + for (i=0;inquestions;++i) { + const int qtype = req->questions[i]->type; + const int qclass = req->questions[i]->dns_question_class; + const char *qname = req->questions[i]->name; + struct in_addr ans; + struct in6_addr ans6; + memset(&ans6, 0, sizeof(ans6)); + + if (qtype == EVDNS_TYPE_A && + qclass == EVDNS_CLASS_INET && + !evutil_ascii_strcasecmp(qname, "nobodaddy.example.com")) { + ans.s_addr = htonl(0x7f000001); + evdns_server_request_add_a_reply(req, qname, + 1, &ans.s_addr, 2000); + added_any = 1; + } else if (!evutil_ascii_strcasecmp(qname, + "nosuchplace.example.com")) { + /* ok, just say notfound. */ + } else if (!evutil_ascii_strcasecmp(qname, + "both.example.com")) { + if (qtype == EVDNS_TYPE_A) { + ans.s_addr = htonl(0x50502020); + evdns_server_request_add_a_reply(req, qname, + 1, &ans.s_addr, 2000); + added_any = 1; + } else if (qtype == EVDNS_TYPE_AAAA) { + ans6.s6_addr[0] = 0x80; + ans6.s6_addr[1] = 0xff; + ans6.s6_addr[14] = 0xbb; + ans6.s6_addr[15] = 0xbb; + evdns_server_request_add_aaaa_reply(req, qname, + 1, &ans6.s6_addr, 2000); + added_any = 1; + } + evdns_server_request_add_cname_reply(req, qname, + "both-canonical.example.com", 1000); + } else if (!evutil_ascii_strcasecmp(qname, + "v4only.example.com") || + !evutil_ascii_strcasecmp(qname, "v4assert.example.com")) { + if (qtype == EVDNS_TYPE_A) { + ans.s_addr = htonl(0x12345678); + evdns_server_request_add_a_reply(req, qname, + 1, &ans.s_addr, 2000); + added_any = 1; + } else if (!evutil_ascii_strcasecmp(qname, + "v4assert.example.com")) { + TT_FAIL(("Got an AAAA request for v4assert")); + } + } else if (!evutil_ascii_strcasecmp(qname, + "v6only.example.com") || + !evutil_ascii_strcasecmp(qname, "v6assert.example.com")) { + if (qtype == EVDNS_TYPE_AAAA) { + ans6.s6_addr[0] = 0x0b; + ans6.s6_addr[1] = 0x0b; + ans6.s6_addr[14] = 0xf0; + ans6.s6_addr[15] = 0x0d; + evdns_server_request_add_aaaa_reply(req, qname, + 1, &ans6.s6_addr, 2000); + added_any = 1; + } else if (!evutil_ascii_strcasecmp(qname, + "v6assert.example.com")) { + TT_FAIL(("Got a A request for v6assert")); + } + } else if (!evutil_ascii_strcasecmp(qname, + "v6timeout.example.com")) { + if (qtype == EVDNS_TYPE_A) { + ans.s_addr = htonl(0xabcdef01); + evdns_server_request_add_a_reply(req, qname, + 1, &ans.s_addr, 2000); + added_any = 1; + } else if (qtype == EVDNS_TYPE_AAAA) { + /* Let the v6 request time out.*/ + evdns_server_request_drop(req); + return; + } + } else if (!evutil_ascii_strcasecmp(qname, + "v4timeout.example.com")) { + if (qtype == EVDNS_TYPE_AAAA) { + ans6.s6_addr[0] = 0x0a; + ans6.s6_addr[1] = 0x0a; + ans6.s6_addr[14] = 0xff; + ans6.s6_addr[15] = 0x01; + evdns_server_request_add_aaaa_reply(req, qname, + 1, &ans6.s6_addr, 2000); + added_any = 1; + } else if (qtype == EVDNS_TYPE_A) { + /* Let the v4 request time out.*/ + evdns_server_request_drop(req); + return; + } + } else if (!evutil_ascii_strcasecmp(qname, + "v6timeout-nonexist.example.com")) { + if (qtype == EVDNS_TYPE_A) { + /* Fall through, give an nexist. */ + } else if (qtype == EVDNS_TYPE_AAAA) { + /* Let the v6 request time out.*/ + evdns_server_request_drop(req); + return; + } + } else if (!evutil_ascii_strcasecmp(qname, + "all-timeout.example.com")) { + /* drop all requests */ + evdns_server_request_drop(req); + return; + } else { + TT_GRIPE(("Got weird request for %s",qname)); + } + } + if (added_any) + evdns_server_request_respond(req, 0); + else + evdns_server_request_respond(req, 3); +} + +/* Implements a listener for connect_hostname test. */ +static void +nil_accept_cb(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *s, + int socklen, void *arg) +{ + int *p = arg; + (*p)++; + ++total_n_accepted; + /* don't do anything with the socket; let it close when we exit() */ + if (total_n_accepted >= 3 && total_connected_or_failed >= 5) + event_base_loopexit(be_connect_hostname_base, + NULL); +} + +struct be_conn_hostname_result { + int dnserr; + int what; +}; + +/* Bufferevent event callback for the connect_hostname test: remembers what + * event we got. */ +static void +be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx) +{ + struct be_conn_hostname_result *got = ctx; + if (!got->what) { + TT_BLATHER(("Got a bufferevent event %d", what)); + got->what = what; + + if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) { + int r; + if ((r = bufferevent_socket_get_dns_error(bev))) { + got->dnserr = r; + TT_BLATHER(("DNS error %d: %s", r, + evutil_gai_strerror(r))); + } ++total_connected_or_failed; + TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed)); + + if (total_n_accepted >= 3 && total_connected_or_failed >= 5) + event_base_loopexit(be_connect_hostname_base, + NULL); + } + } else { + TT_FAIL(("Two events on one bufferevent. %d,%d", + got->what, (int)what)); + } +} + +static void +test_bufferevent_connect_hostname(void *arg) +{ + struct basic_test_data *data = arg; + struct evconnlistener *listener = NULL; + struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL; + struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0}, + be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0}; + int expect_err5; + struct evdns_base *dns=NULL; + struct evdns_server_port *port=NULL; + evutil_socket_t server_fd=-1; + struct sockaddr_in sin; + int listener_port=-1; + ev_uint16_t dns_port=0; + int n_accept=0, n_dns=0; + char buf[128]; + + be_connect_hostname_base = data->base; + + /* Bind an address and figure out what port it's on. */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + sin.sin_port = 0; + listener = evconnlistener_new_bind(data->base, nil_accept_cb, + &n_accept, + LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC, + -1, (struct sockaddr *)&sin, sizeof(sin)); + listener_port = regress_get_socket_port( + evconnlistener_get_fd(listener)); + + port = regress_get_dnsserver(data->base, &dns_port, NULL, + be_getaddrinfo_server_cb, &n_dns); + tt_assert(port); + tt_int_op(dns_port, >=, 0); + + /* Start an evdns_base that uses the server as its resolver. */ + dns = evdns_base_new(data->base, 0); + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port); + evdns_base_nameserver_ip_add(dns, buf); + + /* Now, finally, at long last, launch the bufferevents. One should do + * a failing lookup IP, one should do a successful lookup by IP, + * and one should do a successful lookup by hostname. */ + be1 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); + be2 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); + be3 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); + be4 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); + be5 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE); + + bufferevent_setcb(be1, NULL, NULL, be_connect_hostname_event_cb, + &be1_outcome); + bufferevent_setcb(be2, NULL, NULL, be_connect_hostname_event_cb, + &be2_outcome); + bufferevent_setcb(be3, NULL, NULL, be_connect_hostname_event_cb, + &be3_outcome); + bufferevent_setcb(be4, NULL, NULL, be_connect_hostname_event_cb, + &be4_outcome); + bufferevent_setcb(be5, NULL, NULL, be_connect_hostname_event_cb, + &be5_outcome); + + /* Launch an async resolve that will fail. */ + tt_assert(!bufferevent_socket_connect_hostname(be1, dns, AF_INET, + "nosuchplace.example.com", listener_port)); + /* Connect to the IP without resolving. */ + tt_assert(!bufferevent_socket_connect_hostname(be2, dns, AF_INET, + "127.0.0.1", listener_port)); + /* Launch an async resolve that will succeed. */ + tt_assert(!bufferevent_socket_connect_hostname(be3, dns, AF_INET, + "nobodaddy.example.com", listener_port)); + /* Use the blocking resolver. This one will fail if your resolver + * can't resolve localhost to 127.0.0.1 */ + tt_assert(!bufferevent_socket_connect_hostname(be4, NULL, AF_INET, + "localhost", listener_port)); + /* Use the blocking resolver with a nonexistent hostname. */ + tt_assert(!bufferevent_socket_connect_hostname(be5, NULL, AF_INET, + "nonesuch.nowhere.example.com", 80)); + { + /* The blocking resolver will use the system nameserver, which + * might tell us anything. (Yes, some twits even pretend that + * example.com is real.) Let's see what answer to expect. */ + struct evutil_addrinfo hints, *ai = NULL; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + expect_err5 = evutil_getaddrinfo( + "nonesuch.nowhere.example.com", "80", &hints, &ai); + } + + event_base_dispatch(data->base); + + tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR); + tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME); + tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED); + tt_int_op(be2_outcome.dnserr, ==, 0); + tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED); + tt_int_op(be3_outcome.dnserr, ==, 0); + tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED); + tt_int_op(be4_outcome.dnserr, ==, 0); + if (expect_err5) { + tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR); + tt_int_op(be5_outcome.dnserr, ==, expect_err5); + } + + tt_int_op(n_accept, ==, 3); + tt_int_op(n_dns, ==, 2); + +end: + if (listener) + evconnlistener_free(listener); + if (server_fd>=0) + evutil_closesocket(server_fd); + if (port) + evdns_close_server_port(port); + if (dns) + evdns_base_free(dns, 0); + if (be1) + bufferevent_free(be1); + if (be2) + bufferevent_free(be2); + if (be3) + bufferevent_free(be3); + if (be4) + bufferevent_free(be4); + if (be5) + bufferevent_free(be5); +} + + +struct gai_outcome { + int err; + struct evutil_addrinfo *ai; +}; + +static int n_gai_results_pending = 0; +static struct event_base *exit_base_on_no_pending_results = NULL; + +static void +gai_cb(int err, struct evutil_addrinfo *res, void *ptr) +{ + struct gai_outcome *go = ptr; + go->err = err; + go->ai = res; + if (--n_gai_results_pending <= 0 && exit_base_on_no_pending_results) + event_base_loopexit(exit_base_on_no_pending_results, NULL); + if (n_gai_results_pending < 900) + TT_BLATHER(("Got an answer; expecting %d more.", + n_gai_results_pending)); +} + +static void +cancel_gai_cb(evutil_socket_t fd, short what, void *ptr) +{ + struct evdns_getaddrinfo_request *r = ptr; + evdns_getaddrinfo_cancel(r); +} + +static void +test_getaddrinfo_async(void *arg) +{ + struct basic_test_data *data = arg; + struct evutil_addrinfo hints, *a; + struct gai_outcome local_outcome; + struct gai_outcome a_out[12]; + int i; + struct evdns_getaddrinfo_request *r; + char buf[128]; + struct evdns_server_port *port = NULL; + ev_uint16_t dns_port = 0; + int n_dns_questions = 0; + + struct evdns_base *dns_base = evdns_base_new(data->base, 0); + + /* for localhost */ + evdns_base_load_hosts(dns_base, NULL); + + memset(a_out, 0, sizeof(a_out)); + + n_gai_results_pending = 10000; /* don't think about exiting yet. */ + + /* 1. Try some cases that will never hit the asynchronous resolver. */ + /* 1a. Simple case with a symbolic service name */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + memset(&local_outcome, 0, sizeof(local_outcome)); + r = evdns_getaddrinfo(dns_base, "1.2.3.4", "http", + &hints, gai_cb, &local_outcome); + tt_assert(! r); + if (!local_outcome.err) { + tt_ptr_op(local_outcome.ai,!=,NULL); + test_ai_eq(local_outcome.ai, "1.2.3.4:80", SOCK_STREAM, IPPROTO_TCP); + evutil_freeaddrinfo(local_outcome.ai); + local_outcome.ai = NULL; + } else { + TT_BLATHER(("Apparently we have no getservbyname.")); + } + + /* 1b. EVUTIL_AI_NUMERICHOST is set */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = EVUTIL_AI_NUMERICHOST; + memset(&local_outcome, 0, sizeof(local_outcome)); + r = evdns_getaddrinfo(dns_base, "www.google.com", "80", + &hints, gai_cb, &local_outcome); + tt_int_op(r,==,0); + tt_int_op(local_outcome.err,==,EVUTIL_EAI_NONAME); + tt_ptr_op(local_outcome.ai,==,NULL); + + /* 1c. We give a numeric address (ipv6) */ + memset(&hints, 0, sizeof(hints)); + memset(&local_outcome, 0, sizeof(local_outcome)); + hints.ai_family = PF_UNSPEC; + hints.ai_protocol = IPPROTO_TCP; + r = evdns_getaddrinfo(dns_base, "f::f", "8008", + &hints, gai_cb, &local_outcome); + tt_assert(!r); + tt_int_op(local_outcome.err,==,0); + tt_assert(local_outcome.ai); + tt_ptr_op(local_outcome.ai->ai_next,==,NULL); + test_ai_eq(local_outcome.ai, "[f::f]:8008", SOCK_STREAM, IPPROTO_TCP); + evutil_freeaddrinfo(local_outcome.ai); + local_outcome.ai = NULL; + + /* 1d. We give a numeric address (ipv4) */ + memset(&hints, 0, sizeof(hints)); + memset(&local_outcome, 0, sizeof(local_outcome)); + hints.ai_family = PF_UNSPEC; + r = evdns_getaddrinfo(dns_base, "5.6.7.8", NULL, + &hints, gai_cb, &local_outcome); + tt_assert(!r); + tt_int_op(local_outcome.err,==,0); + tt_assert(local_outcome.ai); + a = ai_find_by_protocol(local_outcome.ai, IPPROTO_TCP); + tt_assert(a); + test_ai_eq(a, "5.6.7.8", SOCK_STREAM, IPPROTO_TCP); + a = ai_find_by_protocol(local_outcome.ai, IPPROTO_UDP); + tt_assert(a); + test_ai_eq(a, "5.6.7.8", SOCK_DGRAM, IPPROTO_UDP); + evutil_freeaddrinfo(local_outcome.ai); + local_outcome.ai = NULL; + + /* 1e. nodename is NULL (bind) */ + memset(&hints, 0, sizeof(hints)); + memset(&local_outcome, 0, sizeof(local_outcome)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = EVUTIL_AI_PASSIVE; + r = evdns_getaddrinfo(dns_base, NULL, "9090", + &hints, gai_cb, &local_outcome); + tt_assert(!r); + tt_int_op(local_outcome.err,==,0); + tt_assert(local_outcome.ai); + /* we should get a v4 address of 0.0.0.0... */ + a = ai_find_by_family(local_outcome.ai, PF_INET); + tt_assert(a); + test_ai_eq(a, "0.0.0.0:9090", SOCK_DGRAM, IPPROTO_UDP); + /* ... and a v6 address of ::0 */ + a = ai_find_by_family(local_outcome.ai, PF_INET6); + tt_assert(a); + test_ai_eq(a, "[::]:9090", SOCK_DGRAM, IPPROTO_UDP); + evutil_freeaddrinfo(local_outcome.ai); + local_outcome.ai = NULL; + + /* 1f. nodename is NULL (connect) */ + memset(&hints, 0, sizeof(hints)); + memset(&local_outcome, 0, sizeof(local_outcome)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + r = evdns_getaddrinfo(dns_base, NULL, "2", + &hints, gai_cb, &local_outcome); + tt_assert(!r); + tt_int_op(local_outcome.err,==,0); + tt_assert(local_outcome.ai); + /* we should get a v4 address of 127.0.0.1 .... */ + a = ai_find_by_family(local_outcome.ai, PF_INET); + tt_assert(a); + test_ai_eq(a, "127.0.0.1:2", SOCK_STREAM, IPPROTO_TCP); + /* ... and a v6 address of ::1 */ + a = ai_find_by_family(local_outcome.ai, PF_INET6); + tt_assert(a); + test_ai_eq(a, "[::1]:2", SOCK_STREAM, IPPROTO_TCP); + evutil_freeaddrinfo(local_outcome.ai); + local_outcome.ai = NULL; + + /* 1g. We find localhost immediately. (pf_unspec) */ + memset(&hints, 0, sizeof(hints)); + memset(&local_outcome, 0, sizeof(local_outcome)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + r = evdns_getaddrinfo(dns_base, "LOCALHOST", "80", + &hints, gai_cb, &local_outcome); + tt_assert(!r); + tt_int_op(local_outcome.err,==,0); + tt_assert(local_outcome.ai); + /* we should get a v4 address of 127.0.0.1 .... */ + a = ai_find_by_family(local_outcome.ai, PF_INET); + tt_assert(a); + test_ai_eq(a, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP); + /* ... and a v6 address of ::1 */ + a = ai_find_by_family(local_outcome.ai, PF_INET6); + tt_assert(a); + test_ai_eq(a, "[::1]:80", SOCK_STREAM, IPPROTO_TCP); + evutil_freeaddrinfo(local_outcome.ai); + local_outcome.ai = NULL; + + /* 1g. We find localhost immediately. (pf_inet6) */ + memset(&hints, 0, sizeof(hints)); + memset(&local_outcome, 0, sizeof(local_outcome)); + hints.ai_family = PF_INET6; + hints.ai_socktype = SOCK_STREAM; + r = evdns_getaddrinfo(dns_base, "LOCALHOST", "9999", + &hints, gai_cb, &local_outcome); + tt_assert(! r); + tt_int_op(local_outcome.err,==,0); + tt_assert(local_outcome.ai); + a = local_outcome.ai; + test_ai_eq(a, "[::1]:9999", SOCK_STREAM, IPPROTO_TCP); + tt_ptr_op(a->ai_next, ==, NULL); + evutil_freeaddrinfo(local_outcome.ai); + local_outcome.ai = NULL; + + /* 2. Okay, now we can actually test the asynchronous resolver. */ + /* Start a dummy local dns server... */ + port = regress_get_dnsserver(data->base, &dns_port, NULL, + be_getaddrinfo_server_cb, &n_dns_questions); + tt_assert(port); + tt_int_op(dns_port, >=, 0); + /* ... and tell the evdns_base about it. */ + evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", dns_port); + evdns_base_nameserver_ip_add(dns_base, buf); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = EVUTIL_AI_CANONNAME; + /* 0: Request for both.example.com should return both addresses. */ + r = evdns_getaddrinfo(dns_base, "both.example.com", "8000", + &hints, gai_cb, &a_out[0]); + tt_assert(r); + + /* 1: Request for v4only.example.com should return one address. */ + r = evdns_getaddrinfo(dns_base, "v4only.example.com", "8001", + &hints, gai_cb, &a_out[1]); + tt_assert(r); + + /* 2: Request for v6only.example.com should return one address. */ + hints.ai_flags = 0; + r = evdns_getaddrinfo(dns_base, "v6only.example.com", "8002", + &hints, gai_cb, &a_out[2]); + tt_assert(r); + + /* 3: PF_INET request for v4assert.example.com should not generate a + * v6 request. The server will fail the test if it does. */ + hints.ai_family = PF_INET; + r = evdns_getaddrinfo(dns_base, "v4assert.example.com", "8003", + &hints, gai_cb, &a_out[3]); + tt_assert(r); + + /* 4: PF_INET6 request for v6assert.example.com should not generate a + * v4 request. The server will fail the test if it does. */ + hints.ai_family = PF_INET6; + r = evdns_getaddrinfo(dns_base, "v6assert.example.com", "8004", + &hints, gai_cb, &a_out[4]); + tt_assert(r); + + /* 5: PF_INET request for nosuchplace.example.com should give NEXIST. */ + hints.ai_family = PF_INET; + r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8005", + &hints, gai_cb, &a_out[5]); + tt_assert(r); + + /* 6: PF_UNSPEC request for nosuchplace.example.com should give NEXIST. + */ + hints.ai_family = PF_UNSPEC; + r = evdns_getaddrinfo(dns_base, "nosuchplace.example.com", "8006", + &hints, gai_cb, &a_out[6]); + tt_assert(r); + + /* 7: PF_UNSPEC request for v6timeout.example.com should give an ipv4 + * address only. */ + hints.ai_family = PF_UNSPEC; + r = evdns_getaddrinfo(dns_base, "v6timeout.example.com", "8007", + &hints, gai_cb, &a_out[7]); + tt_assert(r); + + /* 8: PF_UNSPEC request for v6timeout-nonexist.example.com should give + * a NEXIST */ + hints.ai_family = PF_UNSPEC; + r = evdns_getaddrinfo(dns_base, "v6timeout-nonexist.example.com", + "8008", &hints, gai_cb, &a_out[8]); + tt_assert(r); + + /* 9: AI_ADDRCONFIG should at least not crash. Can't test it more + * without knowing what kind of internet we have. */ + hints.ai_flags |= EVUTIL_AI_ADDRCONFIG; + r = evdns_getaddrinfo(dns_base, "both.example.com", + "8009", &hints, gai_cb, &a_out[9]); + tt_assert(r); + + /* 10: PF_UNSPEC for v4timeout.example.com should give an ipv6 address + * only. */ + hints.ai_family = PF_UNSPEC; + hints.ai_flags = 0; + r = evdns_getaddrinfo(dns_base, "v4timeout.example.com", "8010", + &hints, gai_cb, &a_out[10]); + tt_assert(r); + + /* 11: timeout.example.com: cancel it after 100 msec. */ + r = evdns_getaddrinfo(dns_base, "all-timeout.example.com", "8011", + &hints, gai_cb, &a_out[11]); + tt_assert(r); + { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100*1000; /* 100 msec */ + event_base_once(data->base, -1, EV_TIMEOUT, cancel_gai_cb, + r, &tv); + } + + /* XXXXX There are more tests we could do, including: + + - A test to elicit NODATA. + + */ + + n_gai_results_pending = 12; + exit_base_on_no_pending_results = data->base; + + event_base_dispatch(data->base); + + /* 0: both.example.com */ + tt_int_op(a_out[0].err, ==, 0); + tt_assert(a_out[0].ai); + tt_assert(a_out[0].ai->ai_next); + tt_assert(!a_out[0].ai->ai_next->ai_next); + a = ai_find_by_family(a_out[0].ai, PF_INET); + tt_assert(a); + test_ai_eq(a, "80.80.32.32:8000", SOCK_STREAM, IPPROTO_TCP); + a = ai_find_by_family(a_out[0].ai, PF_INET6); + tt_assert(a); + test_ai_eq(a, "[80ff::bbbb]:8000", SOCK_STREAM, IPPROTO_TCP); + tt_assert(a_out[0].ai->ai_canonname); + tt_str_op(a_out[0].ai->ai_canonname, ==, "both-canonical.example.com"); + + /* 1: v4only.example.com */ + tt_int_op(a_out[1].err, ==, 0); + tt_assert(a_out[1].ai); + tt_assert(! a_out[1].ai->ai_next); + test_ai_eq(a_out[1].ai, "18.52.86.120:8001", SOCK_STREAM, IPPROTO_TCP); + tt_assert(a_out[1].ai->ai_canonname == NULL); + + + /* 2: v6only.example.com */ + tt_int_op(a_out[2].err, ==, 0); + tt_assert(a_out[2].ai); + tt_assert(! a_out[2].ai->ai_next); + test_ai_eq(a_out[2].ai, "[b0b::f00d]:8002", SOCK_STREAM, IPPROTO_TCP); + + /* 3: v4assert.example.com */ + tt_int_op(a_out[3].err, ==, 0); + tt_assert(a_out[3].ai); + tt_assert(! a_out[3].ai->ai_next); + test_ai_eq(a_out[3].ai, "18.52.86.120:8003", SOCK_STREAM, IPPROTO_TCP); + + /* 4: v6assert.example.com */ + tt_int_op(a_out[4].err, ==, 0); + tt_assert(a_out[4].ai); + tt_assert(! a_out[4].ai->ai_next); + test_ai_eq(a_out[4].ai, "[b0b::f00d]:8004", SOCK_STREAM, IPPROTO_TCP); + + /* 5: nosuchplace.example.com (inet) */ + tt_int_op(a_out[5].err, ==, EVUTIL_EAI_NONAME); + tt_assert(! a_out[5].ai); + + /* 6: nosuchplace.example.com (unspec) */ + tt_int_op(a_out[6].err, ==, EVUTIL_EAI_NONAME); + tt_assert(! a_out[6].ai); + + /* 7: v6timeout.example.com */ + tt_int_op(a_out[7].err, ==, 0); + tt_assert(a_out[7].ai); + tt_assert(! a_out[7].ai->ai_next); + test_ai_eq(a_out[7].ai, "171.205.239.1:8007", SOCK_STREAM, IPPROTO_TCP); + + /* 8: v6timeout-nonexist.example.com */ + tt_int_op(a_out[8].err, ==, EVUTIL_EAI_NONAME); + tt_assert(! a_out[8].ai); + + /* 9: both (ADDRCONFIG) */ + tt_int_op(a_out[9].err, ==, 0); + tt_assert(a_out[9].ai); + a = ai_find_by_family(a_out[9].ai, PF_INET); + if (a) + test_ai_eq(a, "80.80.32.32:8009", SOCK_STREAM, IPPROTO_TCP); + else + tt_assert(ai_find_by_family(a_out[9].ai, PF_INET6)); + a = ai_find_by_family(a_out[9].ai, PF_INET6); + if (a) + test_ai_eq(a, "[80ff::bbbb]:8009", SOCK_STREAM, IPPROTO_TCP); + else + tt_assert(ai_find_by_family(a_out[9].ai, PF_INET)); + + /* 10: v4timeout.example.com */ + tt_int_op(a_out[10].err, ==, 0); + tt_assert(a_out[10].ai); + tt_assert(! a_out[10].ai->ai_next); + test_ai_eq(a_out[10].ai, "[a0a::ff01]:8010", SOCK_STREAM, IPPROTO_TCP); + + /* 11: cancelled request. */ + tt_int_op(a_out[11].err, ==, EVUTIL_EAI_CANCEL); + tt_assert(a_out[11].ai == NULL); + +end: + if (local_outcome.ai) + evutil_freeaddrinfo(local_outcome.ai); + for (i=0;i<10;++i) { + if (a_out[i].ai) + evutil_freeaddrinfo(a_out[i].ai); + } + if (port) + evdns_close_server_port(port); + if (dns_base) + evdns_base_free(dns_base, 0); +} + +struct gaic_request_status { + int magic; + struct event_base *base; + struct evdns_base *dns_base; + struct evdns_getaddrinfo_request *request; + struct event cancel_event; + int canceled; +}; + +#define GAIC_MAGIC 0x1234abcd + +static int pending = 0; + +static void +gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg) +{ + struct gaic_request_status *status = arg; + + tt_assert(status->magic == GAIC_MAGIC); + status->canceled = 1; + evdns_getaddrinfo_cancel(status->request); + return; +end: + event_base_loopexit(status->base, NULL); +} + +static void +gaic_server_cb(struct evdns_server_request *req, void *arg) +{ + ev_uint32_t answer = 0x7f000001; + tt_assert(req->nquestions); + evdns_server_request_add_a_reply(req, req->questions[0]->name, 1, + &answer, 100); + evdns_server_request_respond(req, 0); + return; +end: + evdns_server_request_respond(req, DNS_ERR_REFUSED); +} + + +static void +gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg) +{ + struct gaic_request_status *status = arg; + struct event_base *base = status->base; + tt_assert(status->magic == GAIC_MAGIC); + + if (result == EVUTIL_EAI_CANCEL) { + tt_assert(status->canceled); + } + event_del(&status->cancel_event); + + memset(status, 0xf0, sizeof(*status)); + free(status); + +end: + if (--pending <= 0) + event_base_loopexit(base, NULL); +} + +static void +gaic_launch(struct event_base *base, struct evdns_base *dns_base) +{ + struct gaic_request_status *status = calloc(1,sizeof(*status)); + struct timeval tv = { 0, 10000 }; + status->magic = GAIC_MAGIC; + status->base = base; + status->dns_base = dns_base; + event_assign(&status->cancel_event, base, -1, 0, gaic_cancel_request_cb, + status); + status->request = evdns_getaddrinfo(dns_base, + "foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb, + status); + event_add(&status->cancel_event, &tv); + ++pending; +} + +#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED +/* FIXME: We should move this to regress_main.c if anything else needs it.*/ + +/* Trivial replacements for malloc/free/realloc to check for memory leaks. + * Not threadsafe. */ +static int allocated_chunks = 0; + +static void * +cnt_malloc(size_t sz) +{ + allocated_chunks += 1; + return malloc(sz); +} + +static void * +cnt_realloc(void *old, size_t sz) +{ + if (!old) + allocated_chunks += 1; + if (!sz) + allocated_chunks -= 1; + return realloc(old, sz); +} + +static void +cnt_free(void *ptr) +{ + allocated_chunks -= 1; + free(ptr); +} + +struct testleak_env_t { + struct event_base *base; + struct evdns_base *dns_base; + struct evdns_request *req; + struct generic_dns_callback_result r; +}; + +static void * +testleak_setup(const struct testcase_t *testcase) +{ + struct testleak_env_t *env; + + allocated_chunks = 0; + event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free); + event_enable_debug_mode(); + + /* not mm_calloc: we don't want to mess with the count. */ + env = calloc(1, sizeof(struct testleak_env_t)); + env->base = event_base_new(); + env->dns_base = evdns_base_new(env->base, 0); + env->req = evdns_base_resolve_ipv4( + env->dns_base, "example.com", DNS_QUERY_NO_SEARCH, + generic_dns_callback, &env->r); + return env; +} + +static int +testleak_cleanup(const struct testcase_t *testcase, void *env_) +{ + int ok = 0; + struct testleak_env_t *env = env_; +#ifdef _EVENT_DISABLE_DEBUG_MODE + tt_int_op(allocated_chunks, ==, 0); +#else + /* FIXME: that's `1' because of event_debug_map_HT_GROW */ + tt_int_op(allocated_chunks, ==, 1); +#endif + ok = 1; +end: + if (env->dns_base) + evdns_base_free(env->dns_base, 0); + if (env->base) + event_base_free(env->base); + if (env) + free(env); + return ok; +} + +static struct testcase_setup_t testleak_funcs = { + testleak_setup, testleak_cleanup +}; + +static void +test_dbg_leak_cancel(void *env_) +{ + /* cancel, loop, free/dns, free/base */ + struct testleak_env_t *env = env_; + int send_err_shutdown = 1; + evdns_cancel_request(env->dns_base, env->req); + env->req = 0; + + /* `req` is freed in callback, that's why one loop is required. */ + event_base_loop(env->base, EVLOOP_NONBLOCK); + + /* send_err_shutdown means nothing as soon as our request is + * already canceled */ + evdns_base_free(env->dns_base, send_err_shutdown); + env->dns_base = 0; + event_base_free(env->base); + env->base = 0; +} + +static void +test_dbg_leak_shutdown(void *env_) +{ + /* free/dns, loop, free/base */ + struct testleak_env_t *env = env_; + int send_err_shutdown = 1; + + /* `req` is freed both with `send_err_shutdown` and without it, + * the only difference is `evdns_callback` call */ + env->req = 0; + + evdns_base_free(env->dns_base, send_err_shutdown); + env->dns_base = 0; + + /* `req` is freed in callback, that's why one loop is required */ + event_base_loop(env->base, EVLOOP_NONBLOCK); + event_base_free(env->base); + env->base = 0; +} +#endif + +static void +test_getaddrinfo_async_cancel_stress(void *ptr) +{ + struct event_base *base; + struct evdns_base *dns_base = NULL; + struct evdns_server_port *server = NULL; + evutil_socket_t fd = -1; + struct sockaddr_in sin; + struct sockaddr_storage ss; + ev_socklen_t slen; + int i; + + base = event_base_new(); + dns_base = evdns_base_new(base, 0); + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = htonl(0x7f000001); + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + tt_abort_perror("socket"); + } + evutil_make_socket_nonblocking(fd); + if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))<0) { + tt_abort_perror("bind"); + } + server = evdns_add_server_port_with_base(base, fd, 0, gaic_server_cb, + base); + + memset(&ss, 0, sizeof(ss)); + slen = sizeof(ss); + if (getsockname(fd, (struct sockaddr*)&ss, &slen)<0) { + tt_abort_perror("getsockname"); + } + evdns_base_nameserver_sockaddr_add(dns_base, + (struct sockaddr*)&ss, slen, 0); + + for (i = 0; i < 1000; ++i) { + gaic_launch(base, dns_base); + } + + event_base_dispatch(base); + +end: + if (dns_base) + evdns_base_free(dns_base, 1); + if (server) + evdns_close_server_port(server); + if (fd >= 0) + evutil_closesocket(fd); +} + + +#define DNS_LEGACY(name, flags) \ + { #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \ + dns_##name } + +struct testcase_t dns_testcases[] = { + DNS_LEGACY(server, TT_FORK|TT_NEED_BASE), + DNS_LEGACY(gethostbyname, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), + DNS_LEGACY(gethostbyname6, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), + DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS), + { "resolve_reverse", dns_resolve_reverse, TT_FORK, NULL, NULL }, + { "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "search_cancel", dns_search_cancel_test, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + { "bufferevent_connect_hostname", test_bufferevent_connect_hostname, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL }, + + { "getaddrinfo_async", test_getaddrinfo_async, + TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" }, + { "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress, + TT_FORK, NULL, NULL }, + +#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED + { "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL }, + { "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL }, +#endif + + END_OF_TESTCASES +}; + diff --git a/libevent/test/regress_et.c b/libevent/test/regress_et.c new file mode 100644 index 0000000..dee7b93 --- /dev/null +++ b/libevent/test/regress_et.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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. + */ +#include "../util-internal.h" +#include "event2/event-config.h" + +#ifdef WIN32 +#include +#endif +#include +#include +#ifdef _EVENT_HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#endif +#include + +#include "event2/event.h" +#include "event2/util.h" + +#include "regress.h" + +static int was_et = 0; + +static void +read_cb(evutil_socket_t fd, short event, void *arg) +{ + char buf; + int len; + + len = recv(fd, &buf, sizeof(buf), 0); + + called++; + if (event & EV_ET) + was_et = 1; + + if (!len) + event_del(arg); +} + +#ifndef SHUT_WR +#define SHUT_WR 1 +#endif + +#ifdef WIN32 +#define LOCAL_SOCKETPAIR_AF AF_INET +#else +#define LOCAL_SOCKETPAIR_AF AF_UNIX +#endif + +static void +test_edgetriggered(void *et) +{ + struct event *ev = NULL; + struct event_base *base = NULL; + const char *test = "test string"; + evutil_socket_t pair[2] = {-1,-1}; + int supports_et; + + /* On Linux 3.2.1 (at least, as patched by Fedora and tested by Nick), + * doing a "recv" on an AF_UNIX socket resets the readability of the + * socket, even though there is no state change, so we don't actually + * get edge-triggered behavior. Yuck! Linux 3.1.9 didn't have this + * problem. + */ +#ifdef __linux__ + if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, pair) == -1) { + tt_abort_perror("socketpair"); + } +#else + if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair) == -1) { + tt_abort_perror("socketpair"); + } +#endif + + called = was_et = 0; + + send(pair[0], test, (int)strlen(test)+1, 0); + shutdown(pair[0], SHUT_WR); + + /* Initalize the event library */ + base = event_base_new(); + + if (!strcmp(event_base_get_method(base), "epoll") || + !strcmp(event_base_get_method(base), "epoll (with changelist)") || + !strcmp(event_base_get_method(base), "kqueue")) + supports_et = 1; + else + supports_et = 0; + + TT_BLATHER(("Checking for edge-triggered events with %s, which should %s" + "support edge-triggering", event_base_get_method(base), + supports_et?"":"not ")); + + /* Initalize one event */ + ev = event_new(base, pair[1], EV_READ|EV_ET|EV_PERSIST, read_cb, &ev); + + event_add(ev, NULL); + + /* We're going to call the dispatch function twice. The first invocation + * will read a single byte from pair[1] in either case. If we're edge + * triggered, we'll only see the event once (since we only see transitions + * from no data to data), so the second invocation of event_base_loop will + * do nothing. If we're level triggered, the second invocation of + * event_base_loop will also activate the event (because there's still + * data to read). */ + event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE); + event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE); + + if (supports_et) { + tt_int_op(called, ==, 1); + tt_assert(was_et); + } else { + tt_int_op(called, ==, 2); + tt_assert(!was_et); + } + + end: + if (ev) { + event_del(ev); + event_free(ev); + } + if (base) + event_base_free(base); + evutil_closesocket(pair[0]); + evutil_closesocket(pair[1]); +} + +static void +test_edgetriggered_mix_error(void *data_) +{ + struct basic_test_data *data = data_; + struct event_base *base = NULL; + struct event *ev_et=NULL, *ev_lt=NULL; + +#ifdef _EVENT_DISABLE_DEBUG_MODE + if (1) + tt_skip(); +#endif + + event_enable_debug_mode(); + + base = event_base_new(); + + /* try mixing edge-triggered and level-triggered to make sure it fails*/ + ev_et = event_new(base, data->pair[0], EV_READ|EV_ET, read_cb, ev_et); + ev_lt = event_new(base, data->pair[0], EV_READ, read_cb, ev_lt); + + /* Add edge-triggered, then level-triggered. Get an error. */ + tt_int_op(0, ==, event_add(ev_et, NULL)); + tt_int_op(-1, ==, event_add(ev_lt, NULL)); + tt_int_op(EV_READ, ==, event_pending(ev_et, EV_READ, NULL)); + tt_int_op(0, ==, event_pending(ev_lt, EV_READ, NULL)); + + tt_int_op(0, ==, event_del(ev_et)); + /* Add level-triggered, then edge-triggered. Get an error. */ + tt_int_op(0, ==, event_add(ev_lt, NULL)); + tt_int_op(-1, ==, event_add(ev_et, NULL)); + tt_int_op(EV_READ, ==, event_pending(ev_lt, EV_READ, NULL)); + tt_int_op(0, ==, event_pending(ev_et, EV_READ, NULL)); + +end: + if (ev_et) + event_free(ev_et); + if (ev_lt) + event_free(ev_lt); + if (base) + event_base_free(base); +} + +struct testcase_t edgetriggered_testcases[] = { + { "et", test_edgetriggered, TT_FORK, NULL, NULL }, + { "et_mix_error", test_edgetriggered_mix_error, + TT_FORK|TT_NEED_SOCKETPAIR|TT_NO_LOGS, &basic_setup, NULL }, + END_OF_TESTCASES +}; diff --git a/libevent/test/regress_http.c b/libevent/test/regress_http.c new file mode 100644 index 0000000..aea318f --- /dev/null +++ b/libevent/test/regress_http.c @@ -0,0 +1,3614 @@ +/* + * Copyright (c) 2003-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +#ifdef WIN32 +#include +#include +#include +#endif + +#include "event2/event-config.h" + +#include +#include +#ifdef _EVENT_HAVE_SYS_TIME_H +#include +#endif +#include +#ifndef WIN32 +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include + +#include "event2/dns.h" + +#include "event2/event.h" +#include "event2/http.h" +#include "event2/buffer.h" +#include "event2/bufferevent.h" +#include "event2/util.h" +#include "log-internal.h" +#include "util-internal.h" +#include "http-internal.h" +#include "regress.h" +#include "regress_testutils.h" + +static struct evhttp *http; +/* set if a test needs to call loopexit on a base */ +static struct event_base *exit_base; + +static char const BASIC_REQUEST_BODY[] = "This is funny"; + +static void http_basic_cb(struct evhttp_request *req, void *arg); +static void http_chunked_cb(struct evhttp_request *req, void *arg); +static void http_post_cb(struct evhttp_request *req, void *arg); +static void http_put_cb(struct evhttp_request *req, void *arg); +static void http_delete_cb(struct evhttp_request *req, void *arg); +static void http_delay_cb(struct evhttp_request *req, void *arg); +static void http_large_delay_cb(struct evhttp_request *req, void *arg); +static void http_badreq_cb(struct evhttp_request *req, void *arg); +static void http_dispatcher_cb(struct evhttp_request *req, void *arg); +static int +http_bind(struct evhttp *myhttp, ev_uint16_t *pport) +{ + int port; + struct evhttp_bound_socket *sock; + + sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", *pport); + if (sock == NULL) + event_errx(1, "Could not start web server"); + + port = regress_get_socket_port(evhttp_bound_socket_get_fd(sock)); + if (port < 0) + return -1; + *pport = (ev_uint16_t) port; + + return 0; +} + +static struct evhttp * +http_setup(ev_uint16_t *pport, struct event_base *base) +{ + struct evhttp *myhttp; + + /* Try a few different ports */ + myhttp = evhttp_new(base); + + if (http_bind(myhttp, pport) < 0) + return NULL; + + /* Register a callback for certain types of requests */ + evhttp_set_cb(myhttp, "/test", http_basic_cb, base); + evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, base); + evhttp_set_cb(myhttp, "/streamed", http_chunked_cb, base); + evhttp_set_cb(myhttp, "/postit", http_post_cb, base); + evhttp_set_cb(myhttp, "/putit", http_put_cb, base); + evhttp_set_cb(myhttp, "/deleteit", http_delete_cb, base); + evhttp_set_cb(myhttp, "/delay", http_delay_cb, base); + evhttp_set_cb(myhttp, "/largedelay", http_large_delay_cb, base); + evhttp_set_cb(myhttp, "/badrequest", http_badreq_cb, base); + evhttp_set_cb(myhttp, "/", http_dispatcher_cb, base); + return (myhttp); +} + +#ifndef NI_MAXSERV +#define NI_MAXSERV 1024 +#endif + +static evutil_socket_t +http_connect(const char *address, u_short port) +{ + /* Stupid code for connecting */ + struct evutil_addrinfo ai, *aitop; + char strport[NI_MAXSERV]; + + struct sockaddr *sa; + int slen; + evutil_socket_t fd; + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = AF_INET; + ai.ai_socktype = SOCK_STREAM; + evutil_snprintf(strport, sizeof(strport), "%d", port); + if (evutil_getaddrinfo(address, strport, &ai, &aitop) != 0) { + event_warn("getaddrinfo"); + return (-1); + } + sa = aitop->ai_addr; + slen = aitop->ai_addrlen; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + event_err(1, "socket failed"); + + evutil_make_socket_nonblocking(fd); + if (connect(fd, sa, slen) == -1) { +#ifdef WIN32 + int tmp_err = WSAGetLastError(); + if (tmp_err != WSAEINPROGRESS && tmp_err != WSAEINVAL && + tmp_err != WSAEWOULDBLOCK) + event_err(1, "connect failed"); +#else + if (errno != EINPROGRESS) + event_err(1, "connect failed"); +#endif + } + + evutil_freeaddrinfo(aitop); + + return (fd); +} + +/* Helper: do a strcmp on the contents of buf and the string s. */ +static int +evbuffer_datacmp(struct evbuffer *buf, const char *s) +{ + size_t b_sz = evbuffer_get_length(buf); + size_t s_sz = strlen(s); + unsigned char *d; + int r; + + if (b_sz < s_sz) + return -1; + + d = evbuffer_pullup(buf, s_sz); + if ((r = memcmp(d, s, s_sz))) + return r; + + if (b_sz > s_sz) + return 1; + else + return 0; +} + +/* Helper: Return true iff buf contains s */ +static int +evbuffer_contains(struct evbuffer *buf, const char *s) +{ + struct evbuffer_ptr ptr; + ptr = evbuffer_search(buf, s, strlen(s), NULL); + return ptr.pos != -1; +} + +static void +http_readcb(struct bufferevent *bev, void *arg) +{ + const char *what = BASIC_REQUEST_BODY; + struct event_base *my_base = arg; + + if (evbuffer_contains(bufferevent_get_input(bev), what)) { + struct evhttp_request *req = evhttp_request_new(NULL, NULL); + enum message_read_status done; + + /* req->kind = EVHTTP_RESPONSE; */ + done = evhttp_parse_firstline(req, bufferevent_get_input(bev)); + if (done != ALL_DATA_READ) + goto out; + + done = evhttp_parse_headers(req, bufferevent_get_input(bev)); + if (done != ALL_DATA_READ) + goto out; + + if (done == 1 && + evhttp_find_header(evhttp_request_get_input_headers(req), + "Content-Type") != NULL) + test_ok++; + + out: + evhttp_request_free(req); + bufferevent_disable(bev, EV_READ); + if (exit_base) + event_base_loopexit(exit_base, NULL); + else if (my_base) + event_base_loopexit(my_base, NULL); + else { + fprintf(stderr, "No way to exit loop!\n"); + exit(1); + } + } +} + +static void +http_writecb(struct bufferevent *bev, void *arg) +{ + if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { + /* enable reading of the reply */ + bufferevent_enable(bev, EV_READ); + test_ok++; + } +} + +static void +http_errorcb(struct bufferevent *bev, short what, void *arg) +{ + test_ok = -2; + event_base_loopexit(arg, NULL); +} + +static void +http_basic_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *evb = evbuffer_new(); + int empty = evhttp_find_header(evhttp_request_get_input_headers(req), "Empty") != NULL; + event_debug(("%s: called\n", __func__)); + evbuffer_add_printf(evb, BASIC_REQUEST_BODY); + + /* For multi-line headers test */ + { + const char *multi = + evhttp_find_header(evhttp_request_get_input_headers(req),"X-multi"); + if (multi) { + if (strcmp("END", multi + strlen(multi) - 3) == 0) + test_ok++; + if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Last")) + test_ok++; + } + } + + /* injecting a bad content-length */ + if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Negative")) + evhttp_add_header(evhttp_request_get_output_headers(req), + "Content-Length", "-100"); + + /* allow sending of an empty reply */ + evhttp_send_reply(req, HTTP_OK, "Everything is fine", + !empty ? evb : NULL); + + evbuffer_free(evb); +} + +static char const* const CHUNKS[] = { + "This is funny", + "but not hilarious.", + "bwv 1052" +}; + +struct chunk_req_state { + struct event_base *base; + struct evhttp_request *req; + int i; +}; + +static void +http_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg) +{ + struct evbuffer *evb = evbuffer_new(); + struct chunk_req_state *state = arg; + struct timeval when = { 0, 0 }; + + evbuffer_add_printf(evb, "%s", CHUNKS[state->i]); + evhttp_send_reply_chunk(state->req, evb); + evbuffer_free(evb); + + if (++state->i < (int) (sizeof(CHUNKS)/sizeof(CHUNKS[0]))) { + event_base_once(state->base, -1, EV_TIMEOUT, + http_chunked_trickle_cb, state, &when); + } else { + evhttp_send_reply_end(state->req); + free(state); + } +} + +static void +http_chunked_cb(struct evhttp_request *req, void *arg) +{ + struct timeval when = { 0, 0 }; + struct chunk_req_state *state = malloc(sizeof(struct chunk_req_state)); + event_debug(("%s: called\n", __func__)); + + memset(state, 0, sizeof(struct chunk_req_state)); + state->req = req; + state->base = arg; + + if (strcmp(evhttp_request_get_uri(req), "/streamed") == 0) { + evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Length", "39"); + } + + /* generate a chunked/streamed reply */ + evhttp_send_reply_start(req, HTTP_OK, "Everything is fine"); + + /* but trickle it across several iterations to ensure we're not + * assuming it comes all at once */ + event_base_once(arg, -1, EV_TIMEOUT, http_chunked_trickle_cb, state, &when); +} + +static void +http_complete_write(evutil_socket_t fd, short what, void *arg) +{ + struct bufferevent *bev = arg; + const char *http_request = "host\r\n" + "Connection: close\r\n" + "\r\n"; + bufferevent_write(bev, http_request, strlen(http_request)); +} + +static void +http_basic_test(void *arg) +{ + struct basic_test_data *data = arg; + struct timeval tv; + struct bufferevent *bev; + evutil_socket_t fd; + const char *http_request; + ev_uint16_t port = 0, port2 = 0; + + test_ok = 0; + + http = http_setup(&port, data->base); + + /* bind to a second socket */ + if (http_bind(http, &port2) == -1) { + fprintf(stdout, "FAILED (bind)\n"); + exit(1); + } + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_readcb, http_writecb, + http_errorcb, data->base); + + /* first half of the http request */ + http_request = + "GET /test HTTP/1.1\r\n" + "Host: some"; + + bufferevent_write(bev, http_request, strlen(http_request)); + evutil_timerclear(&tv); + tv.tv_usec = 10000; + event_base_once(data->base, + -1, EV_TIMEOUT, http_complete_write, bev, &tv); + + event_base_dispatch(data->base); + + tt_assert(test_ok == 3); + + /* connect to the second port */ + bufferevent_free(bev); + evutil_closesocket(fd); + + fd = http_connect("127.0.0.1", port2); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_readcb, http_writecb, + http_errorcb, data->base); + + http_request = + "GET /test HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + tt_assert(test_ok == 5); + + /* Connect to the second port again. This time, send an absolute uri. */ + bufferevent_free(bev); + evutil_closesocket(fd); + + fd = http_connect("127.0.0.1", port2); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_readcb, http_writecb, + http_errorcb, data->base); + + http_request = + "GET http://somehost.net/test HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + tt_assert(test_ok == 7); + + evhttp_free(http); + end: + ; +} + +static void +http_delay_reply(evutil_socket_t fd, short what, void *arg) +{ + struct evhttp_request *req = arg; + + evhttp_send_reply(req, HTTP_OK, "Everything is fine", NULL); + + ++test_ok; +} + +static void +http_delay_cb(struct evhttp_request *req, void *arg) +{ + struct timeval tv; + evutil_timerclear(&tv); + tv.tv_sec = 0; + tv.tv_usec = 200 * 1000; + + event_base_once(arg, -1, EV_TIMEOUT, http_delay_reply, req, &tv); +} + +static void +http_badreq_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *buf = evbuffer_new(); + + evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/xml; charset=UTF-8"); + evbuffer_add_printf(buf, "Hello, %s!", "127.0.0.1"); + + evhttp_send_reply(req, HTTP_OK, "OK", buf); + evbuffer_free(buf); +} + +static void +http_badreq_errorcb(struct bufferevent *bev, short what, void *arg) +{ + event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg)); + /* ignore */ +} + +#ifndef SHUT_WR +#ifdef WIN32 +#define SHUT_WR SD_SEND +#else +#define SHUT_WR 1 +#endif +#endif + +static void +http_badreq_readcb(struct bufferevent *bev, void *arg) +{ + const char *what = "Hello, 127.0.0.1"; + const char *bad_request = "400 Bad Request"; + + if (evbuffer_contains(bufferevent_get_input(bev), bad_request)) { + TT_FAIL(("%s:bad request detected", __func__)); + bufferevent_disable(bev, EV_READ); + event_base_loopexit(arg, NULL); + return; + } + + if (evbuffer_contains(bufferevent_get_input(bev), what)) { + struct evhttp_request *req = evhttp_request_new(NULL, NULL); + enum message_read_status done; + + /* req->kind = EVHTTP_RESPONSE; */ + done = evhttp_parse_firstline(req, bufferevent_get_input(bev)); + if (done != ALL_DATA_READ) + goto out; + + done = evhttp_parse_headers(req, bufferevent_get_input(bev)); + if (done != ALL_DATA_READ) + goto out; + + if (done == 1 && + evhttp_find_header(evhttp_request_get_input_headers(req), + "Content-Type") != NULL) + test_ok++; + + out: + evhttp_request_free(req); + evbuffer_drain(bufferevent_get_input(bev), evbuffer_get_length(bufferevent_get_input(bev))); + } + + shutdown(bufferevent_getfd(bev), SHUT_WR); +} + +static void +http_badreq_successcb(evutil_socket_t fd, short what, void *arg) +{ + event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg)); + event_base_loopexit(exit_base, NULL); +} + +static void +http_bad_request_test(void *arg) +{ + struct basic_test_data *data = arg; + struct timeval tv; + struct bufferevent *bev = NULL; + evutil_socket_t fd; + const char *http_request; + ev_uint16_t port=0, port2=0; + + test_ok = 0; + exit_base = data->base; + + http = http_setup(&port, data->base); + + /* bind to a second socket */ + if (http_bind(http, &port2) == -1) + TT_DIE(("Bind socket failed")); + + /* NULL request test */ + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_badreq_readcb, http_writecb, + http_badreq_errorcb, data->base); + bufferevent_enable(bev, EV_READ); + + /* real NULL request */ + http_request = ""; + + bufferevent_write(bev, http_request, strlen(http_request)); + + shutdown(fd, SHUT_WR); + timerclear(&tv); + tv.tv_usec = 10000; + event_base_once(data->base, -1, EV_TIMEOUT, http_badreq_successcb, bev, &tv); + + event_base_dispatch(data->base); + + bufferevent_free(bev); + evutil_closesocket(fd); + + if (test_ok != 0) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + /* Second answer (BAD REQUEST) on connection close */ + + /* connect to the second port */ + fd = http_connect("127.0.0.1", port2); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_badreq_readcb, http_writecb, + http_badreq_errorcb, data->base); + bufferevent_enable(bev, EV_READ); + + /* first half of the http request */ + http_request = + "GET /badrequest HTTP/1.0\r\n" \ + "Connection: Keep-Alive\r\n" \ + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + timerclear(&tv); + tv.tv_usec = 10000; + event_base_once(data->base, -1, EV_TIMEOUT, http_badreq_successcb, bev, &tv); + + event_base_dispatch(data->base); + + tt_int_op(test_ok, ==, 2); + +end: + evhttp_free(http); + if (bev) + bufferevent_free(bev); +} + +static struct evhttp_connection *delayed_client; + +static void +http_large_delay_cb(struct evhttp_request *req, void *arg) +{ + struct timeval tv; + evutil_timerclear(&tv); + tv.tv_sec = 3; + + event_base_once(arg, -1, EV_TIMEOUT, http_delay_reply, req, &tv); + evhttp_connection_fail(delayed_client, EVCON_HTTP_EOF); +} + +/* + * HTTP DELETE test, just piggyback on the basic test + */ + +static void +http_delete_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *evb = evbuffer_new(); + int empty = evhttp_find_header(evhttp_request_get_input_headers(req), "Empty") != NULL; + + /* Expecting a DELETE request */ + if (evhttp_request_get_command(req) != EVHTTP_REQ_DELETE) { + fprintf(stdout, "FAILED (delete type)\n"); + exit(1); + } + + event_debug(("%s: called\n", __func__)); + evbuffer_add_printf(evb, BASIC_REQUEST_BODY); + + /* allow sending of an empty reply */ + evhttp_send_reply(req, HTTP_OK, "Everything is fine", + !empty ? evb : NULL); + + evbuffer_free(evb); +} + +static void +http_delete_test(void *arg) +{ + struct basic_test_data *data = arg; + struct bufferevent *bev; + evutil_socket_t fd; + const char *http_request; + ev_uint16_t port = 0; + + test_ok = 0; + + http = http_setup(&port, data->base); + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_readcb, http_writecb, + http_errorcb, data->base); + + http_request = + "DELETE /deleteit HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + bufferevent_free(bev); + evutil_closesocket(fd); + + evhttp_free(http); + + tt_int_op(test_ok, ==, 2); + end: + ; +} + +static void +http_allowed_methods_eventcb(struct bufferevent *bev, short what, void *arg) +{ + char **output = arg; + if ((what & (BEV_EVENT_ERROR|BEV_EVENT_EOF))) { + char buf[4096]; + int n; + n = evbuffer_remove(bufferevent_get_input(bev), buf, + sizeof(buf)-1); + if (n >= 0) { + buf[n]='\0'; + if (*output) + free(*output); + *output = strdup(buf); + } + event_base_loopexit(exit_base, NULL); + } +} + +static void +http_allowed_methods_test(void *arg) +{ + struct basic_test_data *data = arg; + struct bufferevent *bev1, *bev2, *bev3; + evutil_socket_t fd1, fd2, fd3; + const char *http_request; + char *result1=NULL, *result2=NULL, *result3=NULL; + ev_uint16_t port = 0; + + exit_base = data->base; + test_ok = 0; + + http = http_setup(&port, data->base); + + fd1 = http_connect("127.0.0.1", port); + + /* GET is out; PATCH is in. */ + evhttp_set_allowed_methods(http, EVHTTP_REQ_PATCH); + + /* Stupid thing to send a request */ + bev1 = bufferevent_socket_new(data->base, fd1, 0); + bufferevent_enable(bev1, EV_READ|EV_WRITE); + bufferevent_setcb(bev1, NULL, NULL, + http_allowed_methods_eventcb, &result1); + + http_request = + "GET /index.html HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev1, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + fd2 = http_connect("127.0.0.1", port); + + bev2 = bufferevent_socket_new(data->base, fd2, 0); + bufferevent_enable(bev2, EV_READ|EV_WRITE); + bufferevent_setcb(bev2, NULL, NULL, + http_allowed_methods_eventcb, &result2); + + http_request = + "PATCH /test HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev2, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + fd3 = http_connect("127.0.0.1", port); + + bev3 = bufferevent_socket_new(data->base, fd3, 0); + bufferevent_enable(bev3, EV_READ|EV_WRITE); + bufferevent_setcb(bev3, NULL, NULL, + http_allowed_methods_eventcb, &result3); + + http_request = + "FLOOP /test HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev3, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + bufferevent_free(bev1); + bufferevent_free(bev2); + bufferevent_free(bev3); + evutil_closesocket(fd1); + evutil_closesocket(fd2); + evutil_closesocket(fd3); + + evhttp_free(http); + + /* Method known but disallowed */ + tt_assert(result1); + tt_assert(!strncmp(result1, "HTTP/1.1 501 ", strlen("HTTP/1.1 501 "))); + + /* Method known and allowed */ + tt_assert(result2); + tt_assert(!strncmp(result2, "HTTP/1.1 200 ", strlen("HTTP/1.1 200 "))); + + /* Method unknown */ + tt_assert(result3); + tt_assert(!strncmp(result3, "HTTP/1.1 501 ", strlen("HTTP/1.1 501 "))); + + end: + if (result1) + free(result1); + if (result2) + free(result2); + if (result3) + free(result3); +} + +static void http_request_done(struct evhttp_request *, void *); +static void http_request_empty_done(struct evhttp_request *, void *); + +static void +_http_connection_test(struct basic_test_data *data, int persistent) +{ + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + + test_ok = 0; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + tt_assert(evhttp_connection_get_base(evcon) == data->base); + + exit_base = data->base; + /* + * At this point, we want to schedule a request to the HTTP + * server using our make request method. + */ + + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok); + + /* try to make another request over the same connection */ + test_ok = 0; + + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* + * if our connections are not supposed to be persistent; request + * a close from the server. + */ + if (!persistent) + evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + tt_abort_msg("couldn't make request"); + } + + event_base_dispatch(data->base); + + /* make another request: request empty reply */ + test_ok = 0; + + req = evhttp_request_new(http_request_empty_done, data->base); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + tt_abort_msg("Couldn't make request"); + exit(1); + } + + event_base_dispatch(data->base); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + +static void +http_connection_test(void *arg) +{ + _http_connection_test(arg, 0); +} +static void +http_persist_connection_test(void *arg) +{ + _http_connection_test(arg, 1); +} + +static struct regress_dns_server_table search_table[] = { + { "localhost", "A", "127.0.0.1", 0 }, + { NULL, NULL, NULL, 0 } +}; + +static void +http_connection_async_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + struct evdns_base *dns_base = NULL; + ev_uint16_t portnum = 0; + char address[64]; + + exit_base = data->base; + tt_assert(regress_dnsserver(data->base, &portnum, search_table)); + + dns_base = evdns_base_new(data->base, 0/* init name servers */); + tt_assert(dns_base); + + /* Add ourself as the only nameserver, and make sure we really are + * the only nameserver. */ + evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum); + evdns_base_nameserver_ip_add(dns_base, address); + + test_ok = 0; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, dns_base, "127.0.0.1", port); + tt_assert(evcon); + + /* + * At this point, we want to schedule a request to the HTTP + * server using our make request method. + */ + + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok); + + /* try to make another request over the same connection */ + test_ok = 0; + + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* + * if our connections are not supposed to be persistent; request + * a close from the server. + */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + tt_abort_msg("couldn't make request"); + } + + event_base_dispatch(data->base); + + /* make another request: request empty reply */ + test_ok = 0; + + req = evhttp_request_new(http_request_empty_done, data->base); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + tt_abort_msg("Couldn't make request"); + exit(1); + } + + event_base_dispatch(data->base); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); + if (dns_base) + evdns_base_free(dns_base, 0); + regress_clean_dnsserver(); +} + +static void +http_request_never_call(struct evhttp_request *req, void *arg) +{ + fprintf(stdout, "FAILED\n"); + exit(1); +} + +static void +http_do_cancel(evutil_socket_t fd, short what, void *arg) +{ + struct evhttp_request *req = arg; + struct timeval tv; + struct event_base *base; + evutil_timerclear(&tv); + tv.tv_sec = 0; + tv.tv_usec = 500 * 1000; + + base = evhttp_connection_get_base(evhttp_request_get_connection(req)); + evhttp_cancel_request(req); + + event_base_loopexit(base, &tv); + + ++test_ok; +} + +static void +http_cancel_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + struct timeval tv; + + exit_base = data->base; + + test_ok = 0; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + /* + * At this point, we want to schedule a request to the HTTP + * server using our make request method. + */ + + req = evhttp_request_new(http_request_never_call, NULL); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/delay"), + !=, -1); + + evutil_timerclear(&tv); + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + + event_base_once(data->base, -1, EV_TIMEOUT, http_do_cancel, req, &tv); + + event_base_dispatch(data->base); + + tt_int_op(test_ok, ==, 2); + + /* try to make another request over the same connection */ + test_ok = 0; + + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test"), + !=, -1); + + event_base_dispatch(data->base); + + /* make another request: request empty reply */ + test_ok = 0; + + req = evhttp_request_new(http_request_empty_done, data->base); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis"); + + /* We give ownership of the request to the connection */ + tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test"), + !=, -1); + + event_base_dispatch(data->base); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + +static void +http_request_done(struct evhttp_request *req, void *arg) +{ + const char *what = arg; + + if (evhttp_request_get_response_code(req) != HTTP_OK) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + test_ok = 1; + EVUTIL_ASSERT(exit_base); + event_base_loopexit(exit_base, NULL); +} + +static void +http_request_expect_error(struct evhttp_request *req, void *arg) +{ + if (evhttp_request_get_response_code(req) == HTTP_OK) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + test_ok = 1; + EVUTIL_ASSERT(arg); + event_base_loopexit(arg, NULL); +} + +/* test virtual hosts */ +static void +http_virtual_host_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + struct evhttp *second = NULL, *third = NULL; + evutil_socket_t fd; + struct bufferevent *bev; + const char *http_request; + + exit_base = data->base; + + http = http_setup(&port, data->base); + + /* virtual host */ + second = evhttp_new(NULL); + evhttp_set_cb(second, "/funnybunny", http_basic_cb, NULL); + third = evhttp_new(NULL); + evhttp_set_cb(third, "/blackcoffee", http_basic_cb, NULL); + + if (evhttp_add_virtual_host(http, "foo.com", second) == -1) { + tt_abort_msg("Couldn't add vhost"); + } + + if (evhttp_add_virtual_host(http, "bar.*.foo.com", third) == -1) { + tt_abort_msg("Couldn't add wildcarded vhost"); + } + + /* add some aliases to the vhosts */ + tt_assert(evhttp_add_server_alias(second, "manolito.info") == 0); + tt_assert(evhttp_add_server_alias(third, "bonkers.org") == 0); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + /* make a request with a different host and expect an error */ + req = evhttp_request_new(http_request_expect_error, data->base); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/funnybunny") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok == 1); + + test_ok = 0; + + /* make a request with the right host and expect a response */ + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "foo.com"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/funnybunny") == -1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok == 1); + + test_ok = 0; + + /* make a request with the right host and expect a response */ + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "bar.magic.foo.com"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/blackcoffee") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok == 1) + + test_ok = 0; + + /* make a request with the right host and expect a response */ + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "manolito.info"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/funnybunny") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok == 1) + + test_ok = 0; + + /* make a request with the right host and expect a response */ + req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY); + + /* Add the Host header. This time with the optional port. */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "bonkers.org:8000"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/blackcoffee") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok == 1) + + test_ok = 0; + + /* Now make a raw request with an absolute URI. */ + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_readcb, http_writecb, + http_errorcb, NULL); + + /* The host in the URI should override the Host: header */ + http_request = + "GET http://manolito.info/funnybunny HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + tt_int_op(test_ok, ==, 2); + + bufferevent_free(bev); + evutil_closesocket(fd); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + + +/* test date header and content length */ + +static void +http_request_empty_done(struct evhttp_request *req, void *arg) +{ + if (evhttp_request_get_response_code(req) != HTTP_OK) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evhttp_find_header(evhttp_request_get_input_headers(req), "Date") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + + if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Length") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (strcmp(evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Length"), + "0")) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 0) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + test_ok = 1; + EVUTIL_ASSERT(arg); + event_base_loopexit(arg, NULL); +} + +/* + * HTTP DISPATCHER test + */ + +void +http_dispatcher_cb(struct evhttp_request *req, void *arg) +{ + + struct evbuffer *evb = evbuffer_new(); + event_debug(("%s: called\n", __func__)); + evbuffer_add_printf(evb, "DISPATCHER_TEST"); + + evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); + + evbuffer_free(evb); +} + +static void +http_dispatcher_test_done(struct evhttp_request *req, void *arg) +{ + struct event_base *base = arg; + const char *what = "DISPATCHER_TEST"; + + if (evhttp_request_get_response_code(req) != HTTP_OK) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) { + fprintf(stderr, "FAILED (content type)\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) { + fprintf(stderr, "FAILED (length %lu vs %lu)\n", + (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what)); + exit(1); + } + + if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) { + fprintf(stderr, "FAILED (data)\n"); + exit(1); + } + + test_ok = 1; + event_base_loopexit(base, NULL); +} + +static void +http_dispatcher_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + + test_ok = 0; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + /* also bind to local host */ + evhttp_connection_set_local_address(evcon, "127.0.0.1"); + + /* + * At this point, we want to schedule an HTTP GET request + * server using our make request method. + */ + + req = evhttp_request_new(http_dispatcher_test_done, data->base); + tt_assert(req); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + +/* + * HTTP POST test. + */ + +void http_postrequest_done(struct evhttp_request *, void *); + +#define POST_DATA "Okay. Not really printf" + +static void +http_post_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + + test_ok = 0; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + /* + * At this point, we want to schedule an HTTP POST request + * server using our make request method. + */ + + req = evhttp_request_new(http_postrequest_done, data->base); + tt_assert(req); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + evbuffer_add_printf(evhttp_request_get_output_buffer(req), POST_DATA); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_int_op(test_ok, ==, 1); + + test_ok = 0; + + req = evhttp_request_new(http_postrequest_done, data->base); + tt_assert(req); + + /* Now try with 100-continue. */ + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue"); + evbuffer_add_printf(evhttp_request_get_output_buffer(req), POST_DATA); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_int_op(test_ok, ==, 1); + + evhttp_connection_free(evcon); + evhttp_free(http); + + end: + ; +} + +void +http_post_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *evb; + event_debug(("%s: called\n", __func__)); + + /* Yes, we are expecting a post request */ + if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) { + fprintf(stdout, "FAILED (post type)\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(POST_DATA)) { + fprintf(stdout, "FAILED (length: %lu vs %lu)\n", + (unsigned long) evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long) strlen(POST_DATA)); + exit(1); + } + + if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), POST_DATA) != 0) { + fprintf(stdout, "FAILED (data)\n"); + fprintf(stdout, "Got :%s\n", evbuffer_pullup(evhttp_request_get_input_buffer(req),-1)); + fprintf(stdout, "Want:%s\n", POST_DATA); + exit(1); + } + + evb = evbuffer_new(); + evbuffer_add_printf(evb, BASIC_REQUEST_BODY); + + evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); + + evbuffer_free(evb); +} + +void +http_postrequest_done(struct evhttp_request *req, void *arg) +{ + const char *what = BASIC_REQUEST_BODY; + struct event_base *base = arg; + + if (req == NULL) { + fprintf(stderr, "FAILED (timeout)\n"); + exit(1); + } + + if (evhttp_request_get_response_code(req) != HTTP_OK) { + + fprintf(stderr, "FAILED (response code)\n"); + exit(1); + } + + if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) { + fprintf(stderr, "FAILED (content type)\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) { + fprintf(stderr, "FAILED (length %lu vs %lu)\n", + (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what)); + exit(1); + } + + if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) { + fprintf(stderr, "FAILED (data)\n"); + exit(1); + } + + test_ok = 1; + event_base_loopexit(base, NULL); +} + +/* + * HTTP PUT test, basically just like POST, but ... + */ + +void http_putrequest_done(struct evhttp_request *, void *); + +#define PUT_DATA "Hi, I'm some PUT data" + +static void +http_put_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + + test_ok = 0; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + /* + * Schedule the HTTP PUT request + */ + + req = evhttp_request_new(http_putrequest_done, data->base); + tt_assert(req); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "someotherhost"); + evbuffer_add_printf(evhttp_request_get_output_buffer(req), PUT_DATA); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_PUT, "/putit") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + evhttp_connection_free(evcon); + evhttp_free(http); + + tt_int_op(test_ok, ==, 1); + end: + ; +} + +void +http_put_cb(struct evhttp_request *req, void *arg) +{ + struct evbuffer *evb; + event_debug(("%s: called\n", __func__)); + + /* Expecting a PUT request */ + if (evhttp_request_get_command(req) != EVHTTP_REQ_PUT) { + fprintf(stdout, "FAILED (put type)\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(PUT_DATA)) { + fprintf(stdout, "FAILED (length: %lu vs %lu)\n", + (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(PUT_DATA)); + exit(1); + } + + if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), PUT_DATA) != 0) { + fprintf(stdout, "FAILED (data)\n"); + fprintf(stdout, "Got :%s\n", evbuffer_pullup(evhttp_request_get_input_buffer(req),-1)); + fprintf(stdout, "Want:%s\n", PUT_DATA); + exit(1); + } + + evb = evbuffer_new(); + evbuffer_add_printf(evb, "That ain't funny"); + + evhttp_send_reply(req, HTTP_OK, "Everything is great", evb); + + evbuffer_free(evb); +} + +void +http_putrequest_done(struct evhttp_request *req, void *arg) +{ + struct event_base *base = arg; + const char *what = "That ain't funny"; + + if (req == NULL) { + fprintf(stderr, "FAILED (timeout)\n"); + exit(1); + } + + if (evhttp_request_get_response_code(req) != HTTP_OK) { + + fprintf(stderr, "FAILED (response code)\n"); + exit(1); + } + + if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) { + fprintf(stderr, "FAILED (content type)\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) { + fprintf(stderr, "FAILED (length %lu vs %lu)\n", + (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what)); + exit(1); + } + + + if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) { + fprintf(stderr, "FAILED (data)\n"); + exit(1); + } + + test_ok = 1; + event_base_loopexit(base, NULL); +} + +static void +http_failure_readcb(struct bufferevent *bev, void *arg) +{ + const char *what = "400 Bad Request"; + if (evbuffer_contains(bufferevent_get_input(bev), what)) { + test_ok = 2; + bufferevent_disable(bev, EV_READ); + event_base_loopexit(arg, NULL); + } +} + +/* + * Testing that the HTTP server can deal with a malformed request. + */ +static void +http_failure_test(void *arg) +{ + struct basic_test_data *data = arg; + struct bufferevent *bev; + evutil_socket_t fd; + const char *http_request; + ev_uint16_t port = 0; + + test_ok = 0; + + http = http_setup(&port, data->base); + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, http_failure_readcb, http_writecb, + http_errorcb, data->base); + + http_request = "illegal request\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + event_base_dispatch(data->base); + + bufferevent_free(bev); + evutil_closesocket(fd); + + evhttp_free(http); + + tt_int_op(test_ok, ==, 2); + end: + ; +} + +static void +close_detect_done(struct evhttp_request *req, void *arg) +{ + struct timeval tv; + tt_assert(req); + tt_assert(evhttp_request_get_response_code(req) == HTTP_OK); + + test_ok = 1; + + end: + evutil_timerclear(&tv); + tv.tv_sec = 3; + event_base_loopexit(arg, &tv); +} + +static void +close_detect_launch(evutil_socket_t fd, short what, void *arg) +{ + struct evhttp_connection *evcon = arg; + struct event_base *base = evhttp_connection_get_base(evcon); + struct evhttp_request *req; + + req = evhttp_request_new(close_detect_done, base); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + tt_fail_msg("Couldn't make request"); + } +} + +static void +close_detect_cb(struct evhttp_request *req, void *arg) +{ + struct evhttp_connection *evcon = arg; + struct event_base *base = evhttp_connection_get_base(evcon); + struct timeval tv; + + if (req != NULL && evhttp_request_get_response_code(req) != HTTP_OK) { + tt_abort_msg("Failed"); + } + + evutil_timerclear(&tv); + tv.tv_sec = 3; /* longer than the http time out */ + + /* launch a new request on the persistent connection in 3 seconds */ + event_base_once(base, -1, EV_TIMEOUT, close_detect_launch, evcon, &tv); + end: + ; +} + + +static void +_http_close_detection(struct basic_test_data *data, int with_delay) +{ + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + + test_ok = 0; + http = http_setup(&port, data->base); + + /* 2 second timeout */ + evhttp_set_timeout(http, 1); + + evcon = evhttp_connection_base_new(data->base, NULL, + "127.0.0.1", port); + tt_assert(evcon); + delayed_client = evcon; + + /* + * At this point, we want to schedule a request to the HTTP + * server using our make request method. + */ + + req = evhttp_request_new(close_detect_cb, evcon); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, + req, EVHTTP_REQ_GET, with_delay ? "/largedelay" : "/test") == -1) { + tt_abort_msg("couldn't make request"); + exit(1); + } + + event_base_dispatch(data->base); + + /* at this point, the http server should have no connection */ + tt_assert(TAILQ_FIRST(&http->connections) == NULL); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} +static void +http_close_detection_test(void *arg) +{ + _http_close_detection(arg, 0); +} +static void +http_close_detection_delay_test(void *arg) +{ + _http_close_detection(arg, 1); +} + +static void +http_highport_test(void *arg) +{ + struct basic_test_data *data = arg; + int i = -1; + struct evhttp *myhttp = NULL; + + /* Try a few different ports */ + for (i = 0; i < 50; ++i) { + myhttp = evhttp_new(data->base); + if (evhttp_bind_socket(myhttp, "127.0.0.1", 65535 - i) == 0) { + test_ok = 1; + evhttp_free(myhttp); + return; + } + evhttp_free(myhttp); + } + + tt_fail_msg("Couldn't get a high port"); +} + +static void +http_bad_header_test(void *ptr) +{ + struct evkeyvalq headers; + + TAILQ_INIT(&headers); + + tt_want(evhttp_add_header(&headers, "One", "Two") == 0); + tt_want(evhttp_add_header(&headers, "One", "Two\r\n Three") == 0); + tt_want(evhttp_add_header(&headers, "One\r", "Two") == -1); + tt_want(evhttp_add_header(&headers, "One\n", "Two") == -1); + tt_want(evhttp_add_header(&headers, "One", "Two\r") == -1); + tt_want(evhttp_add_header(&headers, "One", "Two\n") == -1); + + evhttp_clear_headers(&headers); +} + +static int validate_header( + const struct evkeyvalq* headers, + const char *key, const char *value) +{ + const char *real_val = evhttp_find_header(headers, key); + tt_assert(real_val != NULL); + tt_want(strcmp(real_val, value) == 0); +end: + return (0); +} + +static void +http_parse_query_test(void *ptr) +{ + struct evkeyvalq headers; + int r; + + TAILQ_INIT(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test", &headers); + tt_want(validate_header(&headers, "q", "test") == 0); + tt_int_op(r, ==, 0); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test&foo=bar", &headers); + tt_want(validate_header(&headers, "q", "test") == 0); + tt_want(validate_header(&headers, "foo", "bar") == 0); + tt_int_op(r, ==, 0); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test+foo", &headers); + tt_want(validate_header(&headers, "q", "test foo") == 0); + tt_int_op(r, ==, 0); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test%0Afoo", &headers); + tt_want(validate_header(&headers, "q", "test\nfoo") == 0); + tt_int_op(r, ==, 0); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test%0Dfoo", &headers); + tt_want(validate_header(&headers, "q", "test\rfoo") == 0); + tt_int_op(r, ==, 0); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test&&q2", &headers); + tt_int_op(r, ==, -1); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test+this", &headers); + tt_want(validate_header(&headers, "q", "test this") == 0); + tt_int_op(r, ==, 0); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=test&q2=foo", &headers); + tt_int_op(r, ==, 0); + tt_want(validate_header(&headers, "q", "test") == 0); + tt_want(validate_header(&headers, "q2", "foo") == 0); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q&q2=foo", &headers); + tt_int_op(r, ==, -1); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=foo&q2", &headers); + tt_int_op(r, ==, -1); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=foo&q2&q3=x", &headers); + tt_int_op(r, ==, -1); + evhttp_clear_headers(&headers); + + r = evhttp_parse_query("http://www.test.com/?q=&q2=&q3=", &headers); + tt_int_op(r, ==, 0); + tt_want(validate_header(&headers, "q", "") == 0); + tt_want(validate_header(&headers, "q2", "") == 0); + tt_want(validate_header(&headers, "q3", "") == 0); + evhttp_clear_headers(&headers); + +end: + evhttp_clear_headers(&headers); +} + +static void +http_parse_uri_test(void *ptr) +{ + const int nonconform = (ptr != NULL); + const unsigned parse_flags = + nonconform ? EVHTTP_URI_NONCONFORMANT : 0; + struct evhttp_uri *uri = NULL; + char url_tmp[4096]; +#define URI_PARSE(uri) \ + evhttp_uri_parse_with_flags((uri), parse_flags) + +#define TT_URI(want) do { \ + char *ret = evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)); \ + tt_want(ret != NULL); \ + tt_want(ret == url_tmp); \ + if (strcmp(ret,want) != 0) \ + TT_FAIL(("\"%s\" != \"%s\"",ret,want)); \ + } while(0) + + tt_want(evhttp_uri_join(NULL, 0, 0) == NULL); + tt_want(evhttp_uri_join(NULL, url_tmp, 0) == NULL); + tt_want(evhttp_uri_join(NULL, url_tmp, sizeof(url_tmp)) == NULL); + + /* bad URIs: parsing */ +#define BAD(s) do { \ + if (URI_PARSE(s) != NULL) \ + TT_FAIL(("Expected error parsing \"%s\"",s)); \ + } while(0) + /* Nonconformant URIs we can parse: parsing */ +#define NCF(s) do { \ + uri = URI_PARSE(s); \ + if (uri != NULL && !nonconform) { \ + TT_FAIL(("Expected error parsing \"%s\"",s)); \ + } else if (uri == NULL && nonconform) { \ + TT_FAIL(("Couldn't parse nonconformant URI \"%s\"", \ + s)); \ + } \ + if (uri) { \ + tt_want(evhttp_uri_join(uri, url_tmp, \ + sizeof(url_tmp))); \ + evhttp_uri_free(uri); \ + } \ + } while(0) + + NCF("http://www.test.com/ why hello"); + NCF("http://www.test.com/why-hello\x01"); + NCF("http://www.test.com/why-hello?\x01"); + NCF("http://www.test.com/why-hello#\x01"); + BAD("http://www.\x01.test.com/why-hello"); + BAD("http://www.%7test.com/why-hello"); + NCF("http://www.test.com/why-hell%7o"); + BAD("h%3ttp://www.test.com/why-hello"); + NCF("http://www.test.com/why-hello%7"); + NCF("http://www.test.com/why-hell%7o"); + NCF("http://www.test.com/foo?ba%r"); + NCF("http://www.test.com/foo#ba%r"); + BAD("99:99/foo"); + BAD("http://www.test.com:999x/"); + BAD("http://www.test.com:x/"); + BAD("http://[hello-there]/"); + BAD("http://[::1]]/"); + BAD("http://[::1/"); + BAD("http://[foob/"); + BAD("http://[/"); + BAD("http://[ffff:ffff:ffff:ffff:Ffff:ffff:ffff:" + "ffff:ffff:ffff:ffff:ffff:ffff:ffff]/"); + BAD("http://[vX.foo]/"); + BAD("http://[vX.foo]/"); + BAD("http://[v.foo]/"); + BAD("http://[v5.fo%o]/"); + BAD("http://[v5X]/"); + BAD("http://[v5]/"); + BAD("http://[]/"); + BAD("http://f\x01red@www.example.com/"); + BAD("http://f%0red@www.example.com/"); + BAD("http://www.example.com:9999999999999999999999999999999999999/"); + BAD("http://www.example.com:hihi/"); + BAD("://www.example.com/"); + + /* bad URIs: joining */ + uri = evhttp_uri_new(); + tt_want(0==evhttp_uri_set_host(uri, "www.example.com")); + tt_want(evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)) != NULL); + /* not enough space: */ + tt_want(evhttp_uri_join(uri, url_tmp, 3) == NULL); + /* host is set, but path doesn't start with "/": */ + tt_want(0==evhttp_uri_set_path(uri, "hi_mom")); + tt_want(evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)) == NULL); + tt_want(evhttp_uri_join(uri, NULL, sizeof(url_tmp))==NULL); + tt_want(evhttp_uri_join(uri, url_tmp, 0)==NULL); + evhttp_uri_free(uri); + uri = URI_PARSE("mailto:foo@bar"); + tt_want(uri != NULL); + tt_want(evhttp_uri_get_host(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(!strcmp(evhttp_uri_get_scheme(uri), "mailto")); + tt_want(!strcmp(evhttp_uri_get_path(uri), "foo@bar")); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("mailto:foo@bar"); + evhttp_uri_free(uri); + + uri = evhttp_uri_new(); + /* Bad URI usage: setting invalid values */ + tt_want(-1 == evhttp_uri_set_scheme(uri,"")); + tt_want(-1 == evhttp_uri_set_scheme(uri,"33")); + tt_want(-1 == evhttp_uri_set_scheme(uri,"hi!")); + tt_want(-1 == evhttp_uri_set_userinfo(uri,"hello@")); + tt_want(-1 == evhttp_uri_set_host(uri,"[1.2.3.4]")); + tt_want(-1 == evhttp_uri_set_host(uri,"[")); + tt_want(-1 == evhttp_uri_set_host(uri,"www.[foo].com")); + tt_want(-1 == evhttp_uri_set_port(uri,-3)); + tt_want(-1 == evhttp_uri_set_path(uri,"hello?world")); + tt_want(-1 == evhttp_uri_set_query(uri,"hello#world")); + tt_want(-1 == evhttp_uri_set_fragment(uri,"hello#world")); + /* Valid URI usage: setting valid values */ + tt_want(0 == evhttp_uri_set_scheme(uri,"http")); + tt_want(0 == evhttp_uri_set_scheme(uri,NULL)); + tt_want(0 == evhttp_uri_set_userinfo(uri,"username:pass")); + tt_want(0 == evhttp_uri_set_userinfo(uri,NULL)); + tt_want(0 == evhttp_uri_set_host(uri,"www.example.com")); + tt_want(0 == evhttp_uri_set_host(uri,"1.2.3.4")); + tt_want(0 == evhttp_uri_set_host(uri,"[1:2:3:4::]")); + tt_want(0 == evhttp_uri_set_host(uri,"[v7.wobblewobble]")); + tt_want(0 == evhttp_uri_set_host(uri,NULL)); + tt_want(0 == evhttp_uri_set_host(uri,"")); + tt_want(0 == evhttp_uri_set_port(uri, -1)); + tt_want(0 == evhttp_uri_set_port(uri, 80)); + tt_want(0 == evhttp_uri_set_port(uri, 65535)); + tt_want(0 == evhttp_uri_set_path(uri, "")); + tt_want(0 == evhttp_uri_set_path(uri, "/documents/public/index.html")); + tt_want(0 == evhttp_uri_set_path(uri, NULL)); + tt_want(0 == evhttp_uri_set_query(uri, "key=val&key2=val2")); + tt_want(0 == evhttp_uri_set_query(uri, "keyvalblarg")); + tt_want(0 == evhttp_uri_set_query(uri, "")); + tt_want(0 == evhttp_uri_set_query(uri, NULL)); + tt_want(0 == evhttp_uri_set_fragment(uri, "")); + tt_want(0 == evhttp_uri_set_fragment(uri, "here?i?am")); + tt_want(0 == evhttp_uri_set_fragment(uri, NULL)); + evhttp_uri_free(uri); + + /* Valid parsing */ + uri = URI_PARSE("http://www.test.com/?q=t%33est"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=t%33est") == 0); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("http://www.test.com/?q=t%33est"); + evhttp_uri_free(uri); + + uri = URI_PARSE("http://%77ww.test.com"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "%77ww.test.com") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("http://%77ww.test.com"); + evhttp_uri_free(uri); + + uri = URI_PARSE("http://www.test.com?q=test"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("http://www.test.com?q=test"); + evhttp_uri_free(uri); + + uri = URI_PARSE("http://www.test.com#fragment"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want_str_op(evhttp_uri_get_fragment(uri), ==, "fragment"); + TT_URI("http://www.test.com#fragment"); + evhttp_uri_free(uri); + + uri = URI_PARSE("http://8000/"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "8000") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("http://8000/"); + evhttp_uri_free(uri); + + uri = URI_PARSE("http://:8000/"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == 8000); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("http://:8000/"); + evhttp_uri_free(uri); + + uri = URI_PARSE("http://www.test.com:/"); /* empty port */ + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0); + tt_want_str_op(evhttp_uri_get_path(uri), ==, "/"); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("http://www.test.com/"); + evhttp_uri_free(uri); + + uri = URI_PARSE("http://www.test.com:"); /* empty port 2 */ + tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("http://www.test.com"); + evhttp_uri_free(uri); + + uri = URI_PARSE("ftp://www.test.com/?q=test"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("ftp://www.test.com/?q=test"); + evhttp_uri_free(uri); + + uri = URI_PARSE("ftp://[::1]:999/?q=test"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "[::1]") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == 999); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("ftp://[::1]:999/?q=test"); + evhttp_uri_free(uri); + + uri = URI_PARSE("ftp://[ff00::127.0.0.1]/?q=test"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "[ff00::127.0.0.1]") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("ftp://[ff00::127.0.0.1]/?q=test"); + evhttp_uri_free(uri); + + uri = URI_PARSE("ftp://[v99.not_(any:time)_soon]/?q=test"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "[v99.not_(any:time)_soon]") == 0); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("ftp://[v99.not_(any:time)_soon]/?q=test"); + evhttp_uri_free(uri); + + uri = URI_PARSE("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0); + tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user:pass") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0); + tt_want(evhttp_uri_get_port(uri) == 42); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=test&s=some+thing") == 0); + tt_want(strcmp(evhttp_uri_get_fragment(uri), "fragment") == 0); + TT_URI("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment"); + evhttp_uri_free(uri); + + uri = URI_PARSE("scheme://user@foo.com/#fragment"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0); + tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(strcmp(evhttp_uri_get_fragment(uri), "fragment") == 0); + TT_URI("scheme://user@foo.com/#fragment"); + evhttp_uri_free(uri); + + uri = URI_PARSE("scheme://%75ser@foo.com/#frag@ment"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0); + tt_want(strcmp(evhttp_uri_get_userinfo(uri), "%75ser") == 0); + tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(strcmp(evhttp_uri_get_fragment(uri), "frag@ment") == 0); + TT_URI("scheme://%75ser@foo.com/#frag@ment"); + evhttp_uri_free(uri); + + uri = URI_PARSE("file:///some/path/to/the/file"); + tt_want(strcmp(evhttp_uri_get_scheme(uri), "file") == 0); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "/some/path/to/the/file") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("file:///some/path/to/the/file"); + evhttp_uri_free(uri); + + uri = URI_PARSE("///some/path/to/the-file"); + tt_want(uri != NULL); + tt_want(evhttp_uri_get_scheme(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "/some/path/to/the-file") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("///some/path/to/the-file"); + evhttp_uri_free(uri); + + uri = URI_PARSE("/s:ome/path/to/the-file?q=99#fred"); + tt_want(uri != NULL); + tt_want(evhttp_uri_get_scheme(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_host(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "/s:ome/path/to/the-file") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=99") == 0); + tt_want(strcmp(evhttp_uri_get_fragment(uri), "fred") == 0); + TT_URI("/s:ome/path/to/the-file?q=99#fred"); + evhttp_uri_free(uri); + + uri = URI_PARSE("relative/path/with/co:lon"); + tt_want(uri != NULL); + tt_want(evhttp_uri_get_scheme(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_host(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "relative/path/with/co:lon") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(evhttp_uri_get_fragment(uri) == NULL); + TT_URI("relative/path/with/co:lon"); + evhttp_uri_free(uri); + + uri = URI_PARSE("bob?q=99&q2=q?33#fr?ed"); + tt_want(uri != NULL); + tt_want(evhttp_uri_get_scheme(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_host(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "bob") == 0); + tt_want(strcmp(evhttp_uri_get_query(uri), "q=99&q2=q?33") == 0); + tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0); + TT_URI("bob?q=99&q2=q?33#fr?ed"); + evhttp_uri_free(uri); + + uri = URI_PARSE("#fr?ed"); + tt_want(uri != NULL); + tt_want(evhttp_uri_get_scheme(uri) == NULL); + tt_want(evhttp_uri_get_userinfo(uri) == NULL); + tt_want(evhttp_uri_get_host(uri) == NULL); + tt_want(evhttp_uri_get_port(uri) == -1); + tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0); + tt_want(evhttp_uri_get_query(uri) == NULL); + tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0); + TT_URI("#fr?ed"); + evhttp_uri_free(uri); +#undef URI_PARSE +#undef TT_URI +#undef BAD +} + +static void +http_uriencode_test(void *ptr) +{ + char *s=NULL, *s2=NULL; + size_t sz; + +#define ENC(from,want,plus) do { \ + s = evhttp_uriencode((from), -1, (plus)); \ + tt_assert(s); \ + tt_str_op(s,==,(want)); \ + sz = -1; \ + s2 = evhttp_uridecode((s), (plus), &sz); \ + tt_assert(s2); \ + tt_str_op(s2,==,(from)); \ + tt_int_op(sz,==,strlen(from)); \ + free(s); \ + free(s2); \ + s = s2 = NULL; \ + } while (0) + +#define DEC(from,want,dp) do { \ + s = evhttp_uridecode((from),(dp),&sz); \ + tt_assert(s); \ + tt_str_op(s,==,(want)); \ + tt_int_op(sz,==,strlen(want)); \ + free(s); \ + s = NULL; \ + } while (0) + +#define OLD_DEC(from,want) do { \ + s = evhttp_decode_uri((from)); \ + tt_assert(s); \ + tt_str_op(s,==,(want)); \ + free(s); \ + s = NULL; \ + } while (0) + + + ENC("Hello", "Hello",0); + ENC("99", "99",0); + ENC("", "",0); + ENC( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-.~_", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-.~_",0); + ENC(" ", "%20",0); + ENC(" ", "+",1); + ENC("\xff\xf0\xe0", "%FF%F0%E0",0); + ENC("\x01\x19", "%01%19",1); + ENC("http://www.ietf.org/rfc/rfc3986.txt", + "http%3A%2F%2Fwww.ietf.org%2Frfc%2Frfc3986.txt",1); + + ENC("1+2=3", "1%2B2%3D3",1); + ENC("1+2=3", "1%2B2%3D3",0); + + /* Now try encoding with internal NULs. */ + s = evhttp_uriencode("hello\0world", 11, 0); + tt_assert(s); + tt_str_op(s,==,"hello%00world"); + free(s); + s = NULL; + + /* Now try out some decoding cases that we don't generate with + * encode_uri: Make sure that malformed stuff doesn't crash... */ + DEC("%%xhello th+ere \xff", + "%%xhello th+ere \xff", 0); + /* Make sure plus decoding works */ + DEC("plus+should%20work+", "plus should work ",1); + /* Try some lowercase hex */ + DEC("%f0%a0%b0", "\xf0\xa0\xb0",1); + + /* Try an internal NUL. */ + sz = 0; + s = evhttp_uridecode("%00%00x%00%00", 1, &sz); + tt_int_op(sz,==,5); + tt_assert(!memcmp(s, "\0\0x\0\0", 5)); + free(s); + s = NULL; + + /* Try with size == NULL */ + sz = 0; + s = evhttp_uridecode("%00%00x%00%00", 1, NULL); + tt_assert(!memcmp(s, "\0\0x\0\0", 5)); + free(s); + s = NULL; + + /* Test out the crazy old behavior of the deprecated + * evhttp_decode_uri */ + OLD_DEC("http://example.com/normal+path/?key=val+with+spaces", + "http://example.com/normal+path/?key=val with spaces"); + +end: + if (s) + free(s); + if (s2) + free(s2); +#undef ENC +#undef DEC +#undef OLD_DEC +} + +static void +http_base_test(void *ptr) +{ + struct event_base *base = NULL; + struct bufferevent *bev; + evutil_socket_t fd; + const char *http_request; + ev_uint16_t port = 0; + + test_ok = 0; + base = event_base_new(); + http = http_setup(&port, base); + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(base, fd, 0); + bufferevent_setcb(bev, http_readcb, http_writecb, + http_errorcb, base); + bufferevent_base_set(base, bev); + + http_request = + "GET /test HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + event_base_dispatch(base); + + bufferevent_free(bev); + evutil_closesocket(fd); + + evhttp_free(http); + + tt_int_op(test_ok, ==, 2); + +end: + if (base) + event_base_free(base); +} + +/* + * the server is just going to close the connection if it times out during + * reading the headers. + */ + +static void +http_incomplete_readcb(struct bufferevent *bev, void *arg) +{ + test_ok = -1; + event_base_loopexit(exit_base,NULL); +} + +static void +http_incomplete_errorcb(struct bufferevent *bev, short what, void *arg) +{ + if (what == (BEV_EVENT_READING|BEV_EVENT_EOF)) + test_ok++; + else + test_ok = -2; + event_base_loopexit(exit_base,NULL); +} + +static void +http_incomplete_writecb(struct bufferevent *bev, void *arg) +{ + if (arg != NULL) { + evutil_socket_t fd = *(evutil_socket_t *)arg; + /* terminate the write side to simulate EOF */ + shutdown(fd, SHUT_WR); + } + if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { + /* enable reading of the reply */ + bufferevent_enable(bev, EV_READ); + test_ok++; + } +} + +static void +_http_incomplete_test(struct basic_test_data *data, int use_timeout) +{ + struct bufferevent *bev; + evutil_socket_t fd; + const char *http_request; + ev_uint16_t port = 0; + struct timeval tv_start, tv_end; + + exit_base = data->base; + + test_ok = 0; + + http = http_setup(&port, data->base); + evhttp_set_timeout(http, 1); + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, + http_incomplete_readcb, http_incomplete_writecb, + http_incomplete_errorcb, use_timeout ? NULL : &fd); + + http_request = + "GET /test HTTP/1.1\r\n" + "Host: somehost\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + evutil_gettimeofday(&tv_start, NULL); + + event_base_dispatch(data->base); + + evutil_gettimeofday(&tv_end, NULL); + evutil_timersub(&tv_end, &tv_start, &tv_end); + + bufferevent_free(bev); + if (use_timeout) { + evutil_closesocket(fd); + } + + evhttp_free(http); + + if (use_timeout && tv_end.tv_sec >= 3) { + tt_abort_msg("time"); + } else if (!use_timeout && tv_end.tv_sec >= 1) { + /* we should be done immediately */ + tt_abort_msg("time"); + } + + tt_int_op(test_ok, ==, 2); + end: + ; +} +static void +http_incomplete_test(void *arg) +{ + _http_incomplete_test(arg, 0); +} +static void +http_incomplete_timeout_test(void *arg) +{ + _http_incomplete_test(arg, 1); +} + +/* + * the server is going to reply with chunked data. + */ + +static void +http_chunked_readcb(struct bufferevent *bev, void *arg) +{ + /* nothing here */ +} + +static void +http_chunked_errorcb(struct bufferevent *bev, short what, void *arg) +{ + if (!test_ok) + goto out; + + test_ok = -1; + + if ((what & BEV_EVENT_EOF) != 0) { + struct evhttp_request *req = evhttp_request_new(NULL, NULL); + const char *header; + enum message_read_status done; + + /* req->kind = EVHTTP_RESPONSE; */ + done = evhttp_parse_firstline(req, bufferevent_get_input(bev)); + if (done != ALL_DATA_READ) + goto out; + + done = evhttp_parse_headers(req, bufferevent_get_input(bev)); + if (done != ALL_DATA_READ) + goto out; + + header = evhttp_find_header(evhttp_request_get_input_headers(req), "Transfer-Encoding"); + if (header == NULL || strcmp(header, "chunked")) + goto out; + + header = evhttp_find_header(evhttp_request_get_input_headers(req), "Connection"); + if (header == NULL || strcmp(header, "close")) + goto out; + + header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF); + if (header == NULL) + goto out; + /* 13 chars */ + if (strcmp(header, "d")) + goto out; + free((char*)header); + + if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 13), + "This is funny", 13)) + goto out; + + evbuffer_drain(bufferevent_get_input(bev), 13 + 2); + + header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF); + if (header == NULL) + goto out; + /* 18 chars */ + if (strcmp(header, "12")) + goto out; + free((char *)header); + + if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 18), + "but not hilarious.", 18)) + goto out; + + evbuffer_drain(bufferevent_get_input(bev), 18 + 2); + + header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF); + if (header == NULL) + goto out; + /* 8 chars */ + if (strcmp(header, "8")) + goto out; + free((char *)header); + + if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 8), + "bwv 1052.", 8)) + goto out; + + evbuffer_drain(bufferevent_get_input(bev), 8 + 2); + + header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF); + if (header == NULL) + goto out; + /* 0 chars */ + if (strcmp(header, "0")) + goto out; + free((char *)header); + + test_ok = 2; + + evhttp_request_free(req); + } + +out: + event_base_loopexit(arg, NULL); +} + +static void +http_chunked_writecb(struct bufferevent *bev, void *arg) +{ + if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) { + /* enable reading of the reply */ + bufferevent_enable(bev, EV_READ); + test_ok++; + } +} + +static void +http_chunked_request_done(struct evhttp_request *req, void *arg) +{ + if (evhttp_request_get_response_code(req) != HTTP_OK) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evhttp_find_header(evhttp_request_get_input_headers(req), + "Transfer-Encoding") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 13 + 18 + 8) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (strncmp((char *)evbuffer_pullup(evhttp_request_get_input_buffer(req), 13 + 18 + 8), + "This is funnybut not hilarious.bwv 1052", + 13 + 18 + 8)) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + test_ok = 1; + event_base_loopexit(arg, NULL); +} + +static void +http_chunk_out_test(void *arg) +{ + struct basic_test_data *data = arg; + struct bufferevent *bev; + evutil_socket_t fd; + const char *http_request; + ev_uint16_t port = 0; + struct timeval tv_start, tv_end; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + int i; + + exit_base = data->base; + test_ok = 0; + + http = http_setup(&port, data->base); + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_socket_new(data->base, fd, 0); + bufferevent_setcb(bev, + http_chunked_readcb, http_chunked_writecb, + http_chunked_errorcb, data->base); + + http_request = + "GET /chunked HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + evutil_gettimeofday(&tv_start, NULL); + + event_base_dispatch(data->base); + + bufferevent_free(bev); + + evutil_gettimeofday(&tv_end, NULL); + evutil_timersub(&tv_end, &tv_start, &tv_end); + + tt_int_op(tv_end.tv_sec, <, 1); + + tt_int_op(test_ok, ==, 2); + + /* now try again with the regular connection object */ + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + /* make two requests to check the keepalive behavior */ + for (i = 0; i < 2; i++) { + test_ok = 0; + req = evhttp_request_new(http_chunked_request_done,data->base); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, + EVHTTP_REQ_GET, "/chunked") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_assert(test_ok == 1); + } + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + +static void +http_stream_out_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + + test_ok = 0; + exit_base = data->base; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + /* + * At this point, we want to schedule a request to the HTTP + * server using our make request method. + */ + + req = evhttp_request_new(http_request_done, + (void *)"This is funnybut not hilarious.bwv 1052"); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/streamed") + == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + +static void +http_stream_in_chunk(struct evhttp_request *req, void *arg) +{ + struct evbuffer *reply = arg; + + if (evhttp_request_get_response_code(req) != HTTP_OK) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + evbuffer_add_buffer(reply, evhttp_request_get_input_buffer(req)); +} + +static void +http_stream_in_done(struct evhttp_request *req, void *arg) +{ + if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 0) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + event_base_loopexit(exit_base, NULL); +} + +/** + * Makes a request and reads the response in chunks. + */ +static void +_http_stream_in_test(struct basic_test_data *data, char const *url, + size_t expected_len, char const *expected) +{ + struct evhttp_connection *evcon; + struct evbuffer *reply = evbuffer_new(); + struct evhttp_request *req = NULL; + ev_uint16_t port = 0; + + exit_base = data->base; + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL,"127.0.0.1", port); + tt_assert(evcon); + + req = evhttp_request_new(http_stream_in_done, reply); + evhttp_request_set_chunked_cb(req, http_stream_in_chunk); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, url) == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + if (evbuffer_get_length(reply) != expected_len) { + TT_DIE(("reply length %lu; expected %lu; FAILED (%s)\n", + (unsigned long)evbuffer_get_length(reply), + (unsigned long)expected_len, + (char*)evbuffer_pullup(reply, -1))); + } + + if (memcmp(evbuffer_pullup(reply, -1), expected, expected_len) != 0) { + tt_abort_msg("Memory mismatch"); + } + + test_ok = 1; + end: + if (reply) + evbuffer_free(reply); + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + +static void +http_stream_in_test(void *arg) +{ + _http_stream_in_test(arg, "/chunked", 13 + 18 + 8, + "This is funnybut not hilarious.bwv 1052"); + + _http_stream_in_test(arg, "/test", strlen(BASIC_REQUEST_BODY), + BASIC_REQUEST_BODY); +} + +static void +http_stream_in_cancel_chunk(struct evhttp_request *req, void *arg) +{ + tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_OK); + + end: + evhttp_cancel_request(req); + event_base_loopexit(arg, NULL); +} + +static void +http_stream_in_cancel_done(struct evhttp_request *req, void *arg) +{ + /* should never be called */ + tt_fail_msg("In cancel done"); +} + +static void +http_stream_in_cancel_test(void *arg) +{ + struct basic_test_data *data = arg; + struct evhttp_connection *evcon; + struct evhttp_request *req = NULL; + ev_uint16_t port = 0; + + http = http_setup(&port, data->base); + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + req = evhttp_request_new(http_stream_in_cancel_done, data->base); + evhttp_request_set_chunked_cb(req, http_stream_in_cancel_chunk); + + /* We give ownership of the request to the connection */ + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/chunked") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + test_ok = 1; + end: + evhttp_connection_free(evcon); + evhttp_free(http); + +} + +static void +http_connection_fail_done(struct evhttp_request *req, void *arg) +{ + /* An ENETUNREACH error results in an unrecoverable + * evhttp_connection error (see evhttp_connection_fail()). The + * connection will be reset, and the user will be notified with a NULL + * req parameter. */ + tt_assert(!req); + + test_ok = 1; + + end: + event_base_loopexit(arg, NULL); +} + +/* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH + * error on connection. */ +static void +http_connection_fail_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + + exit_base = data->base; + test_ok = 0; + + /* auto detect a port */ + http = http_setup(&port, data->base); + evhttp_free(http); + http = NULL; + + /* Pick an unroutable address. This administratively scoped multicast + * address should do when working with TCP. */ + evcon = evhttp_connection_base_new(data->base, NULL, "239.10.20.30", 80); + tt_assert(evcon); + + /* + * At this point, we want to schedule an HTTP GET request + * server using our make request method. + */ + + req = evhttp_request_new(http_connection_fail_done, data->base); + tt_assert(req); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) { + tt_abort_msg("Couldn't make request"); + } + + event_base_dispatch(data->base); + + tt_int_op(test_ok, ==, 1); + + end: + if (evcon) + evhttp_connection_free(evcon); +} + +static void +http_connection_retry_done(struct evhttp_request *req, void *arg) +{ + tt_assert(req); + tt_int_op(evhttp_request_get_response_code(req), !=, HTTP_OK); + if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") != NULL) { + tt_abort_msg("(content type)\n"); + } + + tt_uint_op(evbuffer_get_length(evhttp_request_get_input_buffer(req)), ==, 0); + + test_ok = 1; + end: + event_base_loopexit(arg,NULL); +} + +static struct event_base *http_make_web_server_base=NULL; +static void +http_make_web_server(evutil_socket_t fd, short what, void *arg) +{ + ev_uint16_t port = *(ev_uint16_t*)arg; + http = http_setup(&port, http_make_web_server_base); +} + +static void +http_connection_retry_test(void *arg) +{ + struct basic_test_data *data = arg; + ev_uint16_t port = 0; + struct evhttp_connection *evcon = NULL; + struct evhttp_request *req = NULL; + struct timeval tv, tv_start, tv_end; + + exit_base = data->base; + test_ok = 0; + + /* auto detect a port */ + http = http_setup(&port, data->base); + evhttp_free(http); + http = NULL; + + evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + tt_assert(evcon); + + evhttp_connection_set_timeout(evcon, 1); + /* also bind to local host */ + evhttp_connection_set_local_address(evcon, "127.0.0.1"); + + /* + * At this point, we want to schedule an HTTP GET request + * server using our make request method. + */ + + req = evhttp_request_new(http_connection_retry_done, data->base); + tt_assert(req); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/?arg=val") == -1) { + tt_abort_msg("Couldn't make request"); + } + + evutil_gettimeofday(&tv_start, NULL); + event_base_dispatch(data->base); + evutil_gettimeofday(&tv_end, NULL); + evutil_timersub(&tv_end, &tv_start, &tv_end); + tt_int_op(tv_end.tv_sec, <, 1); + + tt_int_op(test_ok, ==, 1); + + /* + * now test the same but with retries + */ + test_ok = 0; + + evhttp_connection_set_timeout(evcon, 1); + evhttp_connection_set_retries(evcon, 1); + + req = evhttp_request_new(http_connection_retry_done, data->base); + tt_assert(req); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/?arg=val") == -1) { + tt_abort_msg("Couldn't make request"); + } + + evutil_gettimeofday(&tv_start, NULL); + event_base_dispatch(data->base); + evutil_gettimeofday(&tv_end, NULL); + evutil_timersub(&tv_end, &tv_start, &tv_end); + tt_int_op(tv_end.tv_sec, >, 1); + tt_int_op(tv_end.tv_sec, <, 6); + + tt_assert(test_ok == 1); + + /* + * now test the same but with retries and give it a web server + * at the end + */ + test_ok = 0; + + evhttp_connection_set_timeout(evcon, 1); + evhttp_connection_set_retries(evcon, 3); + + req = evhttp_request_new(http_dispatcher_test_done, data->base); + tt_assert(req); + + /* Add the information that we care about */ + evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost"); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + "/?arg=val") == -1) { + tt_abort_msg("Couldn't make request"); + } + + /* start up a web server one second after the connection tried + * to send a request + */ + evutil_timerclear(&tv); + tv.tv_sec = 1; + http_make_web_server_base = data->base; + event_base_once(data->base, -1, EV_TIMEOUT, http_make_web_server, &port, &tv); + + evutil_gettimeofday(&tv_start, NULL); + event_base_dispatch(data->base); + evutil_gettimeofday(&tv_end, NULL); + + evutil_timersub(&tv_end, &tv_start, &tv_end); + + tt_int_op(tv_end.tv_sec, >, 1); + tt_int_op(tv_end.tv_sec, <, 6); + + tt_int_op(test_ok, ==, 1); + + end: + if (evcon) + evhttp_connection_free(evcon); + if (http) + evhttp_free(http); +} + +static void +http_primitives(void *ptr) +{ + char *escaped = NULL; + struct evhttp *http; + + escaped = evhttp_htmlescape("